certificate_authority 0.1.5 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +26 -0
  3. data/.gitignore +6 -0
  4. data/.rspec +3 -0
  5. data/Gemfile +2 -8
  6. data/Gemfile.lock +71 -27
  7. data/README.rdoc +91 -2
  8. data/Rakefile +6 -41
  9. data/certificate_authority.gemspec +22 -83
  10. data/lib/certificate_authority/certificate.rb +139 -49
  11. data/lib/certificate_authority/certificate_revocation_list.rb +34 -14
  12. data/lib/certificate_authority/core_extensions.rb +46 -0
  13. data/lib/certificate_authority/distinguished_name.rb +64 -16
  14. data/lib/certificate_authority/extensions.rb +417 -45
  15. data/lib/certificate_authority/key_material.rb +30 -9
  16. data/lib/certificate_authority/ocsp_handler.rb +75 -5
  17. data/lib/certificate_authority/pkcs11_key_material.rb +0 -2
  18. data/lib/certificate_authority/revocable.rb +14 -0
  19. data/lib/certificate_authority/serial_number.rb +15 -2
  20. data/lib/certificate_authority/signing_request.rb +91 -0
  21. data/lib/certificate_authority/validations.rb +31 -0
  22. data/lib/certificate_authority/version.rb +3 -0
  23. data/lib/certificate_authority.rb +6 -5
  24. metadata +76 -71
  25. data/VERSION.yml +0 -5
  26. data/spec/spec_helper.rb +0 -4
  27. data/spec/units/certificate_authority_spec.rb +0 -4
  28. data/spec/units/certificate_revocation_list_spec.rb +0 -68
  29. data/spec/units/certificate_spec.rb +0 -428
  30. data/spec/units/distinguished_name_spec.rb +0 -59
  31. data/spec/units/extensions_spec.rb +0 -115
  32. data/spec/units/key_material_spec.rb +0 -100
  33. data/spec/units/ocsp_handler_spec.rb +0 -104
  34. data/spec/units/pkcs11_key_material_spec.rb +0 -41
  35. data/spec/units/serial_number_spec.rb +0 -20
  36. data/spec/units/signing_entity_spec.rb +0 -4
  37. data/spec/units/units_helper.rb +0 -1
@@ -1,6 +1,74 @@
1
1
  module CertificateAuthority
2
+ class OCSPResponseBuilder
3
+ attr_accessor :ocsp_response
4
+ attr_accessor :verification_mechanism
5
+ attr_accessor :ocsp_request_reader
6
+ attr_accessor :parent
7
+ attr_accessor :next_update
8
+
9
+ GOOD = OpenSSL::OCSP::V_CERTSTATUS_GOOD
10
+ REVOKED = OpenSSL::OCSP::V_CERTSTATUS_REVOKED
11
+
12
+ NO_REASON=0
13
+ KEY_COMPROMISED=OpenSSL::OCSP::REVOKED_STATUS_KEYCOMPROMISE
14
+ UNSPECIFIED=OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED
15
+
16
+ def build_response()
17
+ raise "Requires a parent for signing" if @parent.nil?
18
+ if @verification_mechanism.nil?
19
+ ## If no verification callback is provided we're marking it GOOD
20
+ @verification_mechanism = lambda {|cert_id| [GOOD,NO_REASON] }
21
+ end
22
+
23
+ @ocsp_request_reader.ocsp_request.certid.each do |cert_id|
24
+ result,reason = verification_mechanism.call(cert_id.serial)
25
+
26
+ ## cert_id, status, reason, rev_time, this update, next update, ext
27
+ ## - unit of time is seconds
28
+ ## - rev_time is currently set to "now"
29
+ @ocsp_response.add_status(cert_id,
30
+ result, reason,
31
+ 0, 0, @next_update, nil)
32
+ end
33
+
34
+ @ocsp_response.sign(OpenSSL::X509::Certificate.new(@parent.to_pem), @parent.key_material.private_key, nil, nil)
35
+ OpenSSL::OCSP::Response.create(OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL, @ocsp_response)
36
+ end
37
+
38
+ def self.from_request_reader(request_reader,verification_mechanism=nil)
39
+ response_builder = OCSPResponseBuilder.new
40
+ response_builder.ocsp_request_reader = request_reader
41
+
42
+ ocsp_response = OpenSSL::OCSP::BasicResponse.new
43
+ ocsp_response.copy_nonce(request_reader.ocsp_request)
44
+ response_builder.ocsp_response = ocsp_response
45
+ response_builder.next_update = 60*15 #Default of 15 minutes
46
+ response_builder
47
+ end
48
+ end
49
+
50
+ class OCSPRequestReader
51
+ attr_accessor :raw_ocsp_request
52
+ attr_accessor :ocsp_request
53
+
54
+ def serial_numbers
55
+ @ocsp_request.certid.collect do |cert_id|
56
+ cert_id.serial
57
+ end
58
+ end
59
+
60
+ def self.from_der(request_body)
61
+ reader = OCSPRequestReader.new
62
+ reader.raw_ocsp_request = request_body
63
+ reader.ocsp_request = OpenSSL::OCSP::Request.new(request_body)
64
+
65
+ reader
66
+ end
67
+ end
68
+
69
+ ## DEPRECATED
2
70
  class OCSPHandler
