r509 0.8.1 → 0.9

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 (203) hide show
  1. data/README.md +343 -151
  2. data/Rakefile +26 -23
  3. data/bin/r509 +126 -112
  4. data/bin/r509-parse +24 -24
  5. data/doc/R509.html +169 -7
  6. data/doc/R509/ASN1.html +370 -0
  7. data/doc/R509/ASN1/GeneralName.html +1121 -0
  8. data/doc/R509/ASN1/GeneralNames.html +843 -0
  9. data/doc/R509/ASN1/NoticeReference.html +392 -0
  10. data/doc/R509/ASN1/PolicyInformation.html +387 -0
  11. data/doc/R509/ASN1/PolicyQualifiers.html +455 -0
  12. data/doc/R509/ASN1/UserNotice.html +386 -0
  13. data/doc/R509/{Crl.html → CRL.html} +7 -7
  14. data/doc/R509/CRL/Administrator.html +1559 -0
  15. data/doc/R509/{Crl/Parser.html → CRL/SignedList.html} +501 -210
  16. data/doc/R509/{Csr.html → CSR.html} +444 -314
  17. data/doc/R509/Cert.html +866 -617
  18. data/doc/R509/Cert/Extensions.html +52 -41
  19. data/doc/R509/Cert/Extensions/AuthorityInfoAccess.html +70 -35
  20. data/doc/R509/Cert/Extensions/AuthorityKeyIdentifier.html +387 -4
  21. data/doc/R509/Cert/Extensions/BasicConstraints.html +61 -25
  22. data/doc/R509/Cert/Extensions/CRLDistributionPoints.html +354 -0
  23. data/doc/R509/Cert/Extensions/CertificatePolicies.html +340 -0
  24. data/doc/R509/Cert/Extensions/ExtendedKeyUsage.html +440 -49
  25. data/doc/R509/Cert/Extensions/{CrlDistributionPoints.html → InhibitAnyPolicy.html} +52 -35
  26. data/doc/R509/Cert/Extensions/KeyUsage.html +247 -121
  27. data/doc/R509/Cert/Extensions/NameConstraints.html +445 -0
  28. data/doc/R509/Cert/Extensions/OCSPNoCheck.html +239 -0
  29. data/doc/R509/Cert/Extensions/PolicyConstraints.html +424 -0
  30. data/doc/R509/Cert/Extensions/SubjectAlternativeName.html +437 -62
  31. data/doc/R509/Cert/Extensions/SubjectKeyIdentifier.html +52 -10
  32. data/doc/R509/CertificateAuthority.html +4 -4
  33. data/doc/R509/CertificateAuthority/Signer.html +154 -187
  34. data/doc/R509/Config.html +6 -6
  35. data/doc/R509/Config/{CaConfig.html → CAConfig.html} +451 -348
  36. data/doc/R509/Config/{CaConfigPool.html → CAConfigPool.html} +47 -47
  37. data/doc/R509/Config/CAProfile.html +1015 -0
  38. data/doc/R509/Config/SubjectItemPolicy.html +86 -86
  39. data/doc/R509/IOHelpers.html +22 -22
  40. data/doc/R509/MessageDigest.html +14 -14
  41. data/doc/R509/NameSanitizer.html +53 -53
  42. data/doc/R509/{Ocsp.html → OCSP.html} +9 -9
  43. data/doc/R509/{Ocsp → OCSP}/Request.html +7 -7
  44. data/doc/R509/{Ocsp → OCSP}/Request/Nonce.html +56 -11
  45. data/doc/R509/{Ocsp → OCSP}/Response.html +44 -44
  46. data/doc/R509/{OidMapper.html → OIDMapper.html} +23 -39
  47. data/doc/R509/PrivateKey.html +415 -168
  48. data/doc/R509/R509Error.html +3 -3
  49. data/doc/R509/{Spki.html → SPKI.html} +354 -192
  50. data/doc/R509/Subject.html +224 -113
  51. data/doc/R509/Validity.html +27 -5
  52. data/doc/R509/Validity/Checker.html +13 -13
  53. data/doc/R509/Validity/DefaultChecker.html +13 -13
  54. data/doc/R509/Validity/DefaultWriter.html +14 -14
  55. data/doc/R509/Validity/Status.html +39 -39
  56. data/doc/R509/Validity/Writer.html +18 -18
  57. data/doc/_index.html +138 -35
  58. data/doc/class_list.html +1 -1
  59. data/doc/css/style.css +10 -0
  60. data/doc/file.README.html +368 -171
  61. data/doc/file.r509.html +92 -69
  62. data/doc/frames.html +1 -1
  63. data/doc/index.html +368 -171
  64. data/doc/method_list.html +910 -390
  65. data/doc/top-level-namespace.html +3 -3
  66. data/lib/r509.rb +32 -16
  67. data/lib/r509/asn1.rb +375 -0
  68. data/lib/r509/cert.rb +381 -364
  69. data/lib/r509/cert/extensions.rb +443 -76
  70. data/lib/r509/certificate_authority.rb +407 -0
  71. data/lib/r509/config.rb +547 -351
  72. data/lib/r509/crl.rb +336 -366
  73. data/lib/r509/csr.rb +278 -289
  74. data/lib/r509/ec-hack.rb +37 -0
  75. data/lib/r509/exceptions.rb +3 -3
  76. data/lib/r509/io_helpers.rb +44 -44
  77. data/lib/r509/message_digest.rb +53 -0
  78. data/lib/r509/ocsp.rb +80 -70
  79. data/lib/r509/oid_mapper.rb +32 -0
  80. data/lib/r509/private_key.rb +228 -0
  81. data/lib/r509/spki.rb +145 -93
  82. data/lib/r509/subject.rb +203 -110
  83. data/lib/r509/validity.rb +70 -68
  84. data/lib/r509/version.rb +2 -2
  85. data/r509.yaml +92 -69
  86. data/spec/asn1_spec.rb +402 -0
  87. data/spec/cert/extensions_spec.rb +957 -494
  88. data/spec/cert_spec.rb +382 -307
  89. data/spec/certificate_authority_spec.rb +668 -250
  90. data/spec/config_spec.rb +515 -302
  91. data/spec/crl_spec.rb +197 -198
  92. data/spec/csr_spec.rb +334 -289
  93. data/spec/fixtures.rb +247 -171
  94. data/spec/fixtures/cert1.der +0 -0
  95. data/spec/fixtures/cert1.pem +0 -0
  96. data/spec/fixtures/cert1_public_key_modulus.txt +0 -0
  97. data/spec/fixtures/cert3.p12 +0 -0
  98. data/spec/fixtures/cert3.pem +0 -0
  99. data/spec/fixtures/cert3_key.pem +0 -0
  100. data/spec/fixtures/cert3_key_des3.pem +0 -0
  101. data/spec/fixtures/cert4.pem +0 -0
  102. data/spec/fixtures/cert5.pem +0 -0
  103. data/spec/fixtures/cert6.pem +0 -0
  104. data/spec/fixtures/cert_expired.pem +0 -0
  105. data/spec/fixtures/cert_inhibit.pem +24 -0
  106. data/spec/fixtures/cert_name_constraints.pem +29 -0
  107. data/spec/fixtures/cert_not_yet_valid.pem +0 -0
  108. data/spec/fixtures/cert_ocsp_no_check.pem +18 -0
  109. data/spec/fixtures/cert_policy_constraints.pem +31 -0
  110. data/spec/fixtures/cert_san.pem +0 -0
  111. data/spec/fixtures/cert_san2.pem +0 -0
  112. data/spec/fixtures/cert_unknown_extension.pem +28 -0
  113. data/spec/fixtures/config_pool_test_minimal.yaml +11 -11
  114. data/spec/fixtures/config_test.yaml +54 -36
  115. data/spec/fixtures/config_test_dsa.yaml +35 -0
  116. data/spec/fixtures/config_test_ec.yaml +35 -0
  117. data/spec/fixtures/config_test_engine_key.yaml +5 -5
  118. data/spec/fixtures/config_test_engine_no_key_name.yaml +4 -4
  119. data/spec/fixtures/config_test_minimal.yaml +4 -4
  120. data/spec/fixtures/config_test_password.yaml +5 -5
  121. data/spec/fixtures/config_test_various.yaml +111 -74
  122. data/spec/fixtures/crl_list_file.txt +0 -0
  123. data/spec/fixtures/crl_with_reason.pem +0 -0
  124. data/spec/fixtures/csr1.der +0 -0
  125. data/spec/fixtures/csr1.pem +0 -0
  126. data/spec/fixtures/csr1_key.der +0 -0
  127. data/spec/fixtures/csr1_key.pem +0 -0
  128. data/spec/fixtures/csr1_key_encrypted_des3.pem +0 -0
  129. data/spec/fixtures/csr1_newlines.pem +0 -0
  130. data/spec/fixtures/csr1_no_begin_end.pem +0 -0
  131. data/spec/fixtures/csr1_public_key_modulus.txt +0 -0
  132. data/spec/fixtures/csr2.pem +0 -0
  133. data/spec/fixtures/csr2_key.pem +0 -0
  134. data/spec/fixtures/csr3.pem +0 -0
  135. data/spec/fixtures/csr4.pem +0 -0
  136. data/spec/fixtures/csr_dsa.pem +0 -0
  137. data/spec/fixtures/csr_invalid_signature.pem +0 -0
  138. data/spec/fixtures/dsa_key.pem +0 -0
  139. data/spec/fixtures/dsa_root.cer +28 -0
  140. data/spec/fixtures/dsa_root.key +20 -0
  141. data/spec/fixtures/ec_csr2.der +0 -0
  142. data/spec/fixtures/ec_csr2.pem +8 -0
  143. data/spec/fixtures/ec_key1.der +0 -0
  144. data/spec/fixtures/ec_key1.pem +6 -0
  145. data/spec/fixtures/ec_key1_encrypted.pem +9 -0
  146. data/spec/fixtures/ec_key2.pem +6 -0
  147. data/spec/fixtures/hmacsha1.sig +1 -0
  148. data/spec/fixtures/hmacsha512.sig +1 -0
  149. data/spec/fixtures/key4.pem +0 -0
  150. data/spec/fixtures/key4_encrypted_des3.pem +0 -0
  151. data/spec/fixtures/missing_key_identifier_ca.cer +0 -0
  152. data/spec/fixtures/missing_key_identifier_ca.key +0 -0
  153. data/spec/fixtures/ocsptest.r509.local.pem +0 -0
  154. data/spec/fixtures/ocsptest.r509.local_ocsp_request.der +0 -0
  155. data/spec/fixtures/ocsptest2.r509.local.pem +0 -0
  156. data/spec/fixtures/second_ca.cer +0 -0
  157. data/spec/fixtures/second_ca.key +0 -0
  158. data/spec/fixtures/spkac.der +0 -0
  159. data/spec/fixtures/spkac.txt +0 -0
  160. data/spec/fixtures/spkac_dsa.txt +1 -1
  161. data/spec/fixtures/spkac_dsa_no_verify.txt +1 -0
  162. data/spec/fixtures/spkac_ec.txt +1 -0
  163. data/spec/fixtures/spkac_rsa_newlines.txt +13 -0
  164. data/spec/fixtures/stca.pem +0 -0
  165. data/spec/fixtures/stca_ocsp_request.der +0 -0
  166. data/spec/fixtures/stca_ocsp_response.der +0 -0
  167. data/spec/fixtures/test1.csr +0 -0
  168. data/spec/fixtures/test_ca.cer +0 -0
  169. data/spec/fixtures/test_ca.key +0 -0
  170. data/spec/fixtures/test_ca.p12 +0 -0
  171. data/spec/fixtures/test_ca_des3.key +0 -0
  172. data/spec/fixtures/test_ca_ec.cer +14 -0
  173. data/spec/fixtures/test_ca_ec.key +6 -0
  174. data/spec/fixtures/test_ca_ec_ee.cer +22 -0
  175. data/spec/fixtures/test_ca_ec_ee.key +6 -0
  176. data/spec/fixtures/test_ca_ocsp.cer +0 -0
  177. data/spec/fixtures/test_ca_ocsp.key +0 -0
  178. data/spec/fixtures/test_ca_ocsp.p12 +0 -0
  179. data/spec/fixtures/test_ca_ocsp_chain.txt +0 -0
  180. data/spec/fixtures/test_ca_ocsp_response.der +0 -0
  181. data/spec/fixtures/test_ca_subroot.cer +0 -0
  182. data/spec/fixtures/test_ca_subroot.key +0 -0
  183. data/spec/fixtures/test_ca_subroot_ocsp.cer +0 -0
  184. data/spec/fixtures/test_ca_subroot_ocsp.key +0 -0
  185. data/spec/fixtures/test_ca_subroot_ocsp_response.der +0 -0
  186. data/spec/fixtures/unknown_oid.csr +0 -0
  187. data/spec/message_digest_spec.rb +104 -84
  188. data/spec/ocsp_spec.rb +105 -105
  189. data/spec/oid_mapper_spec.rb +21 -21
  190. data/spec/private_key_spec.rb +275 -0
  191. data/spec/r509_spec.rb +35 -0
  192. data/spec/spec_helper.rb +15 -6
  193. data/spec/spki_spec.rb +221 -142
  194. data/spec/subject_spec.rb +232 -164
  195. data/spec/validity_spec.rb +91 -91
  196. metadata +79 -25
  197. data/doc/R509/Config/CaProfile.html +0 -651
  198. data/doc/R509/Crl/Administrator.html +0 -2073
  199. data/lib/r509/certificateauthority.rb +0 -290
  200. data/lib/r509/messagedigest.rb +0 -49
  201. data/lib/r509/oidmapper.rb +0 -32
  202. data/lib/r509/privatekey.rb +0 -185
  203. data/spec/privatekey_spec.rb +0 -198
