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.
- data/README.md +343 -151
- data/Rakefile +26 -23
- data/bin/r509 +126 -112
- data/bin/r509-parse +24 -24
- data/doc/R509.html +169 -7
- data/doc/R509/ASN1.html +370 -0
- data/doc/R509/ASN1/GeneralName.html +1121 -0
- data/doc/R509/ASN1/GeneralNames.html +843 -0
- data/doc/R509/ASN1/NoticeReference.html +392 -0
- data/doc/R509/ASN1/PolicyInformation.html +387 -0
- data/doc/R509/ASN1/PolicyQualifiers.html +455 -0
- data/doc/R509/ASN1/UserNotice.html +386 -0
- data/doc/R509/{Crl.html → CRL.html} +7 -7
- data/doc/R509/CRL/Administrator.html +1559 -0
- data/doc/R509/{Crl/Parser.html → CRL/SignedList.html} +501 -210
- data/doc/R509/{Csr.html → CSR.html} +444 -314
- data/doc/R509/Cert.html +866 -617
- data/doc/R509/Cert/Extensions.html +52 -41
- data/doc/R509/Cert/Extensions/AuthorityInfoAccess.html +70 -35
- data/doc/R509/Cert/Extensions/AuthorityKeyIdentifier.html +387 -4
- data/doc/R509/Cert/Extensions/BasicConstraints.html +61 -25
- data/doc/R509/Cert/Extensions/CRLDistributionPoints.html +354 -0
- data/doc/R509/Cert/Extensions/CertificatePolicies.html +340 -0
- data/doc/R509/Cert/Extensions/ExtendedKeyUsage.html +440 -49
- data/doc/R509/Cert/Extensions/{CrlDistributionPoints.html → InhibitAnyPolicy.html} +52 -35
- data/doc/R509/Cert/Extensions/KeyUsage.html +247 -121
- data/doc/R509/Cert/Extensions/NameConstraints.html +445 -0
- data/doc/R509/Cert/Extensions/OCSPNoCheck.html +239 -0
- data/doc/R509/Cert/Extensions/PolicyConstraints.html +424 -0
- data/doc/R509/Cert/Extensions/SubjectAlternativeName.html +437 -62
- data/doc/R509/Cert/Extensions/SubjectKeyIdentifier.html +52 -10
- data/doc/R509/CertificateAuthority.html +4 -4
- data/doc/R509/CertificateAuthority/Signer.html +154 -187
- data/doc/R509/Config.html +6 -6
- data/doc/R509/Config/{CaConfig.html → CAConfig.html} +451 -348
- data/doc/R509/Config/{CaConfigPool.html → CAConfigPool.html} +47 -47
- data/doc/R509/Config/CAProfile.html +1015 -0
- data/doc/R509/Config/SubjectItemPolicy.html +86 -86
- data/doc/R509/IOHelpers.html +22 -22
- data/doc/R509/MessageDigest.html +14 -14
- data/doc/R509/NameSanitizer.html +53 -53
- data/doc/R509/{Ocsp.html → OCSP.html} +9 -9
- data/doc/R509/{Ocsp → OCSP}/Request.html +7 -7
- data/doc/R509/{Ocsp → OCSP}/Request/Nonce.html +56 -11
- data/doc/R509/{Ocsp → OCSP}/Response.html +44 -44
- data/doc/R509/{OidMapper.html → OIDMapper.html} +23 -39
- data/doc/R509/PrivateKey.html +415 -168
- data/doc/R509/R509Error.html +3 -3
- data/doc/R509/{Spki.html → SPKI.html} +354 -192
- data/doc/R509/Subject.html +224 -113
- data/doc/R509/Validity.html +27 -5
- data/doc/R509/Validity/Checker.html +13 -13
- data/doc/R509/Validity/DefaultChecker.html +13 -13
- data/doc/R509/Validity/DefaultWriter.html +14 -14
- data/doc/R509/Validity/Status.html +39 -39
- data/doc/R509/Validity/Writer.html +18 -18
- data/doc/_index.html +138 -35
- data/doc/class_list.html +1 -1
- data/doc/css/style.css +10 -0
- data/doc/file.README.html +368 -171
- data/doc/file.r509.html +92 -69
- data/doc/frames.html +1 -1
- data/doc/index.html +368 -171
- data/doc/method_list.html +910 -390
- data/doc/top-level-namespace.html +3 -3
- data/lib/r509.rb +32 -16
- data/lib/r509/asn1.rb +375 -0
- data/lib/r509/cert.rb +381 -364
- data/lib/r509/cert/extensions.rb +443 -76
- data/lib/r509/certificate_authority.rb +407 -0
- data/lib/r509/config.rb +547 -351
- data/lib/r509/crl.rb +336 -366
- data/lib/r509/csr.rb +278 -289
- data/lib/r509/ec-hack.rb +37 -0
- data/lib/r509/exceptions.rb +3 -3
- data/lib/r509/io_helpers.rb +44 -44
- data/lib/r509/message_digest.rb +53 -0
- data/lib/r509/ocsp.rb +80 -70
- data/lib/r509/oid_mapper.rb +32 -0
- data/lib/r509/private_key.rb +228 -0
- data/lib/r509/spki.rb +145 -93
- data/lib/r509/subject.rb +203 -110
- data/lib/r509/validity.rb +70 -68
- data/lib/r509/version.rb +2 -2
- data/r509.yaml +92 -69
- data/spec/asn1_spec.rb +402 -0
- data/spec/cert/extensions_spec.rb +957 -494
- data/spec/cert_spec.rb +382 -307
- data/spec/certificate_authority_spec.rb +668 -250
- data/spec/config_spec.rb +515 -302
- data/spec/crl_spec.rb +197 -198
- data/spec/csr_spec.rb +334 -289
- data/spec/fixtures.rb +247 -171
- data/spec/fixtures/cert1.der +0 -0
- data/spec/fixtures/cert1.pem +0 -0
- data/spec/fixtures/cert1_public_key_modulus.txt +0 -0
- data/spec/fixtures/cert3.p12 +0 -0
- data/spec/fixtures/cert3.pem +0 -0
- data/spec/fixtures/cert3_key.pem +0 -0
- data/spec/fixtures/cert3_key_des3.pem +0 -0
- data/spec/fixtures/cert4.pem +0 -0
- data/spec/fixtures/cert5.pem +0 -0
- data/spec/fixtures/cert6.pem +0 -0
- data/spec/fixtures/cert_expired.pem +0 -0
- data/spec/fixtures/cert_inhibit.pem +24 -0
- data/spec/fixtures/cert_name_constraints.pem +29 -0
- data/spec/fixtures/cert_not_yet_valid.pem +0 -0
- data/spec/fixtures/cert_ocsp_no_check.pem +18 -0
- data/spec/fixtures/cert_policy_constraints.pem +31 -0
- data/spec/fixtures/cert_san.pem +0 -0
- data/spec/fixtures/cert_san2.pem +0 -0
- data/spec/fixtures/cert_unknown_extension.pem +28 -0
- data/spec/fixtures/config_pool_test_minimal.yaml +11 -11
- data/spec/fixtures/config_test.yaml +54 -36
- data/spec/fixtures/config_test_dsa.yaml +35 -0
- data/spec/fixtures/config_test_ec.yaml +35 -0
- data/spec/fixtures/config_test_engine_key.yaml +5 -5
- data/spec/fixtures/config_test_engine_no_key_name.yaml +4 -4
- data/spec/fixtures/config_test_minimal.yaml +4 -4
- data/spec/fixtures/config_test_password.yaml +5 -5
- data/spec/fixtures/config_test_various.yaml +111 -74
- data/spec/fixtures/crl_list_file.txt +0 -0
- data/spec/fixtures/crl_with_reason.pem +0 -0
- data/spec/fixtures/csr1.der +0 -0
- data/spec/fixtures/csr1.pem +0 -0
- data/spec/fixtures/csr1_key.der +0 -0
- data/spec/fixtures/csr1_key.pem +0 -0
- data/spec/fixtures/csr1_key_encrypted_des3.pem +0 -0
- data/spec/fixtures/csr1_newlines.pem +0 -0
- data/spec/fixtures/csr1_no_begin_end.pem +0 -0
- data/spec/fixtures/csr1_public_key_modulus.txt +0 -0
- data/spec/fixtures/csr2.pem +0 -0
- data/spec/fixtures/csr2_key.pem +0 -0
- data/spec/fixtures/csr3.pem +0 -0
- data/spec/fixtures/csr4.pem +0 -0
- data/spec/fixtures/csr_dsa.pem +0 -0
- data/spec/fixtures/csr_invalid_signature.pem +0 -0
- data/spec/fixtures/dsa_key.pem +0 -0
- data/spec/fixtures/dsa_root.cer +28 -0
- data/spec/fixtures/dsa_root.key +20 -0
- data/spec/fixtures/ec_csr2.der +0 -0
- data/spec/fixtures/ec_csr2.pem +8 -0
- data/spec/fixtures/ec_key1.der +0 -0
- data/spec/fixtures/ec_key1.pem +6 -0
- data/spec/fixtures/ec_key1_encrypted.pem +9 -0
- data/spec/fixtures/ec_key2.pem +6 -0
- data/spec/fixtures/hmacsha1.sig +1 -0
- data/spec/fixtures/hmacsha512.sig +1 -0
- data/spec/fixtures/key4.pem +0 -0
- data/spec/fixtures/key4_encrypted_des3.pem +0 -0
- data/spec/fixtures/missing_key_identifier_ca.cer +0 -0
- data/spec/fixtures/missing_key_identifier_ca.key +0 -0
- data/spec/fixtures/ocsptest.r509.local.pem +0 -0
- data/spec/fixtures/ocsptest.r509.local_ocsp_request.der +0 -0
- data/spec/fixtures/ocsptest2.r509.local.pem +0 -0
- data/spec/fixtures/second_ca.cer +0 -0
- data/spec/fixtures/second_ca.key +0 -0
- data/spec/fixtures/spkac.der +0 -0
- data/spec/fixtures/spkac.txt +0 -0
- data/spec/fixtures/spkac_dsa.txt +1 -1
- data/spec/fixtures/spkac_dsa_no_verify.txt +1 -0
- data/spec/fixtures/spkac_ec.txt +1 -0
- data/spec/fixtures/spkac_rsa_newlines.txt +13 -0
- data/spec/fixtures/stca.pem +0 -0
- data/spec/fixtures/stca_ocsp_request.der +0 -0
- data/spec/fixtures/stca_ocsp_response.der +0 -0
- data/spec/fixtures/test1.csr +0 -0
- data/spec/fixtures/test_ca.cer +0 -0
- data/spec/fixtures/test_ca.key +0 -0
- data/spec/fixtures/test_ca.p12 +0 -0
- data/spec/fixtures/test_ca_des3.key +0 -0
- data/spec/fixtures/test_ca_ec.cer +14 -0
- data/spec/fixtures/test_ca_ec.key +6 -0
- data/spec/fixtures/test_ca_ec_ee.cer +22 -0
- data/spec/fixtures/test_ca_ec_ee.key +6 -0
- data/spec/fixtures/test_ca_ocsp.cer +0 -0
- data/spec/fixtures/test_ca_ocsp.key +0 -0
- data/spec/fixtures/test_ca_ocsp.p12 +0 -0
- data/spec/fixtures/test_ca_ocsp_chain.txt +0 -0
- data/spec/fixtures/test_ca_ocsp_response.der +0 -0
- data/spec/fixtures/test_ca_subroot.cer +0 -0
- data/spec/fixtures/test_ca_subroot.key +0 -0
- data/spec/fixtures/test_ca_subroot_ocsp.cer +0 -0
- data/spec/fixtures/test_ca_subroot_ocsp.key +0 -0
- data/spec/fixtures/test_ca_subroot_ocsp_response.der +0 -0
- data/spec/fixtures/unknown_oid.csr +0 -0
- data/spec/message_digest_spec.rb +104 -84
- data/spec/ocsp_spec.rb +105 -105
- data/spec/oid_mapper_spec.rb +21 -21
- data/spec/private_key_spec.rb +275 -0
- data/spec/r509_spec.rb +35 -0
- data/spec/spec_helper.rb +15 -6
- data/spec/spki_spec.rb +221 -142
- data/spec/subject_spec.rb +232 -164
- data/spec/validity_spec.rb +91 -91
- metadata +79 -25
- data/doc/R509/Config/CaProfile.html +0 -651
- data/doc/R509/Crl/Administrator.html +0 -2073
- data/lib/r509/certificateauthority.rb +0 -290
- data/lib/r509/messagedigest.rb +0 -49
- data/lib/r509/oidmapper.rb +0 -32
- data/lib/r509/privatekey.rb +0 -185
- data/spec/privatekey_spec.rb +0 -198
data/lib/r509/validity.rb
CHANGED
@@ -2,91 +2,93 @@ require 'openssl'
|
|
2
2
|
|
3
3
|
#Module for holding classes for writing and reading certificate validity information (used for serving OCSP responses)
|
4
4
|
module R509::Validity
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
#mapping from OpenSSL
|
6
|
+
VALID = OpenSSL::OCSP::V_CERTSTATUS_GOOD
|
7
|
+
#mapping from OpenSSL
|
8
|
+
REVOKED = OpenSSL::OCSP::V_CERTSTATUS_REVOKED
|
9
|
+
#mapping from OpenSSL
|
10
|
+
UNKNOWN = OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
#data about the status of a certificate
|
13
|
+
class Status
|
14
|
+
attr_reader :status, :revocation_time, :revocation_reason
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
def initialize(options={})
|
17
|
+
@status = options[:status]
|
18
|
+
@revocation_time = options[:revocation_time] || nil
|
19
|
+
@revocation_reason = options[:revocation_reason] || 0
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
if (@status == R509::Validity::REVOKED and @revocation_time.nil?)
|
22
|
+
@revocation_time = Time.now.to_i
|
23
|
+
end
|
24
|
+
end
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
26
|
+
# @return [OpenSSL::OCSP::STATUS] OpenSSL status constants when passing R509 constants
|
27
|
+
def ocsp_status
|
28
|
+
case @status
|
29
|
+
when R509::Validity::VALID
|
30
|
+
OpenSSL::OCSP::V_CERTSTATUS_GOOD
|
31
|
+
when R509::Validity::REVOKED
|
32
|
+
OpenSSL::OCSP::V_CERTSTATUS_REVOKED
|
33
|
+
when R509::Validity::UNKNOWN
|
34
|
+
OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
|
35
|
+
else
|
36
|
+
OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
|
37
|
+
end
|
37
38
|
end
|
39
|
+
end
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
#abstract base class for a Writer
|
42
|
+
class Writer
|
43
|
+
def issue(issuer, serial)
|
44
|
+
raise NotImplementedError, "You must call #issue on a subclass of Writer"
|
45
|
+
end
|
44
46
|
|
45
|
-
|
46
|
-
|
47
|
-
|
47
|
+
def revoke(issuer, serial, reason)
|
48
|
+
raise NotImplementedError, "You must call #revoke on a subclass of Writer"
|
49
|
+
end
|
48
50
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
51
|
+
# is_available? is meant to be implemented to check if the backend store you choose to implement is currently working.
|
52
|
+
# see r509-ocsp-responder and r509-validity-redis for an example of use
|
53
|
+
def is_available?
|
54
|
+
raise NotImplementedError, "You must call #is_available? on a subclass of Writer"
|
54
55
|
end
|
56
|
+
end
|
55
57
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
#abstract base class for a Checker
|
59
|
+
class Checker
|
60
|
+
def check(issuer, serial)
|
61
|
+
raise NotImplementedError, "You must call #check on a subclass of Checker"
|
62
|
+
end
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
64
|
+
# is_available? is meant to be implemented to check if the backend store you choose to implement is currently working.
|
65
|
+
# see r509-ocsp-responder and r509-validity-redis for an example of use
|
66
|
+
def is_available?
|
67
|
+
raise NotImplementedError, "You must call #is_available? on a subclass of Checker"
|
67
68
|
end
|
69
|
+
end
|
68
70
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
#default implementaton of the Checker class. Used for tests. DO NOT USE OTHERWISE
|
72
|
+
class DefaultChecker < R509::Validity::Checker
|
73
|
+
def check(issuer, serial)
|
74
|
+
R509::Validity::Status.new(:status => R509::Validity::VALID)
|
75
|
+
end
|
74
76
|
|
75
|
-
|
76
|
-
|
77
|
-
end
|
77
|
+
def is_available?
|
78
|
+
true
|
78
79
|
end
|
80
|
+
end
|
79
81
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
82
|
+
#default implementaton of the Writer class. Does nothing (obviously)
|
83
|
+
class DefaultWriter < R509::Validity::Writer
|
84
|
+
def issue(issuer, serial)
|
85
|
+
end
|
84
86
|
|
85
|
-
|
86
|
-
|
87
|
+
def revoke(issuer, serial, reason)
|
88
|
+
end
|
87
89
|
|
88
|
-
|
89
|
-
|
90
|
-
end
|
90
|
+
def is_available?
|
91
|
+
true
|
91
92
|
end
|
93
|
+
end
|
92
94
|
end
|
data/lib/r509/version.rb
CHANGED
data/r509.yaml
CHANGED
@@ -1,73 +1,96 @@
|
|
1
1
|
certificate_authorities: {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
}
|
34
|
-
},
|
35
|
-
client: {
|
36
|
-
basic_constraints: "CA:FALSE",
|
37
|
-
key_usage: [digitalSignature,keyEncipherment],
|
38
|
-
extended_key_usage: [clientAuth],
|
39
|
-
certificate_policies: [ [ "policyIdentifier=2.16.840.1.9999999999.1.2.3.4.2", "CPS.1=http://example.com/cps"] ]
|
40
|
-
},
|
41
|
-
email: {
|
42
|
-
basic_constraints: "CA:FALSE",
|
43
|
-
key_usage: [digitalSignature,keyEncipherment],
|
44
|
-
extended_key_usage: [emailProtection],
|
45
|
-
certificate_policies: [ [ "policyIdentifier=2.16.840.1.9999999999.1.2.3.4.3", "CPS.1=http://example.com/cps"] ]
|
46
|
-
},
|
47
|
-
clientserver: {
|
48
|
-
basic_constraints: "CA:FALSE",
|
49
|
-
key_usage: [digitalSignature,keyEncipherment],
|
50
|
-
extended_key_usage: [serverAuth,clientAuth],
|
51
|
-
certificate_policies: [ [ "policyIdentifier=2.16.840.1.9999999999.1.2.3.4.4", "CPS.1=http://example.com/cps"] ]
|
52
|
-
},
|
53
|
-
codesigning: {
|
54
|
-
basic_constraints: "CA:FALSE",
|
55
|
-
key_usage: [digitalSignature],
|
56
|
-
extended_key_usage: [codeSigning],
|
57
|
-
certificate_policies: [ [ "policyIdentifier=2.16.840.1.9999999999.1.2.3.4.5", "CPS.1=http://example.com/cps"] ]
|
58
|
-
},
|
59
|
-
timestamping: {
|
60
|
-
basic_constraints: "CA:FALSE",
|
61
|
-
key_usage: [digitalSignature],
|
62
|
-
extended_key_usage: [timeStamping],
|
63
|
-
certificate_policies: [ [ "policyIdentifier=2.16.840.1.9999999999.1.2.3.4.6", "CPS.1=http://example.com/cps"] ]
|
64
|
-
},
|
65
|
-
subroot: {
|
66
|
-
basic_constraints: "CA:TRUE,pathlen:0",
|
67
|
-
key_usage: [keyCertSign,cRLSign],
|
68
|
-
extended_key_usage: [],
|
69
|
-
certificate_policies: [ ]
|
70
|
-
}
|
2
|
+
test_ca: {
|
3
|
+
ca_cert: {
|
4
|
+
cert: 'spec/fixtures/test_ca.cer',
|
5
|
+
key: 'spec/fixtures/test_ca.key'
|
6
|
+
},
|
7
|
+
ocsp_cert: {
|
8
|
+
pkcs12: 'spec/fixtures/test_ca_ocsp.p12',
|
9
|
+
password: 'r509'
|
10
|
+
},
|
11
|
+
ocsp_location: ['http://ocsp.domain.com'],
|
12
|
+
ca_issuers_location: ['http://domain.com/ca.html'],
|
13
|
+
ocsp_chain: 'spec/fixtures/test_ca_ocsp_chain.txt',
|
14
|
+
ocsp_start_skew_seconds: 3600,
|
15
|
+
ocsp_validity_hours: 168,
|
16
|
+
cdp_location: ['http://crl.domain.com/test_ca.crl'],
|
17
|
+
crl_list: 'spec/fixtures/test_ca_crl_list.txt',
|
18
|
+
crl_number: 'spec/fixtures/test_ca_crl_number.txt',
|
19
|
+
crl_validity_hours: 168, #7 days
|
20
|
+
message_digest: 'SHA1', #SHA1, SHA256, SHA512 supported. MD5 too, but you really shouldn't use that unless you have a good reason
|
21
|
+
profiles: {
|
22
|
+
server: {
|
23
|
+
basic_constraints: {"ca" : false},
|
24
|
+
key_usage: [digitalSignature,keyEncipherment],
|
25
|
+
extended_key_usage: [serverAuth],
|
26
|
+
subject_item_policy: {
|
27
|
+
CN: "required",
|
28
|
+
O: "required",
|
29
|
+
OU: "optional",
|
30
|
+
ST: "required",
|
31
|
+
C: "required",
|
32
|
+
L: "required"
|
71
33
|
}
|
34
|
+
},
|
35
|
+
client: {
|
36
|
+
basic_constraints: {"ca" : false},
|
37
|
+
key_usage: [digitalSignature,keyEncipherment],
|
38
|
+
extended_key_usage: [clientAuth],
|
39
|
+
},
|
40
|
+
email: {
|
41
|
+
basic_constraints: {"ca" : false},
|
42
|
+
key_usage: [digitalSignature,keyEncipherment],
|
43
|
+
extended_key_usage: [emailProtection],
|
44
|
+
},
|
45
|
+
clientserver: {
|
46
|
+
basic_constraints: {"ca" : false},
|
47
|
+
key_usage: [digitalSignature,keyEncipherment],
|
48
|
+
extended_key_usage: [serverAuth,clientAuth],
|
49
|
+
},
|
50
|
+
codesigning: {
|
51
|
+
basic_constraints: {"ca" : false},
|
52
|
+
key_usage: [digitalSignature],
|
53
|
+
extended_key_usage: [codeSigning],
|
54
|
+
},
|
55
|
+
timestamping: {
|
56
|
+
basic_constraints: {"ca" : false},
|
57
|
+
key_usage: [digitalSignature],
|
58
|
+
extended_key_usage: [timeStamping],
|
59
|
+
},
|
60
|
+
subroot: {
|
61
|
+
basic_constraints: {"ca" : true, "path_length" : 0},
|
62
|
+
key_usage: [keyCertSign,cRLSign],
|
63
|
+
extended_key_usage: [],
|
64
|
+
certificate_policies: [
|
65
|
+
{ policy_identifier: "2.16.840.1.99999.21.234",
|
66
|
+
cps_uris: ["http://example.com/cps","http://haha.com"],
|
67
|
+
user_notices: [ { explicit_text: "this is a great thing", organization: "my org", notice_numbers: "1,2,3" } ]
|
68
|
+
},
|
69
|
+
{ policy_identifier: "2.16.840.1.99999.21.235",
|
70
|
+
cps_uris: ["http://example.com/cps2"],
|
71
|
+
user_notices: [ { explicit_text: "this is a bad thing", organization: "another org", notice_numbers: "3,2,1" },{ explicit_text: "another user notice"} ]
|
72
|
+
}
|
73
|
+
],
|
74
|
+
inhibit_any_policy: 0,
|
75
|
+
policy_constraints: { require_explicit_policy: 0, inhibit_policy_mapping: 0},
|
76
|
+
name_constraints: {
|
77
|
+
permitted: [
|
78
|
+
{type: "IP", value: "192.168.0.0/255.255.0.0"},
|
79
|
+
{type: "dirName", value: [['CN','myCN'],['O','Org']]}
|
80
|
+
],
|
81
|
+
excluded: [
|
82
|
+
{type: "email", value: "domain.com"},
|
83
|
+
{type: "URI", value: ".net"},
|
84
|
+
{type: "DNS", value: "test.us"}
|
85
|
+
]
|
86
|
+
}
|
87
|
+
},
|
88
|
+
ocsp_delegate: {
|
89
|
+
basic_constraints: {"ca" : false},
|
90
|
+
key_usage: [digitalSignature],
|
91
|
+
extended_key_usage: [OCSPSigning],
|
92
|
+
ocsp_no_check: true
|
93
|
+
}
|
72
94
|
}
|
95
|
+
}
|
73
96
|
}
|
data/spec/asn1_spec.rb
ADDED
@@ -0,0 +1,402 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r509/asn1'
|
3
|
+
|
4
|
+
describe R509::ASN1 do
|
5
|
+
it "does not error with valid extension on get_extension_payload" do
|
6
|
+
#SAN extension
|
7
|
+
der = "0L\u0006\u0003U\u001D\u0011\u0001\u0001\xFF\u0004B0@\x82\u000Ewww.test.local\x87\u0004\n\u0001\u0002\u0003\x86\u0015http://www.test.local\x81\u0011myemail@email.com"
|
8
|
+
ext = OpenSSL::X509::Extension.new(der)
|
9
|
+
payload = R509::ASN1.get_extension_payload(ext)
|
10
|
+
payload.should_not be_nil
|
11
|
+
end
|
12
|
+
|
13
|
+
context "general_name_parser" do
|
14
|
+
it "returns nil if passed nil" do
|
15
|
+
general_names = R509::ASN1.general_name_parser(nil)
|
16
|
+
general_names.should be_nil
|
17
|
+
end
|
18
|
+
it "correctly parses dns names" do
|
19
|
+
general_names = R509::ASN1.general_name_parser(['domain2.com','domain3.com'])
|
20
|
+
general_names.dns_names.should == ["domain2.com", "domain3.com"]
|
21
|
+
end
|
22
|
+
|
23
|
+
it "adds SAN IPv4 names" do
|
24
|
+
general_names = R509::ASN1.general_name_parser(['1.2.3.4','2.3.4.5'])
|
25
|
+
general_names.ip_addresses.should == ["1.2.3.4", "2.3.4.5"]
|
26
|
+
end
|
27
|
+
|
28
|
+
it "adds SAN IPv6 names" do
|
29
|
+
general_names = R509::ASN1.general_name_parser(['FE80:0:0:0:0:0:0:1','fe80::2',])
|
30
|
+
general_names.ip_addresses.should == ["fe80::1", "fe80::2"]
|
31
|
+
end
|
32
|
+
|
33
|
+
it "adds SAN URI names" do
|
34
|
+
general_names = R509::ASN1.general_name_parser(['http://myuri.com','ftp://whyftp'])
|
35
|
+
general_names.uris.should == ['http://myuri.com','ftp://whyftp']
|
36
|
+
end
|
37
|
+
|
38
|
+
it "adds SAN rfc822 names" do
|
39
|
+
general_names = R509::ASN1.general_name_parser(['email@domain.com','some@other.com'])
|
40
|
+
general_names.rfc_822_names.should == ['email@domain.com','some@other.com']
|
41
|
+
end
|
42
|
+
|
43
|
+
it "adds directoryNames via R509::Subject objects" do
|
44
|
+
s = R509::Subject.new([['CN','what-what']])
|
45
|
+
s2 = R509::Subject.new([['C','US'],['L','locality']])
|
46
|
+
general_names = R509::ASN1.general_name_parser([s,s2])
|
47
|
+
general_names.directory_names.size.should == 2
|
48
|
+
general_names.directory_names[0].CN.should == 'what-what'
|
49
|
+
general_names.directory_names[0].C.should be_nil
|
50
|
+
general_names.directory_names[1].C.should == 'US'
|
51
|
+
general_names.directory_names[1].L.should == 'locality'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "adds directoryNames via arrays" do
|
55
|
+
s = [['CN','what-what']]
|
56
|
+
s2 = [['C','US'],['L','locality']]
|
57
|
+
general_names = R509::ASN1.general_name_parser([s,s2])
|
58
|
+
general_names.directory_names.size.should == 2
|
59
|
+
general_names.directory_names[0].CN.should == 'what-what'
|
60
|
+
general_names.directory_names[0].C.should be_nil
|
61
|
+
general_names.directory_names[1].C.should == 'US'
|
62
|
+
general_names.directory_names[1].L.should == 'locality'
|
63
|
+
end
|
64
|
+
|
65
|
+
it "adds a mix of SAN name types" do
|
66
|
+
general_names = R509::ASN1.general_name_parser(['1.2.3.4','http://langui.sh','email@address.local','domain.internal','2.3.4.5'])
|
67
|
+
general_names.ip_addresses.should == ['1.2.3.4','2.3.4.5']
|
68
|
+
general_names.dns_names.should == ['domain.internal']
|
69
|
+
general_names.uris.should == ['http://langui.sh']
|
70
|
+
general_names.rfc_822_names.should == ['email@address.local']
|
71
|
+
end
|
72
|
+
|
73
|
+
it "handles empty array" do
|
74
|
+
general_names = R509::ASN1.general_name_parser([])
|
75
|
+
general_names.names.size.should == 0
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe R509::ASN1::GeneralName do
|
82
|
+
context "parses types to tags within ::map_type_to_tag" do
|
83
|
+
it "handles otherName" do
|
84
|
+
R509::ASN1::GeneralName.map_type_to_tag(:otherName).should == 0
|
85
|
+
R509::ASN1::GeneralName.map_type_to_tag("otherName").should == 0
|
86
|
+
end
|
87
|
+
it "handles rfc822Name" do
|
88
|
+
R509::ASN1::GeneralName.map_type_to_tag(:rfc822Name).should == 1
|
89
|
+
R509::ASN1::GeneralName.map_type_to_tag("rfc822Name").should == 1
|
90
|
+
R509::ASN1::GeneralName.map_type_to_tag("email").should == 1
|
91
|
+
end
|
92
|
+
it "handles dNSName" do
|
93
|
+
R509::ASN1::GeneralName.map_type_to_tag(:dNSName).should == 2
|
94
|
+
R509::ASN1::GeneralName.map_type_to_tag("dNSName").should == 2
|
95
|
+
R509::ASN1::GeneralName.map_type_to_tag("DNS").should == 2
|
96
|
+
end
|
97
|
+
it "handles x400Address" do
|
98
|
+
R509::ASN1::GeneralName.map_type_to_tag(:x400Address).should == 3
|
99
|
+
R509::ASN1::GeneralName.map_type_to_tag("x400Address").should == 3
|
100
|
+
end
|
101
|
+
it "handles directoryName" do
|
102
|
+
R509::ASN1::GeneralName.map_type_to_tag(:directoryName).should == 4
|
103
|
+
R509::ASN1::GeneralName.map_type_to_tag("directoryName").should == 4
|
104
|
+
R509::ASN1::GeneralName.map_type_to_tag("dirName").should == 4
|
105
|
+
end
|
106
|
+
it "handles ediPartyName" do
|
107
|
+
R509::ASN1::GeneralName.map_type_to_tag(:ediPartyName).should == 5
|
108
|
+
R509::ASN1::GeneralName.map_type_to_tag("ediPartyName").should == 5
|
109
|
+
end
|
110
|
+
it "handles uniformResourceIdentifier" do
|
111
|
+
R509::ASN1::GeneralName.map_type_to_tag(:uniformResourceIdentifier).should == 6
|
112
|
+
R509::ASN1::GeneralName.map_type_to_tag("uniformResourceIdentifier").should == 6
|
113
|
+
R509::ASN1::GeneralName.map_type_to_tag("URI").should == 6
|
114
|
+
end
|
115
|
+
it "handles iPAddress" do
|
116
|
+
R509::ASN1::GeneralName.map_type_to_tag(:iPAddress).should == 7
|
117
|
+
R509::ASN1::GeneralName.map_type_to_tag("iPAddress").should == 7
|
118
|
+
R509::ASN1::GeneralName.map_type_to_tag("IP").should == 7
|
119
|
+
end
|
120
|
+
it "handles registeredID" do
|
121
|
+
R509::ASN1::GeneralName.map_type_to_tag(:registeredID).should == 8
|
122
|
+
R509::ASN1::GeneralName.map_type_to_tag("registeredID").should == 8
|
123
|
+
end
|
124
|
+
end
|
125
|
+
context "::map_tag_to_type" do
|
126
|
+
it "handles otherName" do
|
127
|
+
R509::ASN1::GeneralName.map_tag_to_type(0).should == :otherName
|
128
|
+
end
|
129
|
+
it "handles rfc822Name" do
|
130
|
+
R509::ASN1::GeneralName.map_tag_to_type(1).should == :rfc822Name
|
131
|
+
end
|
132
|
+
it "handles dNSName" do
|
133
|
+
R509::ASN1::GeneralName.map_tag_to_type(2).should == :dNSName
|
134
|
+
end
|
135
|
+
it "handles x400Address" do
|
136
|
+
R509::ASN1::GeneralName.map_tag_to_type(3).should == :x400Address
|
137
|
+
end
|
138
|
+
it "handles directoryName" do
|
139
|
+
R509::ASN1::GeneralName.map_tag_to_type(4).should == :directoryName
|
140
|
+
end
|
141
|
+
it "handles ediPartyName" do
|
142
|
+
R509::ASN1::GeneralName.map_tag_to_type(5).should == :ediPartyName
|
143
|
+
end
|
144
|
+
it "handles uniformResourceIdentifier" do
|
145
|
+
R509::ASN1::GeneralName.map_tag_to_type(6).should == :uniformResourceIdentifier
|
146
|
+
end
|
147
|
+
it "handles iPAddress" do
|
148
|
+
R509::ASN1::GeneralName.map_tag_to_type(7).should == :iPAddress
|
149
|
+
end
|
150
|
+
it "handles registeredID" do
|
151
|
+
R509::ASN1::GeneralName.map_tag_to_type(8).should == :registeredID
|
152
|
+
end
|
153
|
+
it "raises error with invalid tag" do
|
154
|
+
expect { R509::ASN1::GeneralName.map_tag_to_type(28) }.to raise_error(R509::R509Error,"Invalid tag 28")
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
context "::map_tag_to_serial_prefix" do
|
159
|
+
it "handles otherName" do
|
160
|
+
expect { R509::ASN1::GeneralName.map_tag_to_serial_prefix(0) }.to raise_error(R509::R509Error)
|
161
|
+
end
|
162
|
+
it "handles rfc822Name" do
|
163
|
+
R509::ASN1::GeneralName.map_tag_to_serial_prefix(1).should == "email"
|
164
|
+
end
|
165
|
+
it "handles dNSName" do
|
166
|
+
R509::ASN1::GeneralName.map_tag_to_serial_prefix(2).should == "DNS"
|
167
|
+
end
|
168
|
+
it "handles x400Address" do
|
169
|
+
expect { R509::ASN1::GeneralName.map_tag_to_serial_prefix(3) }.to raise_error(R509::R509Error)
|
170
|
+
end
|
171
|
+
it "handles directoryName" do
|
172
|
+
R509::ASN1::GeneralName.map_tag_to_serial_prefix(4).should == "dirName"
|
173
|
+
end
|
174
|
+
it "handles ediPartyName" do
|
175
|
+
expect { R509::ASN1::GeneralName.map_tag_to_serial_prefix(5) }.to raise_error(R509::R509Error)
|
176
|
+
end
|
177
|
+
it "handles uniformResourceIdentifier" do
|
178
|
+
R509::ASN1::GeneralName.map_tag_to_serial_prefix(6).should == "URI"
|
179
|
+
end
|
180
|
+
it "handles iPAddress" do
|
181
|
+
R509::ASN1::GeneralName.map_tag_to_serial_prefix(7).should == "IP"
|
182
|
+
end
|
183
|
+
it "handles registeredID" do
|
184
|
+
expect { R509::ASN1::GeneralName.map_tag_to_serial_prefix(8) }.to raise_error(R509::R509Error)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
it "handles rfc822Name" do
|
188
|
+
der = "\x81\u0011myemail@email.com"
|
189
|
+
asn = OpenSSL::ASN1.decode der
|
190
|
+
gn = R509::ASN1::GeneralName.new(asn)
|
191
|
+
gn.type.should == :rfc822Name
|
192
|
+
gn.value.should == 'myemail@email.com'
|
193
|
+
end
|
194
|
+
it "handles dNSName" do
|
195
|
+
der = "\x82\u000Ewww.test.local"
|
196
|
+
asn = OpenSSL::ASN1.decode der
|
197
|
+
gn = R509::ASN1::GeneralName.new(asn)
|
198
|
+
gn.type.should == :dNSName
|
199
|
+
gn.value.should == 'www.test.local'
|
200
|
+
end
|
201
|
+
it "handles uniformResourceIdentifier" do
|
202
|
+
der = "\x86\u001Fhttp://www.test.local/subca.crl"
|
203
|
+
asn = OpenSSL::ASN1.decode der
|
204
|
+
gn = R509::ASN1::GeneralName.new(asn)
|
205
|
+
gn.type.should == :uniformResourceIdentifier
|
206
|
+
gn.value.should == "http://www.test.local/subca.crl"
|
207
|
+
end
|
208
|
+
it "handles iPAddress v4" do
|
209
|
+
der = "\x87\u0004\n\u0001\u0002\u0003"
|
210
|
+
asn = OpenSSL::ASN1.decode der
|
211
|
+
gn = R509::ASN1::GeneralName.new(asn)
|
212
|
+
gn.type.should == :iPAddress
|
213
|
+
gn.value.should == '10.1.2.3'
|
214
|
+
end
|
215
|
+
it "handles iPAddress v6" do
|
216
|
+
der = "\x87\x10\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
217
|
+
asn = OpenSSL::ASN1.decode der
|
218
|
+
gn = R509::ASN1::GeneralName.new(asn)
|
219
|
+
gn.type.should == :iPAddress
|
220
|
+
gn.value.should == 'ff::'
|
221
|
+
end
|
222
|
+
it "handles iPAddress v4 with netmask" do
|
223
|
+
der = "\x87\b\n\x01\x02\x03\xFF\xFF\xFF\xFF"
|
224
|
+
asn = OpenSSL::ASN1.decode der
|
225
|
+
gn = R509::ASN1::GeneralName.new(asn)
|
226
|
+
gn.type.should == :iPAddress
|
227
|
+
gn.value.should == '10.1.2.3/255.255.255.255'
|
228
|
+
end
|
229
|
+
it "handles iPAddress v6 with netmask" do
|
230
|
+
der = "\x87 \x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF"
|
231
|
+
asn = OpenSSL::ASN1.decode der
|
232
|
+
gn = R509::ASN1::GeneralName.new(asn)
|
233
|
+
gn.type.should == :iPAddress
|
234
|
+
gn.value.should == 'ff::/ff:ff:ff:ff:ff:ff:ff:ff'
|
235
|
+
end
|
236
|
+
it "handles directoryName" do
|
237
|
+
der = "\xA4`0^1\v0\t\u0006\u0003U\u0004\u0006\u0013\u0002US1\u00110\u000F\u0006\u0003U\u0004\b\f\bIllinois1\u00100\u000E\u0006\u0003U\u0004\a\f\aChicago1\u00180\u0016\u0006\u0003U\u0004\n\f\u000FRuby CA Project1\u00100\u000E\u0006\u0003U\u0004\u0003\f\aTest CA"
|
238
|
+
asn = OpenSSL::ASN1.decode der
|
239
|
+
gn = R509::ASN1::GeneralName.new(asn)
|
240
|
+
gn.type.should == :directoryName
|
241
|
+
gn.value.to_s.should == '/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA'
|
242
|
+
end
|
243
|
+
it "errors on unimplemented type" do
|
244
|
+
# otherName type
|
245
|
+
der = "\xA0\u0014\u0006\u0003*\u0003\u0004\xA0\r\u0016\vHello World"
|
246
|
+
asn = OpenSSL::ASN1.decode der
|
247
|
+
expect { R509::ASN1::GeneralName.new(asn) }.to raise_error(R509::R509Error, "Unimplemented GeneralName tag: 0. At this time R509 does not support GeneralName types other than rfc822Name, dNSName, uniformResourceIdentifier, iPAddress, and directoryName")
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
describe R509::ASN1::GeneralNames do
|
252
|
+
it "adds items of allowed type to the object" do
|
253
|
+
asn = OpenSSL::ASN1.decode "\x82\u000Ewww.test.local"
|
254
|
+
asn2 = OpenSSL::ASN1.decode "\x81\u0011myemail@email.com"
|
255
|
+
asn3 = OpenSSL::ASN1.decode "\x82\u000Ewww.text.local"
|
256
|
+
gns = R509::ASN1::GeneralNames.new
|
257
|
+
gns.add_item(asn)
|
258
|
+
gns.add_item(asn2)
|
259
|
+
gns.add_item(asn3)
|
260
|
+
gns.dns_names.should == ["www.test.local","www.text.local"]
|
261
|
+
gns.rfc_822_names.should == ["myemail@email.com"]
|
262
|
+
end
|
263
|
+
it "errors on unimplemented type" do
|
264
|
+
# otherName type
|
265
|
+
gns = R509::ASN1::GeneralNames.new
|
266
|
+
der = "\xA0\u0014\u0006\u0003*\u0003\u0004\xA0\r\u0016\vHello World"
|
267
|
+
asn = OpenSSL::ASN1.decode der
|
268
|
+
expect { gns.add_item(asn) }.to raise_error(R509::R509Error, "Unimplemented GeneralName tag: 0. At this time R509 does not support GeneralName types other than rfc822Name, dNSName, uniformResourceIdentifier, iPAddress, and directoryName")
|
269
|
+
end
|
270
|
+
it "preserves order" do
|
271
|
+
asn = OpenSSL::ASN1.decode "\x82\u000Ewww.test.local"
|
272
|
+
asn2 = OpenSSL::ASN1.decode "\x81\u0011myemail@email.com"
|
273
|
+
asn3 = OpenSSL::ASN1.decode "\x82\u000Ewww.text.local"
|
274
|
+
gns = R509::ASN1::GeneralNames.new
|
275
|
+
gns.add_item(asn)
|
276
|
+
gns.add_item(asn2)
|
277
|
+
gns.add_item(asn3)
|
278
|
+
gns.names.count.should == 3
|
279
|
+
gns.names[0].type.should == :dNSName
|
280
|
+
gns.names[0].value.should == "www.test.local"
|
281
|
+
gns.names[1].type.should == :rfc822Name
|
282
|
+
gns.names[1].value.should == "myemail@email.com"
|
283
|
+
gns.names[2].type.should == :dNSName
|
284
|
+
gns.names[2].value.should == "www.text.local"
|
285
|
+
end
|
286
|
+
|
287
|
+
it "allows #uniq-ing of #names" do
|
288
|
+
gns = R509::ASN1::GeneralNames.new
|
289
|
+
gns.create_item(:tag => 1, :value => "test")
|
290
|
+
gns.create_item(:tag => 1, :value => "test")
|
291
|
+
gns.names.count.should == 2
|
292
|
+
gns.names.uniq.count.should == 1
|
293
|
+
end
|
294
|
+
|
295
|
+
it "errors with invalid params to #create_item" do
|
296
|
+
gns = R509::ASN1::GeneralNames.new
|
297
|
+
expect { gns.create_item({}) }.to raise_error(ArgumentError,'Must be a hash with (:tag or :type) and :value nodes')
|
298
|
+
end
|
299
|
+
|
300
|
+
it "allows addition of directoryNames with #create_item passing existing subject object" do
|
301
|
+
gns = R509::ASN1::GeneralNames.new
|
302
|
+
s = R509::Subject.new([['C','US'],['L','locality']])
|
303
|
+
gns.directory_names.size.should == 0
|
304
|
+
gns.create_item( :tag => 4, :value => s )
|
305
|
+
gns.directory_names.size.should == 1
|
306
|
+
end
|
307
|
+
it "allows addition of directoryNames with #create_item passing array" do
|
308
|
+
gns = R509::ASN1::GeneralNames.new
|
309
|
+
gns.directory_names.size.should == 0
|
310
|
+
gns.create_item( :tag => 4, :value => [['C','US'],['L','locality']] )
|
311
|
+
gns.directory_names.size.should == 1
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
describe R509::ASN1::PolicyInformation do
|
316
|
+
it "loads data with a policy oid but no qualifiers" do
|
317
|
+
data = OpenSSL::ASN1.decode "0\r\u0006\v`\x86H\u0001\xE09\u0001\u0002\u0003\u0004\u0001"
|
318
|
+
pi = R509::ASN1::PolicyInformation.new(data)
|
319
|
+
pi.policy_identifier.should == '2.16.840.1.12345.1.2.3.4.1'
|
320
|
+
pi.policy_qualifiers.should be_nil
|
321
|
+
end
|
322
|
+
it "loads data with a policy oid and a single qualifier" do
|
323
|
+
data = OpenSSL::ASN1.decode "0U\u0006\v`\x86H\u0001\xE09\u0001\u0002\u0003\u0004\u00010F0\"\u0006\b+\u0006\u0001\u0005\u0005\a\u0002\u0001\u0016\u0016http://example.com/cps0 \u0006\b+\u0006\u0001\u0005\u0005\a\u0002\u0001\u0016\u0014http://other.com/cps"
|
324
|
+
pi = R509::ASN1::PolicyInformation.new(data)
|
325
|
+
pi.policy_identifier.should == '2.16.840.1.12345.1.2.3.4.1'
|
326
|
+
pi.policy_qualifiers.cps_uris.empty?.should == false
|
327
|
+
pi.policy_qualifiers.user_notices.empty?.should == true
|
328
|
+
end
|
329
|
+
it "loads data with a policy oid and multiple qualifiers" do
|
330
|
+
data = OpenSSL::ASN1.decode "0\x81\x94\u0006\n`\x86H\u0001\x86\x8D\u001F\u0015\x81k0\x81\x850#\u0006\b+\u0006\u0001\u0005\u0005\a\u0002\u0001\u0016\u0017http://example.com/cps20;\u0006\b+\u0006\u0001\u0005\u0005\a\u0002\u00020/0\u0018\u0016\vanother org0\t\u0002\u0001\u0003\u0002\u0001\u0002\u0002\u0001\u0001\u001A\u0013this is a bad thing0!\u0006\b+\u0006\u0001\u0005\u0005\a\u0002\u00020\u0015\u001A\u0013another user notice"
|
331
|
+
pi = R509::ASN1::PolicyInformation.new(data)
|
332
|
+
pi.policy_identifier.should == '2.16.840.1.99999.21.235'
|
333
|
+
pi.policy_qualifiers.cps_uris.empty?.should == false
|
334
|
+
pi.policy_qualifiers.user_notices.empty?.should == false
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
describe R509::ASN1::PolicyQualifiers do
|
339
|
+
before :each do
|
340
|
+
@pq = R509::ASN1::PolicyQualifiers.new
|
341
|
+
end
|
342
|
+
|
343
|
+
it "initializes empty cps_uris and user_notices" do
|
344
|
+
@pq.should_not be_nil
|
345
|
+
@pq.cps_uris.empty?.should == true
|
346
|
+
@pq.user_notices.empty?.should == true
|
347
|
+
end
|
348
|
+
it "parses a cps qualifier and adds it to cps_uris" do
|
349
|
+
data = OpenSSL::ASN1.decode "0#\u0006\b+\u0006\u0001\u0005\u0005\a\u0002\u0001\u0016\u0017http://example.com/cps2"
|
350
|
+
@pq.parse(data)
|
351
|
+
@pq.cps_uris.should == ['http://example.com/cps2']
|
352
|
+
@pq.user_notices.should == []
|
353
|
+
end
|
354
|
+
it "parses a user notice and adds it to user_notices" do
|
355
|
+
data = OpenSSL::ASN1.decode "0!\u0006\b+\u0006\u0001\u0005\u0005\a\u0002\u00020\u0015\u001A\u0013another user notice"
|
356
|
+
@pq.parse(data)
|
357
|
+
@pq.cps_uris.should == []
|
358
|
+
@pq.user_notices.count.should == 1
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
describe R509::ASN1::UserNotice do
|
363
|
+
it "loads data with both a notice reference and explicit text" do
|
364
|
+
data = OpenSSL::ASN1.decode "0\u001F0\u0016\u0016\u0006my org0\f\u0002\u0001\u0001\u0002\u0001\u0002\u0002\u0001\u0003\u0002\u0001\u0004\u001A\u0005thing"
|
365
|
+
un = R509::ASN1::UserNotice.new(data)
|
366
|
+
un.notice_reference.should_not be_nil
|
367
|
+
un.explicit_text.should == 'thing'
|
368
|
+
end
|
369
|
+
it "loads data with a notice reference" do
|
370
|
+
data = OpenSSL::ASN1.decode "0\u00180\u0016\u0016\u0006my org0\f\u0002\u0001\u0001\u0002\u0001\u0002\u0002\u0001\u0003\u0002\u0001\u0004"
|
371
|
+
un = R509::ASN1::UserNotice.new(data)
|
372
|
+
un.notice_reference.should_not be_nil
|
373
|
+
un.explicit_text.should be_nil
|
374
|
+
end
|
375
|
+
it "loads data with an explicit text" do
|
376
|
+
data = OpenSSL::ASN1.decode "0\a\u001A\u0005thing"
|
377
|
+
un = R509::ASN1::UserNotice.new(data)
|
378
|
+
un.notice_reference.should be_nil
|
379
|
+
un.explicit_text.should == 'thing'
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
describe R509::ASN1::NoticeReference do
|
384
|
+
it "loads data with an org and no notice numbers" do
|
385
|
+
data = OpenSSL::ASN1.decode "0\n\u0016\u0006my org0\u0000"
|
386
|
+
nr = R509::ASN1::NoticeReference.new(data)
|
387
|
+
nr.organization.should == 'my org'
|
388
|
+
nr.notice_numbers.should == []
|
389
|
+
end
|
390
|
+
it "loads data with an org and 1 notice number" do
|
391
|
+
data = OpenSSL::ASN1.decode "0\r\u0016\u0006my org0\u0003\u0002\u0001\u0001"
|
392
|
+
nr = R509::ASN1::NoticeReference.new(data)
|
393
|
+
nr.organization.should == 'my org'
|
394
|
+
nr.notice_numbers.should == [1]
|
395
|
+
end
|
396
|
+
it "loads data with an org and more than 1 notice number" do
|
397
|
+
data = OpenSSL::ASN1.decode "0\u0016\u0016\u0006my org0\f\u0002\u0001\u0001\u0002\u0001\u0002\u0002\u0001\u0003\u0002\u0001\u0004"
|
398
|
+
nr = R509::ASN1::NoticeReference.new(data)
|
399
|
+
nr.organization.should == 'my org'
|
400
|
+
nr.notice_numbers.should == [1,2,3,4]
|
401
|
+
end
|
402
|
+
end
|