3
- include ActiveModel::Validations
71
+ include Validations
4
72
 
5
73
  attr_accessor :ocsp_request
6
74
  attr_accessor :certificate_ids
@@ -10,10 +78,10 @@ module CertificateAuthority
10
78
 
11
79
  attr_accessor :ocsp_response_body
12
80
 
13
- validate do |crl|
81
+ def validate
14
82
  errors.add :parent, "A parent entity must be set" if parent.nil?
83
+ all_certificates_available
15
84
  end
16
- validate :all_certificates_available
17
85
 
18
86
  def initialize
19
87
  self.certificates = {}
@@ -24,9 +92,11 @@ module CertificateAuthority
24
92
  end
25
93
 
26
94
  def extract_certificate_serials
27
- raise "No valid OCSP request was supplied" if self.ocsp_request.nil?
28
- openssl_request = OpenSSL::OCSP::Request.new(self.ocsp_request)
95
+ openssl_request = OpenSSL::OCSP::Request.new(@ocsp_request)
29
96
 
97
+ if openssl_request.certid.nil?
98
+ raise "Invalid openssl request"
99
+ end
30
100
  self.certificate_ids = openssl_request.certid.collect do |cert_id|
31
101
  cert_id.serial
32
102
  end
@@ -1,8 +1,6 @@
1
1
  module CertificateAuthority
2
2
  class Pkcs11KeyMaterial
3
3
  include KeyMaterial
4
- include ActiveModel::Validations
5
- include ActiveModel::Serialization
6
4
 
7
5
  attr_accessor :engine
8
6
  attr_accessor :token_id
@@ -0,0 +1,14 @@
1
+ module CertificateAuthority
2
+ module Revocable
3
+ attr_accessor :revoked_at
4
+
5
+ def revoke!(time=Time.now)
6
+ @revoked_at = time
7
+ end
8
+
9
+ def revoked?
10
+ # If we have a time, then we're revoked
11
+ !@revoked_at.nil?
12
+ end
13
+ end
14
+ end
@@ -1,9 +1,22 @@
1
+ require 'securerandom'
2
+
1
3
  module CertificateAuthority
2
4
  class SerialNumber
3
- include ActiveModel::Validations
5
+ include Validations
6
+ include Revocable
4
7
 
5
8
  attr_accessor :number
6
9
 
7
- validates :number, :presence => true, :numericality => {:greater_than => 0}
10
+ def validate
11
+ if self.number.nil?
12
+ errors.add :number, "must not be empty"
13
+ elsif self.number.to_i <= 0
14
+ errors.add :number, "must be greater than zero"
15
+ end
16
+ end
17
+
18
+ def initialize
19
+ self.number = SecureRandom.random_number(2**128-1)
20
+ end
8
21
  end