data/spec/ocsp_spec.rb CHANGED
@@ -2,110 +2,110 @@ require 'spec_helper'
2
2
  require 'r509/ocsp'
3
3
  require 'openssl'
4
4
 
5
- describe R509::Ocsp::Response do
6
- before :all do
7
- @ocsp_test_cert = TestFixtures::OCSP_TEST_CERT
8
- @test_ca_config = TestFixtures.test_ca_config
9
- @test_ca_ocsp_response = TestFixtures::TEST_CA_OCSP_RESPONSE
10
- @test_ca_subroot_ocsp_response = TestFixtures::TEST_CA_SUBROOT_OCSP_RESPONSE
11
- @ocsp_response_der = TestFixtures::STCA_OCSP_RESPONSE
12
- @stca_cert = TestFixtures::STCA_CERT
13
- end
14
- it "raises an exception if you try to pass the wrong type to the constructor" do
15
- expect { R509::Ocsp::Response.new(@ocsp_response_der) }.to raise_error(R509::R509Error, 'You must pass an OpenSSL::OCSP::Response object to the constructor. See R509::Ocsp::Response.parse if you are trying to parse')
16
- end
17
- it "raises an exception if you pass nil to #parse" do
18
- expect { R509::Ocsp::Response.parse(nil) }.to raise_error(R509::R509Error, 'You must pass a DER encoded OCSP response to this method')
19
- end
20
- it "parses a response der and returns the right object on #parse" do
21
- ocsp_response = R509::Ocsp::Response.parse(@ocsp_response_der)
22
- ocsp_response.kind_of?(R509::Ocsp::Response).should == true
23
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
24
- end
25
- it "returns data on to_der" do
26
- ocsp_response = R509::Ocsp::Response.parse(@ocsp_response_der)
27
- ocsp_response.to_der.should_not == nil
28
- end
29
- it "returns a BasicResponse object on #basic" do
30
- ocsp_response = R509::Ocsp::Response.parse(@ocsp_response_der)
31
- ocsp_response.basic.kind_of?(OpenSSL::OCSP::BasicResponse).should == true
32
- end
33
- it "returns true if response verifies (in validity period, chain builds to trusted root that's provided)" do
34
- ocsp_response = R509::Ocsp::Response.parse(@test_ca_ocsp_response)
35
- ocsp_response.verify(TestFixtures.test_ca_config.ca_cert.cert).should == true
36
- end
37
- it "verify supports an single certificate and uses it to validate" do
38
- ocsp_response = R509::Ocsp::Response.parse(@test_ca_ocsp_response)
39
- ocsp_response.verify(TestFixtures.test_ca_config.ca_cert.cert).should == true
40
- end
41
- it "verify supports an array of certificates and uses all of them to validate a chain" do
42
- ocsp_response = R509::Ocsp::Response.parse(@test_ca_subroot_ocsp_response)
43
- ocsp_response.verify([TestFixtures.test_ca_config.ca_cert.cert,TestFixtures.test_ca_subroot_cert.cert]).should == true
44
- end
45
- it "verify returns false if you don't give it enough certs to build a chain to a trusted root" do
46
- ocsp_response = R509::Ocsp::Response.parse(@test_ca_subroot_ocsp_response)
47
- ocsp_response.verify([TestFixtures.test_ca_config.ca_cert.cert]).should == false
48
- end
49
- it "returns false if response does not verify" do
50
- #expired response
51
- ocsp_response = R509::Ocsp::Response.parse(@ocsp_response_der)
52
- ocsp_response.verify(OpenSSL::X509::Certificate.new(@stca_cert)).should == false
53
- end
54
- it "nonce is present and equal" do
55
- ocsp_request = OpenSSL::OCSP::Request.new
56
- ocsp_request.add_nonce
57
- basic_response = OpenSSL::OCSP::BasicResponse.new
58
- basic_response.copy_nonce(ocsp_request)
59
- response_double = double("ocsp_response")
60
- response_double.should_receive(:kind_of?).and_return('OpenSSL::OCSP::Response')
61
- response_double.should_receive(:basic).and_return(basic_response)
62
- ocsp_response = R509::Ocsp::Response.new(response_double)
63
- ocsp_response.check_nonce(ocsp_request).should == R509::Ocsp::Request::Nonce::PRESENT_AND_EQUAL
64
- end
65
- it "no nonce" do
66
- ocsp_request = OpenSSL::OCSP::Request.new
67
- basic_response = OpenSSL::OCSP::BasicResponse.new
68
- basic_response.copy_nonce(ocsp_request)
69
- response_double = double("ocsp_response")
70
- response_double.should_receive(:kind_of?).and_return('OpenSSL::OCSP::Response')
71
- response_double.should_receive(:basic).and_return(basic_response)
72
- ocsp_response = R509::Ocsp::Response.new(response_double)
73
- ocsp_response.check_nonce(ocsp_request).should == R509::Ocsp::Request::Nonce::BOTH_ABSENT
74
- end
75
- it "has a nonce in the response only" do
76
- ocsp_request = OpenSSL::OCSP::Request.new
77
- nonce_request = OpenSSL::OCSP::Request.new
78
- nonce_request.add_nonce
79
- basic_response = OpenSSL::OCSP::BasicResponse.new
80
- basic_response.copy_nonce(nonce_request)
81
- response_double = double("ocsp_response")
82
- response_double.should_receive(:kind_of?).and_return('OpenSSL::OCSP::Response')
83
- response_double.should_receive(:basic).and_return(basic_response)
84
- ocsp_response = R509::Ocsp::Response.new(response_double)
85
- ocsp_response.check_nonce(ocsp_request).should == R509::Ocsp::Request::Nonce::RESPONSE_ONLY
86
- end
87
- it "nonce in request and response is not equal" do
88
- ocsp_request = OpenSSL::OCSP::Request.new
89
- ocsp_request.add_nonce
90
- second_request = OpenSSL::OCSP::Request.new
91
- second_request.add_nonce
92
- basic_response = OpenSSL::OCSP::BasicResponse.new
93
- basic_response.copy_nonce(ocsp_request)
94
- response_double = double("ocsp_response")
95
- response_double.should_receive(:kind_of?).and_return('OpenSSL::OCSP::Response')
96
- response_double.should_receive(:basic).and_return(basic_response)
97
- ocsp_response = R509::Ocsp::Response.new(response_double)
98
- ocsp_response.check_nonce(second_request).should == R509::Ocsp::Request::Nonce::NOT_EQUAL
99
- end
100
- it "nonce in request only" do
101
- ocsp_request = OpenSSL::OCSP::Request.new
102
- ocsp_request.add_nonce
103
- basic_response = OpenSSL::OCSP::BasicResponse.new
104
- response_double = double("ocsp_response")
105
- response_double.should_receive(:kind_of?).and_return('OpenSSL::OCSP::Response')
106
- response_double.should_receive(:basic).and_return(basic_response)
107
- ocsp_response = R509::Ocsp::Response.new(response_double)
108
- ocsp_response.check_nonce(ocsp_request).should == R509::Ocsp::Request::Nonce::REQUEST_ONLY
109
- end
5
+ describe R509::OCSP::Response do
6
+ before :all do
7
+ @ocsp_test_cert = TestFixtures::OCSP_TEST_CERT
8
+ @test_ca_config = TestFixtures.test_ca_config
9
+ @test_ca_ocsp_response = TestFixtures::TEST_CA_OCSP_RESPONSE
10
+ @test_ca_subroot_ocsp_response = TestFixtures::TEST_CA_SUBROOT_OCSP_RESPONSE
11
+ @ocsp_response_der = TestFixtures::STCA_OCSP_RESPONSE
12
+ @stca_cert = TestFixtures::STCA_CERT
13
+ end
14
+ it "raises an exception if you try to pass the wrong type to the constructor" do
15
+ expect { R509::OCSP::Response.new(@ocsp_response_der) }.to raise_error(R509::R509Error, 'You must pass an OpenSSL::OCSP::Response object to the constructor. See R509::OCSP::Response.parse if you are trying to parse')
16
+ end
17
+ it "raises an exception if you pass nil to #parse" do
18
+ expect { R509::OCSP::Response.parse(nil) }.to raise_error(R509::R509Error, 'You must pass a DER encoded OCSP response to this method')
19
+ end
20
+ it "parses a response der and returns the right object on #parse" do
21
+ ocsp_response = R509::OCSP::Response.parse(@ocsp_response_der)
22
+ ocsp_response.kind_of?(R509::OCSP::Response).should == true
23
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
24
+ end
25
+ it "returns data on to_der" do
26
+ ocsp_response = R509::OCSP::Response.parse(@ocsp_response_der)
27
+ ocsp_response.to_der.should_not == nil
28
+ end
29
+ it "returns a BasicResponse object on #basic" do
30
+ ocsp_response = R509::OCSP::Response.parse(@ocsp_response_der)
31
+ ocsp_response.basic.kind_of?(OpenSSL::OCSP::BasicResponse).should == true
32
+ end
33
+ it "returns true if response verifies (in validity period, chain builds to trusted root that's provided)" do
34
+ ocsp_response = R509::OCSP::Response.parse(@test_ca_ocsp_response)
35
+ ocsp_response.verify(TestFixtures.test_ca_config.ca_cert.cert).should == true
36
+ end
37
+ it "verify supports an single certificate and uses it to validate" do
38
+ ocsp_response = R509::OCSP::Response.parse(@test_ca_ocsp_response)
39
+ ocsp_response.verify(TestFixtures.test_ca_config.ca_cert.cert).should == true
40
+ end
41
+ it "verify supports an array of certificates and uses all of them to validate a chain" do
42
+ ocsp_response = R509::OCSP::Response.parse(@test_ca_subroot_ocsp_response)
43
+ ocsp_response.verify([TestFixtures.test_ca_config.ca_cert.cert,TestFixtures.test_ca_subroot_cert.cert]).should == true
44
+ end
45
+ it "verify returns false if you don't give it enough certs to build a chain to a trusted root" do
46
+ ocsp_response = R509::OCSP::Response.parse(@test_ca_subroot_ocsp_response)
47
+ ocsp_response.verify([TestFixtures.test_ca_config.ca_cert.cert]).should == false
48
+ end
49
+ it "returns false if response does not verify" do
50
+ #expired response
51
+ ocsp_response = R509::OCSP::Response.parse(@ocsp_response_der)
52
+ ocsp_response.verify(OpenSSL::X509::Certificate.new(@stca_cert)).should == false
53
+ end
54
+ it "nonce is present and equal" do
55
+ ocsp_request = OpenSSL::OCSP::Request.new
56
+ ocsp_request.add_nonce
57
+ basic_response = OpenSSL::OCSP::BasicResponse.new
58
+ basic_response.copy_nonce(ocsp_request)
59
+ response_double = double("ocsp_response")
60
+ response_double.should_receive(:kind_of?).and_return('OpenSSL::OCSP::Response')
61
+ response_double.should_receive(:basic).and_return(basic_response)
62
+ ocsp_response = R509::OCSP::Response.new(response_double)
63
+ ocsp_response.check_nonce(ocsp_request).should == R509::OCSP::Request::Nonce::PRESENT_AND_EQUAL
64
+ end
65
+ it "no nonce" do
66
+ ocsp_request = OpenSSL::OCSP::Request.new
67
+ basic_response = OpenSSL::OCSP::BasicResponse.new
68
+ basic_response.copy_nonce(ocsp_request)
69
+ response_double = double("ocsp_response")
70
+ response_double.should_receive(:kind_of?).and_return('OpenSSL::OCSP::Response')
71
+ response_double.should_receive(:basic).and_return(basic_response)
72
+ ocsp_response = R509::OCSP::Response.new(response_double)
73
+ ocsp_response.check_nonce(ocsp_request).should == R509::OCSP::Request::Nonce::BOTH_ABSENT
74
+ end
75
+ it "has a nonce in the response only" do
76
+ ocsp_request = OpenSSL::OCSP::Request.new
77
+ nonce_request = OpenSSL::OCSP::Request.new
78
+ nonce_request.add_nonce
79
+ basic_response = OpenSSL::OCSP::BasicResponse.new
80
+ basic_response.copy_nonce(nonce_request)
81
+ response_double = double("ocsp_response")
82
+ response_double.should_receive(:kind_of?).and_return('OpenSSL::OCSP::Response')
83
+ response_double.should_receive(:basic).and_return(basic_response)
84
+ ocsp_response = R509::OCSP::Response.new(response_double)
85
+ ocsp_response.check_nonce(ocsp_request).should == R509::OCSP::Request::Nonce::RESPONSE_ONLY
86
+ end
87
+ it "nonce in request and response is not equal" do
88
+ ocsp_request = OpenSSL::OCSP::Request.new
89
+ ocsp_request.add_nonce
90
+ second_request = OpenSSL::OCSP::Request.new
91
+ second_request.add_nonce
92
+ basic_response = OpenSSL::OCSP::BasicResponse.new
93
+ basic_response.copy_nonce(ocsp_request)
94
+ response_double = double("ocsp_response")
95
+ response_double.should_receive(:kind_of?).and_return('OpenSSL::OCSP::Response')
96
+ response_double.should_receive(:basic).and_return(basic_response)
97
+ ocsp_response = R509::OCSP::Response.new(response_double)
98
+ ocsp_response.check_nonce(second_request).should == R509::OCSP::Request::Nonce::NOT_EQUAL
99
+ end
100
+ it "nonce in request only" do
101
+ ocsp_request = OpenSSL::OCSP::Request.new
102
+ ocsp_request.add_nonce
103
+ basic_response = OpenSSL::OCSP::BasicResponse.new
104
+ response_double = double("ocsp_response")
105
+ response_double.should_receive(:kind_of?).and_return('OpenSSL::OCSP::Response')
106
+ response_double.should_receive(:basic).and_return(basic_response)
107
+ ocsp_response = R509::OCSP::Response.new(response_double)
108
+ ocsp_response.check_nonce(ocsp_request).should == R509::OCSP::Request::Nonce::REQUEST_ONLY
109
+ end
110
110
 
