devpki 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 11f6846c98a3b3dbbe24f57d5fa4f4e619fa0587
4
+ data.tar.gz: b54ac7be253248ea001141cb5c501119b675b3f5
5
+ SHA512:
6
+ metadata.gz: e2d7d58b4895f5b63b4e8f319eab48d3a60c9c2feabc7ac2b4242299af17f2a34e9831205e2ebee88ee95983b065fbadef3f569a4cd9eef8a9bc048eb0007b03
7
+ data.tar.gz: 59fc8a36ffa80468cd8beb76a43fbc386f5e1495e6830b51e02f854e8660d200c64d394304f304d1ddad9756e5d6d266377577c7ee5431253141b1289b0ff841
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in devpki.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Jānis Kiršteins
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Jānis Kiršteins
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Devpki
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'devpki'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install devpki
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/a.cer ADDED
File without changes
data/b.cer ADDED
File without changes
data/bin/devpki ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'devpki'
4
+ require 'devpki/data_directory'
5
+
6
+ if not DevPKI::DataDirectory::platform_supported?
7
+ puts "ERROR: currently only OS X is supported. The application will now terminate."
8
+ abort
9
+ end
10
+
11
+ DevPKI::CLI.start
12
+
data/c.cer ADDED
File without changes
data/ca.crt ADDED
File without changes
data/ca2.crt ADDED
File without changes
data/d.cer ADDED
File without changes
data/devpki.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'devpki/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "devpki"
8
+ spec.version = DevPKI::VERSION
9
+ spec.authors = ["Jānis Kiršteins"]
10
+ spec.email = ["janis@montadigital.com"]
11
+ spec.description = "Tool for doing common PKI-related tasks"
12
+ spec.summary = "Tool for doing common PKI-related tasks"
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "thor"
22
+ spec.add_runtime_dependency "sqlite3"
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ end
data/lib/devpki/ca.rb ADDED
@@ -0,0 +1,122 @@
1
+ require 'devpki'
2
+ require 'devpki/data_directory'
3
+ require 'sqlite3'
4
+ require 'rubygems'
5
+ require 'openssl'
6
+
7
+ module DevPKI
8
+ class CA
9
+
10
+ attr_accessor :sqlite_db
11
+ attr_accessor :id
12
+
13
+ def initialize(id=0)
14
+ raise CADBError.new("CA ##{id} does not exist. It must be initialized first.") if not DevPKI::CA.exists?(id)
15
+
16
+ @sqlite_db = SQLite3::Database.open(DevPKI::CA.db_path(id))
17
+ @id = id
18
+ end
19
+
20
+ def self.delete(id)
21
+ raise InvalidOption.new("CA with ID #{id} does not exist.") if not self.exists?(id)
22
+ File.delete self.db_path(id)
23
+ end
24
+
25
+ # Initializes an empty CA database and generates a certificate for self
26
+ def self.init(id, name=nil, parent_ca_id=nil)
27
+ raise InvalidOption.new("CA with ID #{id} already exists!") if self.exists?(id)
28
+ raise InvalidOption.new("Parent CA with ID #{id} does not exist!") if parent_ca_id != nil and not self.exists?(parent_ca_id)
29
+
30
+ db = SQLite3::Database.new(self.db_path(id))
31
+
32
+ sql = <<-SQL
33
+ create table certificates (
34
+ id integer primary key autoincrement,
35
+ private_key_id integer not null,
36
+ pem text,
37
+
38
+ FOREIGN KEY(private_key_id) REFERENCES private_keys(id)
39
+ );
40
+
41
+ create table private_keys (
42
+ id integer primary key autoincrement,
43
+ pem text
44
+ );
45
+ SQL
46
+
47
+ db.execute_batch(sql)
48
+
49
+ if parent_ca_id != nil
50
+ raise InvalidOption.new("Parent CA with ID #{id} does not exist!") if not self.exists?(parent_ca_id)
51
+ puts "Exists: #{self.exists?(parent_ca_id)}"
52
+ parent_db = SQLite3::Database.open(self.db_path(parent_ca_id))
53
+
54
+ parent_ca_raw = parent_db.get_first_value( "select pem from certificates" )
55
+ parent_key_raw = parent_db.get_first_value( "select pem from private_keys" )
56
+
57
+ parent_ca_cert = OpenSSL::X509::Certificate.new parent_ca_raw
58
+ parent_ca_key = OpenSSL::PKey::RSA.new parent_key_raw
59
+ end
60
+
61
+ key = OpenSSL::PKey::RSA.new(2048)
62
+ public_key = key.public_key
63
+
64
+ name ||= "Generic DevPKI CA ##{id}"
65
+ subject = "/CN=#{name}"
66
+
67
+ cert = OpenSSL::X509::Certificate.new
68
+ cert.subject = OpenSSL::X509::Name.parse(subject)
69
+ if parent_ca_id == nil
70
+ cert.issuer = cert.subject
71
+ else
72
+ cert.issuer = parent_ca_cert.subject
73
+ end
74
+ cert.not_before = Time.now
75
+ cert.not_after = Time.now + 2 * 365 * 24 * 60 * 60
76
+ cert.public_key = public_key
77
+ cert.serial = Random.rand(1..100000)
78
+ cert.version = 2
79
+
80
+ ef = OpenSSL::X509::ExtensionFactory.new
81
+ ef.subject_certificate = cert
82
+
83
+ if parent_ca_id == nil
84
+ ef.issuer_certificate = cert
85
+ else
86
+ ef.issuer_certificate = parent_ca_cert
87
+ end
88
+
89
+ cert.extensions = [
90
+ ef.create_extension("basicConstraints","CA:TRUE", true),
91
+ ef.create_extension("subjectKeyIdentifier", "hash"),
92
+ ]
93
+ cert.add_extension ef.create_extension("authorityKeyIdentifier",
94
+ "keyid:always,issuer:always")
95
+
96
+ if parent_ca_id == nil
97
+ cert.sign key, OpenSSL::Digest::SHA512.new
98
+ else
99
+ cert.sign parent_ca_key, OpenSSL::Digest::SHA512.new
100
+ end
101
+
102
+ db.execute( "INSERT INTO private_keys (pem) VALUES ( ? )", key.to_pem )
103
+ private_key_id = db.last_insert_row_id
104
+
105
+ db.execute( "INSERT INTO certificates (private_key_id, pem) VALUES ( ?, ? )", private_key_id, cert.to_pem)
106
+
107
+ puts key.to_pem
108
+ puts cert.to_pem
109
+ end
110
+
111
+ # Checks if CA with given ID exists
112
+ def self.exists?(id)
113
+ File.exists?(self.db_path(id))
114
+ end
115
+
116
+ # Returns the path to a CA database
117
+ def self.db_path(id)
118
+ DevPKI::DataDirectory::absolute_path_for("ca_#{id}.db")
119
+ end
120
+
121
+ end
122
+ end
@@ -0,0 +1,17 @@
1
+ require 'devpki'
2
+ require 'thor'
3
+
4
+ module DevPKI
5
+ module SUBCLI
6
+ class CA < Thor
7
+
8
+ # Hack to override the help message produced by Thor.
9
+ # https://github.com/wycats/thor/issues/261#issuecomment-16880836
10
+ def self.banner(command, namespace = nil, subcommand = nil)
11
+ "#{basename} ca #{command.usage}"
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,28 @@
1
+ require 'devpki'
2
+ require 'thor'
3
+ require 'devpki/ca'
4
+ require 'devpki/data_directory'
5
+
6
+ module DevPKI
7
+ module SUBCLI
8
+ class CA < Thor
9
+ desc "delete <id> [-all]", "Delete a CA"
10
+ long_desc <<-LONGDESC
11
+ Deletes a certification authority (CA) and its database.
12
+
13
+ If ID is not given, it is assumed to be 0.
14
+
15
+ With option --all, all CA databases will be deleted.
16
+ LONGDESC
17
+ option :all, :type => :boolean
18
+ def delete(id=0)
19
+ if options[:all]
20
+ DevPKI::DataDirectory::reset_to_empty
21
+ else
22
+ DevPKI::CA.delete(id)
23
+ puts "CA database deleted."
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ require 'devpki'
2
+ require 'thor'
3
+ require 'devpki/ca'
4
+
5
+ module DevPKI
6
+ module SUBCLI
7
+ class CA < Thor
8
+ desc "init <id> [--name=<name>] [--with-parent=<id>]", "Create a new CA"
9
+ long_desc <<-LONGDESC
10
+ Initializes a new certification authority (CA) with given ID. The given ID must not already be in use
11
+ by another CA.
12
+
13
+ The ID provides a way to specify which CA you wish to target with other commands.
14
+ You may omit the <id> argument, if you wish, in which case it is assumed to be 'default'.
15
+
16
+ You only need to specify ID, if you plan to use multiple CAs.
17
+
18
+ If the --name option is given, the value will be included in the CA's commmon name.
19
+
20
+ If the option --with-parent is given, the CA will be created as a subordinate CA to the specified parent CA.
21
+ Without this option, the CA will be created as a root CA.
22
+ LONGDESC
23
+ option :name, :banner => "<name>", :desc => "Value to include in the CA's certificate common name"
24
+ option :"with-parent", :banner => "<id>", :desc => "ID of the parent CA. If ommitted, the CA will be created as a root CA"
25
+
26
+ def init(id="default")
27
+ DevPKI::CA.init(id, options[:name], options[:"with-parent"])
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,121 @@
1
+ require 'devpki'
2
+ require 'thor'
3
+ require 'net/http'
4
+
5
+ module DevPKI
6
+ class CLI < Thor
7
+ desc "ocsp [--method=get|post] --uri=<ocsp uri> ISSUER_CER_FILE:SUBJ_A.CER[,SUBJ_B.CER...]...", "Performs an OCSP query"
8
+ long_desc <<-LONGDESC
9
+ This command performs an OCSP query against the given OCSP URI, over HTTP. To perform
10
+ a query, at least 2 certificates are needed - the CA certificate and the subject certificate
11
+ file that is to be checked for revocation.
12
+
13
+ Only HTTP POST method is supported at the moment (RFC 2560).
14
+
15
+ EXAMPLE:
16
+
17
+ To test subj_a.cer (issuer certificate ca.cer) against http://ocsp.ca.com:
18
+
19
+ > $ devpki ocsp --uri=http://ocsp.ca.com ca.cer:subj_a.cer
20
+
21
+
22
+ LONGDESC
23
+ option :method, :default => "post", :banner => "get|post", :desc => "Method to use. GET as per RFC5019, or POST as per RFC2560. Defaults to POST."
24
+ option :uri, :banner => "<ocsp uri>", :required => true, :desc => "OCSP responder URI."
25
+
26
+ def ocsp(*cer_files)
27
+
28
+ raise InvalidOption.new("Please specify at least one CA and subject certificate file.") if cer_files.empty?
29
+
30
+ ca_subj_map = {}
31
+ cer_files.each do |ca_subj_pair|
32
+ raise InvalidOption.new("\"#{ca_subj_pair}\" is an invalid CA and subject pair. Please pass a pair with format similar to \"ca.cer:a.cer[,b.cer...]\"") if not ca_subj_pair.include?(":")
33
+
34
+ ca_subjlist_split = ca_subj_pair.split(":")
35
+
36
+ ca_file = ca_subjlist_split.first
37
+
38
+ raise InvalidOption.new("No subject certificates specified for CA file \"#{ca_file}\". Please pass a pair with format similar to \"ca.cer:a.cer[,b.cer...]\"") if ca_subjlist_split.length != 2
39
+ subj_files = ca_subjlist_split.last.split(",")
40
+
41
+ ca_subj_map[ca_file] = subj_files
42
+ end
43
+
44
+ ca_subj_map.each_pair do |ca_file,subj_file_list|
45
+ raise InvalidOption.new("CA certificate file \"#{ca_file}\" does not exist.") if not File.exist?(ca_file)
46
+ subj_file_list.each do |subj_file|
47
+ raise InvalidOption.new("Subject certificate file \"#{subj_file}\" does not exist.") if not File.exist?(subj_file)
48
+ end
49
+ end
50
+
51
+ method = options[:method].upcase
52
+ raise InvalidOption.new("GET method not implemented yet.") if method == "GET"
53
+
54
+ ###### -------------- move this to DevPKI::OCSP
55
+
56
+ cert_ids = []
57
+ store = OpenSSL::X509::Store.new
58
+
59
+ ca_subj_map.each_pair do |ca_file, subj_file_list|
60
+ ca_cert = OpenSSL::X509::Certificate.new File.read(ca_file)
61
+ store.add_cert(ca_cert)
62
+
63
+ subj_file_list.each do |subj_file|
64
+ subj_cert = OpenSSL::X509::Certificate.new File.read(subj_file)
65
+
66
+ cert_ids << OpenSSL::OCSP::CertificateId.new(subj_cert, ca_cert)
67
+ end
68
+ end
69
+
70
+ request = OpenSSL::OCSP::Request.new
71
+ cert_ids.each do |cert_id|
72
+ request.add_certid(cert_id)
73
+ end
74
+
75
+ request_uri = URI(options[:uri])
76
+
77
+ http_req = Net::HTTP::Post.new(request_uri.path)
78
+ http_req.content_type = "application/ocsp-request"
79
+ http_req.body = request.to_der
80
+
81
+ http_response = Net::HTTP.new(request_uri.host, request_uri.port).start do |http|
82
+ http.request(http_req)
83
+ end
84
+
85
+ ## ----
86
+
87
+ if http_response.code != "200"
88
+ raise StandardError, "Invalid response code from OCSP responder: #{http_response.code}"
89
+ end
90
+
91
+ response = OpenSSL::OCSP::Response.new(http_response.body)
92
+ puts "Status: #{response.status}"
93
+ puts "Status string: #{response.status_string}"
94
+
95
+ if response.status != 0
96
+ raise StandardError, "Not a successful status"
97
+ end
98
+ if response.basic[0][0].serial != cert.serial
99
+ raise StandardError, "Not the same serial"
100
+ end
101
+ if response.basic[0][1] != 0 # 0 is good, 1 is revoked, 2 is unknown.
102
+ raise StandardError, "Not a good status"
103
+ end
104
+ current_time = Time.now
105
+ if response.basic[0][4] > current_time or response.basic[0][5] < current_time
106
+ raise StandardError, "The response is not within its validity window"
107
+ end
108
+
109
+ # we also need to verify that the OCSP response is signed by
110
+ # a certificate that is allowed and chains up to a trusted root.
111
+ # To do this you'll need to build an OpenSSL::X509::Store object
112
+ # that contains the certificate you're checking + intermediates + root.
113
+
114
+ if response.basic.verify([],store) != true
115
+ raise StandardError, "Response not signed by a trusted certificate"
116
+ end
117
+
118
+ end
119
+ end
120
+
121
+ end
data/lib/devpki/cli.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'thor'
2
+
3
+ require 'devpki'
4
+ require 'devpki/cli/ca/init'
5
+ require 'devpki/cli/ca/delete'
6
+ require 'devpki/cli/ca/_hack'
7
+
8
+ require 'devpki/cli/ocsp'
9
+
10
+ module DevPKI
11
+ class CLI < Thor
12
+ desc "ca [<id>] <command> [<args>]", "PKI CA functionality"
13
+ subcommand "ca", DevPKI::SUBCLI::CA
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ require 'devpki'
2
+ require 'fileutils'
3
+
4
+ Dir["lib/devpki/cli/**/*.rb"].each {|file| require file[4..-1] }
5
+
6
+ module DevPKI
7
+ class DataDirectory
8
+
9
+ # Only support OSX atm
10
+ def self.platform_supported?
11
+ (/darwin/ =~ RUBY_PLATFORM) != nil
12
+ end
13
+
14
+ def self.reset_to_empty
15
+ FileUtils.rm_rf(self.absolute_path)
16
+ self.get
17
+ end
18
+
19
+ def self.absolute_path
20
+ File.expand_path("~/Library/Application Support/devpki")
21
+ end
22
+
23
+ def self.absolute_path_for(file_name)
24
+ File.expand_path(file_name, self.absolute_path)
25
+ end
26
+
27
+ def self.get
28
+ if not Dir.exists?(self.absolute_path)
29
+ Dir.mkdir(self.absolute_path)
30
+ end
31
+ Dir.new(self.absolute_path)
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ module DevPKI
2
+ VERSION = "0.0.1"
3
+ end
data/lib/devpki.rb ADDED
@@ -0,0 +1,14 @@
1
+ require "devpki/version"
2
+
3
+ module DevPKI
4
+ autoload :CLI, 'devpki/cli'
5
+
6
+ class DevPKIError < StandardError
7
+ def self.status_code(code)
8
+ define_method(:status_code) { code }
9
+ end
10
+ end
11
+
12
+ class InvalidOption < DevPKIError; status_code(10) ; end
13
+ class CADBError < DevPKIError; status_code(11) ; end
14
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: devpki
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jānis Kiršteins
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
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: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Tool for doing common PKI-related tasks
70
+ email:
71
+ - janis@montadigital.com
72
+ executables:
73
+ - devpki
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - LICENSE
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - a.cer
84
+ - b.cer
85
+ - bin/devpki
86
+ - c.cer
87
+ - ca.crt
88
+ - ca2.crt
89
+ - d.cer
90
+ - devpki.gemspec
91
+ - lib/devpki.rb
92
+ - lib/devpki/ca.rb
93
+ - lib/devpki/cli.rb
94
+ - lib/devpki/cli/ca/_hack.rb
95
+ - lib/devpki/cli/ca/delete.rb
96
+ - lib/devpki/cli/ca/init.rb
97
+ - lib/devpki/cli/ocsp.rb
98
+ - lib/devpki/data_directory.rb
99
+ - lib/devpki/version.rb
100
+ homepage: ''
101
+ licenses:
102
+ - MIT
103
+ metadata: {}
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 2.1.9
121
+ signing_key:
122
+ specification_version: 4
123
+ summary: Tool for doing common PKI-related tasks
124
+ test_files: []