9
22
  end
@@ -0,0 +1,91 @@
1
+ module CertificateAuthority
2
+ class SigningRequest
3
+ attr_accessor :distinguished_name
4
+ attr_accessor :key_material
5
+ attr_accessor :raw_body
6
+ attr_accessor :openssl_csr
7
+ attr_accessor :digest
8
+ attr_accessor :attributes
9
+
10
+ def initialize()
11
+ @attributes = []
12
+ end
13
+
14
+ # Fake attribute for convenience because adding
15
+ # alternative names on a CSR is remarkably non-trivial.
16
+ def subject_alternative_names=(alt_names)
17
+ raise "alt_names must be an Array" unless alt_names.is_a?(Array)
18
+
19
+ factory = OpenSSL::X509::ExtensionFactory.new
20
+ name_list = alt_names.map{|m| "DNS:#{m}"}.join(",")
21
+ ext = factory.create_ext("subjectAltName",name_list,false)
22
+ ext_set = OpenSSL::ASN1::Set([OpenSSL::ASN1::Sequence([ext])])
23
+ attr = OpenSSL::X509::Attribute.new("extReq", ext_set)
24
+ @attributes << attr
25
+ end
26
+
27
+ def read_attributes_by_oid(*oids)
28
+ attributes.detect { |a| oids.include?(a.oid) }
29
+ end
30
+ protected :read_attributes_by_oid
31
+
32
+ def to_cert
33
+ cert = Certificate.new
34
+ if !@distinguished_name.nil?
35
+ cert.distinguished_name = @distinguished_name
36
+ end
37
+ cert.key_material = @key_material
38
+ if attribute = read_attributes_by_oid('extReq', 'msExtReq')
39
+ set = OpenSSL::ASN1.decode(attribute.value)
40
+ seq = set.value.first
41
+ seq.value.collect { |asn1ext| OpenSSL::X509::Extension.new(asn1ext).to_a }.each do |o, v, c|
42
+ Certificate::EXTENSIONS.each do |klass|
43
+ cert.extensions[klass::OPENSSL_IDENTIFIER] = klass.parse(v, c) if v && klass::OPENSSL_IDENTIFIER == o
44
+ end
45
+ end
46
+ end
47
+ cert
48
+ end
49
+
50
+ def to_pem
51
+ to_x509_csr.to_pem
52
+ end
53
+
54
+ def to_x509_csr
55
+ raise "Must specify a DN/subject on csr" if @distinguished_name.nil?
56
+ raise "Invalid DN in request" unless @distinguished_name.valid?
57
+ raise "CSR must have key material" if @key_material.nil?
58
+ raise "CSR must include a public key on key material" if @key_material.public_key.nil?
59
+ raise "Need a private key on key material for CSR generation" if @key_material.private_key.nil?
60
+
61
+ opensslcsr = OpenSSL::X509::Request.new
62
+ opensslcsr.subject = @distinguished_name.to_x509_name
63
+ opensslcsr.public_key = @key_material.public_key
64
+ opensslcsr.attributes = @attributes unless @attributes.nil?
65
+ opensslcsr.sign @key_material.private_key, OpenSSL::Digest.new(@digest || "SHA512")
66
+ opensslcsr
67
+ end
68
+
69
+ def self.from_x509_csr(raw_csr)
70
+ csr = SigningRequest.new
71
+ openssl_csr = OpenSSL::X509::Request.new(raw_csr)
72
+ csr.distinguished_name = DistinguishedName.from_openssl openssl_csr.subject
73
+ csr.raw_body = raw_csr
74
+ csr.openssl_csr = openssl_csr
75
+ csr.attributes = openssl_csr.attributes
76
+ key_material = SigningRequestKeyMaterial.new
77
+ key_material.public_key = openssl_csr.public_key
78
+ csr.key_material = key_material
79
+ csr
80
+ end
81
+
82
+ def self.from_netscape_spkac(raw_spkac)
83
+ openssl_spkac = OpenSSL::Netscape::SPKI.new raw_spkac
84
+ csr = SigningRequest.new
85
+ csr.raw_body = raw_spkac
86
+ key_material = SigningRequestKeyMaterial.new
87
+ key_material.public_key = openssl_spkac.public_key
88
+ csr
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,31 @@
1
+ #
2
+ # This is a super simple replacement for ActiveSupport::Validations
3
+ #
4
+
5
+ module CertificateAuthority
6
+ class Errors < Array
7
+ def add(symbol, msg)
8
+ self.push([symbol, msg])
9
+ end
10
+ def full_messages
11
+ self.map {|i| i[0].to_s + ": " + i[1]}.join("\n")
12
+ end
13
+ end
14
+
15
+ module Validations
16
+ def valid?
17
+ @errors = Errors.new
18
+ validate
19
+ errors.empty?
20
+ end
21
+
22
+ # must be overridden
23
+ def validate
24
+ raise NotImplementedError
25
+ end
26
+
27
+ def errors
28
+ @errors ||= Errors.new
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module CertificateAuthority
2
+ VERSION = '1.1.0'.freeze
3
+ end
@@ -1,11 +1,11 @@
1
- $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
-
3
- #Exterior requirements
1
+ # Exterior requirements
4
2
  require 'openssl'