111
111
  end
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
- require 'r509/oidmapper'
2
+ require 'r509/oid_mapper'
3
3
 
4
4
 
5
5
  # NOTE
@@ -7,25 +7,25 @@ require 'r509/oidmapper'
7
7
  # each test. Accordingly, we MUST use OIDs (and short names) here that will not
8
8
  # be present in any other tests (or in the real world)
9
9
 
10
- describe R509::OidMapper do
11
- it "registers one new oid" do
12
- subject = R509::Subject.new [['1.4.3.2.1.2.3.5.5.5.5.5','random_oid']]
13
- subject['1.4.3.2.1.2.3.5.5.5.5.5'].should == 'random_oid'
14
- expect { R509::Subject.new [['myOidName','random_oid']] }.to raise_error(OpenSSL::X509::NameError,'invalid field name')
10
+ describe R509::OIDMapper do
11
+ it "registers one new oid" do
12
+ subject = R509::Subject.new [['1.4.3.2.1.2.3.5.5.5.5.5','random_oid']]
13
+ subject['1.4.3.2.1.2.3.5.5.5.5.5'].should == 'random_oid'
14
+ expect { R509::Subject.new [['myOIDName','random_oid']] }.to raise_error(OpenSSL::X509::NameError,'invalid field name')
15
15
 