5
- require 'active_model'
6
3
 
7
- #Internal modules
4
+ # Internal modules
5
+ require 'certificate_authority/core_extensions'
8
6
  require 'certificate_authority/signing_entity'
7
+ require 'certificate_authority/revocable'
8
+ require 'certificate_authority/validations'
9
9
  require 'certificate_authority/distinguished_name'
10
10
  require 'certificate_authority/serial_number'
11
11
  require 'certificate_authority/key_material'
@@ -14,6 +14,7 @@ require 'certificate_authority/extensions'
14
14
  require 'certificate_authority/certificate'
15
15
  require 'certificate_authority/certificate_revocation_list'
16
16
  require 'certificate_authority/ocsp_handler'
17
+ require 'certificate_authority/signing_request'
17
18
 
18
19
  module CertificateAuthority
19
20
  end
metadata CHANGED
@@ -1,134 +1,139 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: certificate_authority
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
5
- prerelease:
4
+ version: 1.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Chris Chandler
9
- autorequire:
8
+ autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-08-12 00:00:00.000000000 Z
11
+ date: 2022-06-30 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- name: activemodel
16
- requirement: &70219917934620 !ruby/object:Gem::Requirement
17
- none: false
14
+ name: coveralls
15
+ requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
- - - ~>
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
- version: 3.0.6
22
- type: :runtime
19
+ version: '0'
20
+ type: :development
23
21
  prerelease: false
24
- version_requirements: *70219917934620
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
25
27
  - !ruby/object:Gem::Dependency
26
- name: rspec
27
- requirement: &70219917933580 !ruby/object:Gem::Requirement
28
- none: false
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
29
44
  requirements:
30
- - - ! '>='
45
+ - - ">="
31
46
  - !ruby/object:Gem::Version
32
47
  version: '0'
33
48
  type: :development
34
49
  prerelease: false
35
- version_requirements: *70219917933580
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
36
55
  - !ruby/object:Gem::Dependency
37
- name: jeweler
38
- requirement: &70219917932340 !ruby/object:Gem::Requirement
39
- none: false
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
40
58
  requirements:
41
- - - ~>
59
+ - - ">="
42
60
  - !ruby/object:Gem::Version
43
- version: 1.5.2
61
+ version: '0'
44
62
  type: :development
45
63
  prerelease: false
46
- version_requirements: *70219917932340
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
47
69
  - !ruby/object:Gem::Dependency
48
- name: rcov
49
- requirement: &70219917931200 !ruby/object:Gem::Requirement
50
- none: false
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
51
72
  requirements:
52
- - - ! '>='
73
+ - - ">="
53
74
  - !ruby/object:Gem::Version
54
75
  version: '0'
55
76
  type: :development
56
77
  prerelease: false
57
- version_requirements: *70219917931200
58
- description:
59
- email: chris@flatterline.com
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description:
84
+ email:
85
+ - squanderingtime@gmail.com
60
86
  executables: []
61
87
  extensions: []
62
- extra_rdoc_files:
63
- - README.rdoc
88
+ extra_rdoc_files: []
64
89
  files:
90
+ - ".github/workflows/ci.yml"
91
+ - ".gitignore"
92
+ - ".rspec"
65
93
  - Gemfile
66
94
  - Gemfile.lock
67
95
  - README.rdoc
68
96
  - Rakefile
69
- - VERSION.yml
70
97
  - certificate_authority.gemspec
71
98
  - lib/certificate_authority.rb
72
99
  - lib/certificate_authority/certificate.rb
73
100
  - lib/certificate_authority/certificate_revocation_list.rb
101
+ - lib/certificate_authority/core_extensions.rb
74
102
  - lib/certificate_authority/distinguished_name.rb
75
103
  - lib/certificate_authority/extensions.rb
76
104
  - lib/certificate_authority/key_material.rb
77
105
  - lib/certificate_authority/ocsp_handler.rb
78
106
  - lib/certificate_authority/pkcs11_key_material.rb
107
+ - lib/certificate_authority/revocable.rb
79
108
  - lib/certificate_authority/serial_number.rb
80
109
  - lib/certificate_authority/signing_entity.rb
110
+ - lib/certificate_authority/signing_request.rb
111
+ - lib/certificate_authority/validations.rb
112
+ - lib/certificate_authority/version.rb
81
113
  - lib/tasks/certificate_authority.rake
82
- - spec/spec_helper.rb
83
- - spec/units/certificate_authority_spec.rb
84
- - spec/units/certificate_revocation_list_spec.rb
85
- - spec/units/certificate_spec.rb
86
- - spec/units/distinguished_name_spec.rb
87
- - spec/units/extensions_spec.rb
88
- - spec/units/key_material_spec.rb
89
- - spec/units/ocsp_handler_spec.rb
90
- - spec/units/pkcs11_key_material_spec.rb
91
- - spec/units/serial_number_spec.rb
92
- - spec/units/signing_entity_spec.rb
93
- - spec/units/units_helper.rb
94
- homepage: http://github.com/cchandler/certificate_authority
114
+ homepage: https://github.com/cchandler/certificate_authority
95
115
  licenses:
96
116
  - MIT
97
- post_install_message:
117
+ metadata:
118
+ homepage_uri: https://github.com/cchandler/certificate_authority
119
+ source_code_uri: https://github.com/cchandler/certificate_authority
120
+ post_install_message:
98
121
  rdoc_options: []
99
122
  require_paths:
100
123
  - lib
101
124
  required_ruby_version: !ruby/object:Gem::Requirement
102
- none: false
103
125
  requirements:
104
- - - ! '>='
126
+ - - ">="
105
127
  - !ruby/object:Gem::Version
106
- version: '0'
107
- segments:
108
- - 0
109
- hash: -4255291266010713520
128
+ version: '2.4'
110
129
  required_rubygems_version: !ruby/object:Gem::Requirement
111
- none: false
112
130
  requirements:
113
- - - ! '>='
131
+ - - ">="
114
132
  - !ruby/object:Gem::Version
115
133
  version: '0'
116
134
  requirements: []
117
- rubyforge_project:
118
- rubygems_version: 1.8.15
119
- signing_key:
120
- specification_version: 3
135
+ rubygems_version: 3.3.7
136
+ signing_key:
137
+ specification_version: 4
121
138
  summary: Ruby gem for managing the core functions outlined in RFC-3280 for PKI