16
- R509::OidMapper.register('1.4.3.2.1.2.3.5.5.5.5.5','myOidName').should == true
17
- subject_new = R509::Subject.new [['myOidName','random_oid']]
18
- subject_new['myOidName'].should == 'random_oid'
19
- end
20
- it "registers a batch of new oids" do
21
- expect { R509::Subject.new [['testOidName','random_oid']] }.to raise_error(OpenSSL::X509::NameError,'invalid field name')
22
- expect { R509::Subject.new [['anotherOidName','second_random']] }.to raise_error(OpenSSL::X509::NameError,'invalid field name')
23
- R509::OidMapper.batch_register([
24
- {:oid => '1.4.3.2.1.2.3.4.4.4.4', :short_name => 'testOidName'},
25
- {:oid => '1.4.3.2.1.2.5.4.4.4.4', :short_name => 'anotherOidName'}
26
- ])
27
- subject_new = R509::Subject.new [['testOidName','random_oid'],['anotherOidName','second_random']]
28
- subject_new['testOidName'].should == 'random_oid'
29
- subject_new['anotherOidName'].should == 'second_random'
30
- end
16
+ R509::OIDMapper.register('1.4.3.2.1.2.3.5.5.5.5.5','myOIDName').should == true
17
+ subject_new = R509::Subject.new [['myOIDName','random_oid']]
18
+ subject_new['myOIDName'].should == 'random_oid'
19
+ end
20
+ it "registers a batch of new oids" do
21
+ expect { R509::Subject.new [['testOIDName','random_oid']] }.to raise_error(OpenSSL::X509::NameError,'invalid field name')
22
+ expect { R509::Subject.new [['anotherOIDName','second_random']] }.to raise_error(OpenSSL::X509::NameError,'invalid field name')
23
+ R509::OIDMapper.batch_register([
24
+ {:oid => '1.4.3.2.1.2.3.4.4.4.4', :short_name => 'testOIDName'},
25
+ {:oid => '1.4.3.2.1.2.5.4.4.4.4', :short_name => 'anotherOIDName'}
26
+ ])
27
+ subject_new = R509::Subject.new [['testOIDName','random_oid'],['anotherOIDName','second_random']]
28
+ subject_new['testOIDName'].should == 'random_oid'
29
+ subject_new['anotherOIDName'].should == 'second_random'
30
+ end
31
31
  end
@@ -0,0 +1,275 @@
1
+ require 'spec_helper'
2
+ require 'r509/private_key'
3
+ require 'stringio'
4
+
5
+ describe R509::PrivateKey do
6
+ before :all do
7
+ @key_csr = TestFixtures::KEY_CSR
8
+ @key_csr_encrypted = TestFixtures::KEY_CSR_ENCRYPTED
9
+ @csr_public_key_modulus = TestFixtures::CSR_PUBLIC_KEY_MODULUS
10
+ @key_csr_der = TestFixtures::KEY_CSR_DER
11
+ @dsa_key = TestFixtures::DSA_KEY
12
+ @ec_key_pem = TestFixtures::EC_KEY1
13
+ @ec_key_der = TestFixtures::EC_KEY1_DER
14
+ @ec_key_encrypted = TestFixtures::EC_KEY1_ENCRYPTED
15
+ end
16
+ it "throws an exception when given a type other than DSA, RSA, or EC" do
17
+ expect { R509::PrivateKey.new(:type=>:not_rsa_or_dsa) }.to raise_error(ArgumentError)
18
+ end
19
+ it "throws an exception when no hash is provided" do
20
+ expect { R509::PrivateKey.new('string') }.to raise_error(ArgumentError,'Must provide a hash of options')
21
+ end
22
+ it "returns the right value for #rsa?" do
23
+ private_key = R509::PrivateKey.new(:key=>@key_csr)
24
+ private_key.dsa?.should == false
25
+ private_key.ec?.should == false
26
+ private_key.rsa?.should == true
27
+ end
28
+ it "returns the right value for #dsa?" do
29
+ private_key = R509::PrivateKey.new(:key => @dsa_key)
30
+ private_key.rsa?.should == false
31
+ private_key.ec?.should == false
32
+ private_key.dsa?.should == true
33
+ end
34
+ it "generates a default 2048-bit RSA key when nothing is passed to the constructor" do
35
+ private_key = R509::PrivateKey.new
36
+ private_key.rsa?.should == true
37
+ private_key.bit_strength.should == 2048
38
+ end
39
+ it "defaults to RSA" do
40
+ private_key = R509::PrivateKey.new(:bit_strength=>1024)
41
+ private_key.key.kind_of?(OpenSSL::PKey::RSA).should == true
42
+ end
43
+ it "loads a pre-existing RSA key" do
44
+ private_key = R509::PrivateKey.new(:key=>@key_csr)
45
+ private_key.to_pem.should == @key_csr
46
+ @key_csr.should_not == nil
47
+ end
48
+ it "generates an RSA key at the default bit strength (2048)" do
49
+ private_key = R509::PrivateKey.new(:type => :rsa)
50
+ private_key.bit_strength.should == 2048
51
+ private_key.key.n.to_i.to_s(2).size.should == 2048
52
+ end
53
+ it "generates an RSA key at a custom bit strength" do
54
+ private_key = R509::PrivateKey.new(:type => :rsa, :bit_strength => 512)
55
+ private_key.bit_strength.should == 512
56
+ private_key.key.n.to_i.to_s(2).size.should == 512
57
+ end
58
+ it "loads a pre-existing DSA key" do
59
+ private_key = R509::PrivateKey.new(:key => @dsa_key)
60
+ private_key.key.kind_of?(OpenSSL::PKey::DSA).should == true
61
+ private_key.key.to_pem.should == @dsa_key
62
+ @dsa_key.should_not == nil
63
+ end
64
+ it "generates a DSA key at the default bit strength (2048)" do
65
+ private_key = R509::PrivateKey.new(:type => :dsa)
66
+ private_key.dsa?.should == true
67
+ private_key.bit_strength.should == 2048
68
+ private_key.key.p.to_i.to_s(2).size.should == 2048
69
+ end
70
+ it "generates a DSA key at a custom bit strength" do
71
+ private_key = R509::PrivateKey.new(:type => :dsa, :bit_strength => 512)
72
+ private_key.bit_strength.should == 512
73
+ private_key.key.p.to_i.to_s(2).size.should == 512
74
+ end
75
+ it "has an exponent of 65537 for new RSA keys" do
76
+ #this test actually checks ruby's underlying libs to make sure they're
77
+ #doing what they're supposed to be doing.
78
+ private_key = R509::PrivateKey.new(:type => :rsa, :bit_strength => 512)
79
+ private_key.key.e.should == 65537
80
+ end
81
+ it "returns the public key" do
82
+ private_key = R509::PrivateKey.new(:key => @key_csr)
83
+ private_key.public_key.n.to_i.should == @csr_public_key_modulus.to_i
84
+ end
85
+ it "returns pem" do
86
+ #load the DER, check that it matches the PEM on to_pem
87
+ private_key = R509::PrivateKey.new(:key => @key_csr_der)
88
+ private_key.to_pem.should == @key_csr
89
+ end
90
+ it "returns der" do
91
+ #load the PEM, check that it matches the DER on to_der
92
+ private_key = R509::PrivateKey.new(:key => @key_csr)
93
+ private_key.to_der.should == @key_csr_der
94
+ end
95
+ it "writes pem" do
96
+ private_key = R509::PrivateKey.new(:key => @key_csr)
97
+ sio = StringIO.new
98
+ sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
99
+ private_key.write_pem(sio)
100
+ sio.string.should == @key_csr
101
+ end
102
+ it "writes der" do
103
+ private_key = R509::PrivateKey.new(:key => @key_csr_der)
104
+ sio = StringIO.new
105
+ sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
106
+ private_key.write_der(sio)
107
+ sio.string.should == @key_csr_der
108
+ end
109
+ it "loads an encrypted private key with the right password" do
110
+ private_key = R509::PrivateKey.new(:key => @key_csr_encrypted, :password => 'Testing1')
111
+ private_key.public_key.n.to_i.should == @csr_public_key_modulus.to_i
112
+ end
113
+ it "fails to load an encrypted private key with wrong password" do
114
+ expect { R509::PrivateKey.new(:key => @key_csr_encrypted, :password => 'wrongPassword') }.to raise_error(R509::R509Error,"Failed to load private key. Invalid key or incorrect password.")
115
+ end
116
+ it "returns an encrypted pem" do
117
+ private_key = R509::PrivateKey.new(:key => @key_csr)
118
+ encrypted_private_key = private_key.to_encrypted_pem('des3','Testing1')
119
+ decrypted_private_key = R509::PrivateKey.new(:key => encrypted_private_key, :password => 'Testing1')
120
+ private_key.to_pem.should == decrypted_private_key.to_pem
121
+ end
122
+ it "writes an encrypted pem" do
123
+ private_key = R509::PrivateKey.new(:key => @key_csr)
124
+ sio = StringIO.new
125
+ sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
126
+ private_key.write_encrypted_pem(sio,'des3','Testing1')
127
+ sio.string.match(/Proc-Type: 4,ENCRYPTED/).should_not == nil
128
+ end
129
+ it "creates an encrypted private key with des3 cipher" do
130
+ private_key = R509::PrivateKey.new(:key => @key_csr)
131
+ sio = StringIO.new
132
+ sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
133
+ private_key.write_encrypted_pem(sio,'des3','Testing1')
134
+ sio.string.match(/DES-EDE3-CBC/).should_not == nil
135
+ end
136
+ it "creates an encrypted private key with aes128 cipher" do
137
+ private_key = R509::PrivateKey.new(:key => @key_csr)
138
+ sio = StringIO.new
139
+ sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
140
+ private_key.write_encrypted_pem(sio,'aes128','Testing1')
141
+ sio.string.match(/AES-128-CBC/).should_not == nil
142
+ end
143
+ it "returns false for in_hardware? when not using an engine" do
144
+ private_key = R509::PrivateKey.new(:key => @key_csr)
145
+ private_key.in_hardware?.should == false
146
+ end
147
+ it "returns true for in_hardware? when an engine is present" do
148
+ engine = double("engine")
149
+ engine.should_receive(:kind_of?).with(OpenSSL::Engine).and_return(true)
150
+ key_name = "r509_key"
151
+ key = R509::PrivateKey.new(
152
+ :engine => engine,
153
+ :key_name => key_name
154
+ )
155
+ key.in_hardware?.should == true
156
+ end
157
+ it "raises an error if you provide engine and key" do
158
+ expect { R509::PrivateKey.new(:key => @key_csr, :engine => 'not really an engine') }.to raise_error(ArgumentError, "You can't pass both :key and :engine")
159
+ end
160
+ it "raises an error if you provide a key_name with no engine" do
161
+ expect { R509::PrivateKey.new(:key_name => 'my_key') }.to raise_error(ArgumentError, 'When providing a :key_name you MUST provide an :engine')
162
+ end
163
+ it "raises an error when providing an engine with no key_name" do
164
+ expect { R509::PrivateKey.new(:engine => 'engine_goes_here') }.to raise_error(ArgumentError, 'When providing an :engine you MUST provide a :key_name')
165
+ end
166
+ it "raises an error if engine is not an OpenSSL::Engine" do
167
+ expect { R509::PrivateKey.new(:key_name => 'my_key', :engine => 'not really an engine') }.to raise_error(ArgumentError, 'When providing an engine, it must be of type OpenSSL::Engine')
168
+ end
169
+ it "raises an error if you call output methods (pem,der,write) when using a hardware key" do
170
+ engine = double("engine")
171
+ engine.should_receive(:kind_of?).with(OpenSSL::Engine).and_return(true)
172
+ key_name = "r509_key"
173
+ key = R509::PrivateKey.new(
174
+ :engine => engine,
175
+ :key_name => key_name
176
+ )
177
+ expect { key.to_pem }.to raise_error(R509::R509Error, "This method cannot be called when using keys in hardware")
178
+ expect { key.to_der }.to raise_error(R509::R509Error, "This method cannot be called when using keys in hardware")
179
+ expect { key.to_encrypted_pem('aes256','password') }.to raise_error(R509::R509Error, "This method cannot be called when using keys in hardware")
180
+ expect { key.write_encrypted_pem('/dev/null','aes256','password') }.to raise_error(R509::R509Error, "This method cannot be called when using keys in hardware")
181
+ expect { key.write_der('/dev/null') }.to raise_error(R509::R509Error, "This method cannot be called when using keys in hardware")
182
+ end
183
+ it "loads a hardware key successfully" do
184
+ engine = double("engine")
185
+ engine.should_receive(:kind_of?).with(OpenSSL::Engine).and_return(true)
186
+ faux_key = double("faux_key")
187
+ faux_key.should_receive(:public_key).and_return("returning public key")
188
+ key_name = "r509_key"
189
+ engine.should_receive(:load_private_key).twice.with(key_name).and_return(faux_key)
190
+ key = R509::PrivateKey.new(
191
+ :engine => engine,
192
+ :key_name => key_name
193
+ )
194
+ key.kind_of?(R509::PrivateKey).should == true
195
+ key.public_key.should == "returning public key"
196
+ end
197
+ it "loads a private key with load_from_file" do
198
+ path = File.dirname(__FILE__) + '/fixtures/key4.pem'
199
+ key = R509::PrivateKey.load_from_file path
200
+ key.rsa?.should == true
201
+ end
202
+ it "loads a private key with load_from_file with password" do
203
+ path = File.dirname(__FILE__) + '/fixtures/key4_encrypted_des3.pem'
204
+ key = R509::PrivateKey.load_from_file( path, 'r509')
205
+ key.rsa?.should == true
206
+ end
207
+
208
+ it "returns an error for curve_name for dsa/rsa" do
209
+ private_key = R509::PrivateKey.new(:key => @key_csr)
210
+ expect { private_key.curve_name }.to raise_error(R509::R509Error, 'Curve name is only available with EC private keys')
211
+ end
212
+
213
+ context "elliptic curves", :ec => true do
214
+ it "loads a pre-existing EC key" do
215
+ private_key = R509::PrivateKey.new(:key => @ec_key_pem)
216
+ private_key.to_pem.should == @ec_key_pem
217
+ @ec_key_pem.should_not be_nil
218
+ end
219
+
220
+ it "loads an encrypted private key with the right password" do
221
+ private_key = R509::PrivateKey.new(:key => @ec_key_encrypted, :password => 'Testing1')
222
+ private_key.to_pem.should == @ec_key_pem
223
+ @ec_key_encrypted.should_not be_nil
224
+ @ec_key_pem.should_not be_nil
225
+ end
226
+
227
+ it "returns the right value for #ec?" do
228
+ path = File.dirname(__FILE__) + '/fixtures/ec_key1.der'
229
+ private_key = R509::PrivateKey.load_from_file path
230
+ private_key.rsa?.should == false
231
+ private_key.dsa?.should == false
232
+ private_key.ec?.should == true
233
+ end
234
+
235
+ it "returns the curve_name" do
236
+ private_key = R509::PrivateKey.new(:key => @ec_key_pem)
237
+ private_key.curve_name.should == 'secp384r1'
238
+ end
239
+
240
+ it "generates an elliptic curve key using the default curve (secp384r1)" do
241
+ private_key = R509::PrivateKey.new(:type => :ec)
242
+ private_key.curve_name.should == 'secp384r1'
243
+ end
244
+
245
+ it "generates an elliptic curve key using a specified curve" do
246
+ private_key = R509::PrivateKey.new(:type => :ec, :curve_name => 'sect283r1')
247
+ private_key.curve_name.should == 'sect283r1'
248
+ end
249
+
250
+ it "returns the public key" do
251
+ private_key = R509::PrivateKey.new(:key => @ec_key_pem)
252
+ public_key = private_key.public_key
253
+ public_key.public_key?.should == true
254
+ public_key.private_key?.should == false
255
+ end
256
+
257
+ it "returns the pem" do
258
+ private_key = R509::PrivateKey.new(:key => @ec_key_pem)
259
+ private_key.to_pem.should == @ec_key_pem
260
+ end
261
+
262
+ it "returns the der" do
263
+ private_key = R509::PrivateKey.new(:key => @ec_key_pem)
264
+ private_key.to_der.should == @ec_key_der
265
+ end
266
+
267
+ it "returns error for bit_strength" do
268
+ private_key = R509::PrivateKey.new(:key => @ec_key_pem)
269
+ expect { private_key.bit_strength }.to raise_error(R509::R509Error,'Bit strength is not available for EC at this time.')
270
+ end
271
+
272
+
273
+ end
274
+ end
275
+