122
- test_files:
123
- - spec/spec_helper.rb
124
- - spec/units/certificate_authority_spec.rb
125
- - spec/units/certificate_revocation_list_spec.rb
126
- - spec/units/certificate_spec.rb
127
- - spec/units/distinguished_name_spec.rb
128
- - spec/units/extensions_spec.rb
129
- - spec/units/key_material_spec.rb
130
- - spec/units/ocsp_handler_spec.rb
131
- - spec/units/pkcs11_key_material_spec.rb
132
- - spec/units/serial_number_spec.rb
133
- - spec/units/signing_entity_spec.rb
134
- - spec/units/units_helper.rb
139
+ test_files: []
data/VERSION.yml DELETED
@@ -1,5 +0,0 @@
1
- ---
2
- :major: 0
3
- :minor: 1
4
- :patch: 5
5
- :build:
data/spec/spec_helper.rb DELETED
@@ -1,4 +0,0 @@
1
- require 'rubygems'
2
- require 'rspec'
3
-
4
- require File.dirname(__FILE__) + '/../lib/certificate_authority'
@@ -1,4 +0,0 @@
1
- require File.dirname(__FILE__) + '/units_helper'
2
-
3
- describe CertificateAuthority do
4
- end
@@ -1,68 +0,0 @@
1
- require File.dirname(__FILE__) + '/units_helper'
2
-
3
- describe CertificateAuthority::CertificateRevocationList do
4
- before(:each) do
5
- @crl = CertificateAuthority::CertificateRevocationList.new
6
-
7
- @root_certificate = CertificateAuthority::Certificate.new
8
- @root_certificate.signing_entity = true
9
- @root_certificate.subject.common_name = "CRL Root"
10
- @root_certificate.key_material.generate_key(1024)
11
- @root_certificate.serial_number.number = 1
12
- @root_certificate.sign!
13
-
14
- @certificate = CertificateAuthority::Certificate.new
15
- @certificate.key_material.generate_key(1024)
16
- @certificate.subject.common_name = "http://bogusSite.com"
17
- @certificate.parent = @root_certificate
18
- @certificate.serial_number.number = 2
19
- @certificate.sign!
20
-
21
- @crl.parent = @root_certificate
22
- @certificate.revoked_at = Time.now
23
- end
24
-
25
- it "should accept a list of certificates" do
26
- @crl << @certificate
27
- end
28
-
29
- it "should complain if you add a certificate without a revocation time" do
30
- @certificate.revoked_at = nil
31
- lambda{ @crl << @certificate}.should raise_error
32
- end
33
-
34
- it "should have a 'parent' that will be responsible for signing" do
35
- @crl.parent = @root_certificate
36
- @crl.parent.should_not be_nil
37
- end
38
-
39
- it "should raise an error if you try and sign a CRL without attaching a parent" do
40
- @crl.parent = nil
41
- lambda { @crl.sign! }.should raise_error
42
- end
43
-
44
- it "should be able to generate a proper CRL" do
45
- @crl << @certificate
46
- lambda {@crl.to_pem}.should raise_error
47
- @crl.parent = @root_certificate
48
- @crl.sign!
49
- @crl.to_pem.should_not be_nil
50
- OpenSSL::X509::CRL.new(@crl.to_pem).should_not be_nil
51
- end
52
-
53
- describe "Next update" do
54
- it "should be able to set a 'next_update' value" do
55
- @crl.next_update = (60 * 60 * 10) # 10 Hours
56
- @crl.next_update.should_not be_nil
57
- end
58
-
59
- it "should throw an error if we try and sign up with a negative next_update" do
60
- @crl.sign!
61
- @crl.next_update = - (60 * 60 * 10)
62
- lambda{@crl.sign!}.should raise_error
63
- end
64
-
65
- end
66
-
67
-
68
- end