eassl 0.1.1635
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 +2 -0
- data/Rakefile +45 -0
- data/lib/eassl/authority_certificate.rb +43 -0
- data/lib/eassl/certificate.rb +65 -0
- data/lib/eassl/certificate_authority.rb +21 -0
- data/lib/eassl/certificate_name.rb +33 -0
- data/lib/eassl/key.rb +64 -0
- data/lib/eassl/signing_request.rb +51 -0
- data/lib/eassl.rb +35 -0
- metadata +54 -0
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require 'fileutils'
|
7
|
+
include FileUtils
|
8
|
+
|
9
|
+
REV = File.read(".svn/entries")[/committed-rev="(\d+)"/, 1] rescue nil
|
10
|
+
VERS = ENV['VERSION'] || "0.1" + (REV ? ".#{REV}" : "")
|
11
|
+
|
12
|
+
task :default => [:package]
|
13
|
+
|
14
|
+
#setup_tests
|
15
|
+
|
16
|
+
summary = "EaSSL is a library aimed at making openSSL certificate generation and management easier and more ruby-ish."
|
17
|
+
dependencies = []
|
18
|
+
spec = Gem::Specification.new do |s|
|
19
|
+
s.name = "eassl"
|
20
|
+
s.version = VERS
|
21
|
+
s.platform = Gem::Platform::RUBY
|
22
|
+
s.author = "Paul Nicholson"
|
23
|
+
s.summary = summary
|
24
|
+
# s.test_file = "test/test_eassl.rb"
|
25
|
+
s.has_rdoc = true
|
26
|
+
s.extra_rdoc_files = [ "README" ]
|
27
|
+
dependencies.each do |dep|
|
28
|
+
s.add_dependency(*dep)
|
29
|
+
end
|
30
|
+
s.files = %w(README Rakefile) +
|
31
|
+
Dir.glob("{bin,doc,test,lib}/**/*")
|
32
|
+
|
33
|
+
s.require_path = "lib"
|
34
|
+
s.autorequire = "eassl"
|
35
|
+
end
|
36
|
+
|
37
|
+
Rake::GemPackageTask.new(spec) do |p|
|
38
|
+
p.gem_spec = spec
|
39
|
+
p.need_tar = true
|
40
|
+
end
|
41
|
+
|
42
|
+
task :install do
|
43
|
+
sh %{rake package}
|
44
|
+
sh %{gem install pkg/eassl-#{VERS}}
|
45
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'eassl'
|
3
|
+
module EaSSL
|
4
|
+
# Author:: Paul Nicholson (mailto:paul@webpowerdesign.net)
|
5
|
+
# Co-Author:: Adam Williams (mailto:adam@thewilliams.ws)
|
6
|
+
# Copyright:: Copyright (c) 2006 WebPower Design
|
7
|
+
# License:: Distributes under the same terms as Ruby
|
8
|
+
class AuthorityCertificate
|
9
|
+
def initialize(options)
|
10
|
+
@options = {
|
11
|
+
:key => nil, #required
|
12
|
+
:name => {}, #required, CertificateName
|
13
|
+
}.update(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def ssl
|
17
|
+
cert = OpenSSL::X509::Certificate.new
|
18
|
+
cert.not_before = Time.now
|
19
|
+
cert.subject = cert.issuer = CertificateName.new({ :common_name => "CA" }.update(@options[:name])).ssl
|
20
|
+
cert.not_after = cert.not_before + (365 * 5) * 24 * 60 * 60
|
21
|
+
cert.public_key = @options[:key].public_key
|
22
|
+
cert.serial = 1
|
23
|
+
cert.version = 2 # X509v3
|
24
|
+
|
25
|
+
ef = OpenSSL::X509::ExtensionFactory.new
|
26
|
+
ef.subject_certificate = cert
|
27
|
+
ef.issuer_certificate = cert
|
28
|
+
cert.extensions = [
|
29
|
+
ef.create_extension("basicConstraints","CA:TRUE"),
|
30
|
+
ef.create_extension("keyUsage", "cRLSign, keyCertSign"),
|
31
|
+
ef.create_extension("subjectKeyIdentifier", "hash"),
|
32
|
+
ef.create_extension("nsComment", "Ruby/OpenSSL/EaSSL Generated Certificate"),
|
33
|
+
]
|
34
|
+
cert.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always"))
|
35
|
+
cert.sign(@options[:key].private_key, OpenSSL::Digest::SHA1.new)
|
36
|
+
cert
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(method)
|
40
|
+
ssl.send(method)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'eassl'
|
3
|
+
module EaSSL
|
4
|
+
# Author:: Paul Nicholson (mailto:paul@webpowerdesign.net)
|
5
|
+
# Co-Author:: Adam Williams (mailto:adam@thewilliams.ws)
|
6
|
+
# Copyright:: Copyright (c) 2006 WebPower Design
|
7
|
+
# License:: Distributes under the same terms as Ruby
|
8
|
+
class Certificate
|
9
|
+
def initialize(options)
|
10
|
+
@options = {
|
11
|
+
:days_valid => (365 * 5),
|
12
|
+
:signing_request => nil, #required
|
13
|
+
:ca_certificate => nil, #required
|
14
|
+
:comment => "Ruby/OpenSSL/EaSSL Generated Certificate",
|
15
|
+
}.update(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def ssl
|
19
|
+
unless @ssl
|
20
|
+
@ssl = OpenSSL::X509::Certificate.new
|
21
|
+
@ssl.not_before = Time.now
|
22
|
+
@ssl.subject = @options[:signing_request].subject
|
23
|
+
@ssl.issuer = @options[:ca_certificate]? @options[:ca_certificate].subject : @ssl.subject
|
24
|
+
@ssl.not_after = @ssl.not_before + @options[:days_valid] * 24 * 60 * 60
|
25
|
+
@ssl.public_key = @options[:signing_request].public_key
|
26
|
+
@ssl.serial = @options[:serial] || 2
|
27
|
+
@ssl.version = 2 # X509v3
|
28
|
+
|
29
|
+
ef = OpenSSL::X509::ExtensionFactory.new
|
30
|
+
ef.subject_certificate = @ssl
|
31
|
+
ef.issuer_certificate = @options[:ca_certificate]? @options[:ca_certificate].ssl : @ssl
|
32
|
+
@ssl.extensions = [
|
33
|
+
ef.create_extension("basicConstraints","CA:FALSE"),
|
34
|
+
ef.create_extension("keyUsage", "digitalSignature, keyEncipherment"),
|
35
|
+
ef.create_extension("subjectKeyIdentifier", "hash"),
|
36
|
+
ef.create_extension("extendedKeyUsage", "serverAuth"),
|
37
|
+
ef.create_extension("nsComment", @options[:comment]),
|
38
|
+
]
|
39
|
+
@ssl.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always"))
|
40
|
+
end
|
41
|
+
@ssl
|
42
|
+
end
|
43
|
+
|
44
|
+
def sign(ca_key)
|
45
|
+
ssl.sign(ca_key.ssl, OpenSSL::Digest::SHA1.new)
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_pem
|
49
|
+
ssl.to_pem
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.load(pem_file_path)
|
53
|
+
new({}).load(File.read(pem_file_path))
|
54
|
+
end
|
55
|
+
|
56
|
+
def load(pem_string)
|
57
|
+
begin
|
58
|
+
@ssl = OpenSSL::X509::Certificate.new(pem_string)
|
59
|
+
rescue
|
60
|
+
raise "CertificateLoader: Error loading certificate"
|
61
|
+
end
|
62
|
+
self
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'eassl'
|
3
|
+
module EaSSL
|
4
|
+
# Author:: Paul Nicholson (mailto:paul@webpowerdesign.net)
|
5
|
+
# Co-Author:: Adam Williams (mailto:adam@thewilliams.ws)
|
6
|
+
# Copyright:: Copyright (c) 2006 WebPower Design
|
7
|
+
# License:: Distributes under the same terms as Ruby
|
8
|
+
class CertificateAuthority
|
9
|
+
attr_reader :key, :certificate
|
10
|
+
def initialize(options = {})
|
11
|
+
@key = Key.new({:password => 'ca_ssl_password'}.update(options))
|
12
|
+
@certificate = AuthorityCertificate.new(:key => @key)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_certificate(signing_request)
|
16
|
+
cert = Certificate.new(:signing_request => signing_request, :ca_certificate => @certificate)
|
17
|
+
cert.sign(@key)
|
18
|
+
cert
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'eassl'
|
3
|
+
module EaSSL
|
4
|
+
# Author:: Paul Nicholson (mailto:paul@webpowerdesign.net)
|
5
|
+
# Co-Author:: Adam Williams (mailto:adam@thewilliams.ws)
|
6
|
+
# Copyright:: Copyright (c) 2006 WebPower Design
|
7
|
+
# License:: Distributes under the same terms as Ruby
|
8
|
+
class CertificateName
|
9
|
+
def initialize(options)
|
10
|
+
@options = {
|
11
|
+
:country => "US",
|
12
|
+
:state => "North Carolina",
|
13
|
+
:city => "Fuquay Varina",
|
14
|
+
:organization => "WebPower Design",
|
15
|
+
:department => "Web Security",
|
16
|
+
:common_name => nil, # required
|
17
|
+
:email => "eassl@rubyforge.org",
|
18
|
+
}.update(options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def ssl
|
22
|
+
OpenSSL::X509::Name.new([
|
23
|
+
['C', @options[:country], OpenSSL::ASN1::PRINTABLESTRING],
|
24
|
+
['ST', @options[:state], OpenSSL::ASN1::PRINTABLESTRING],
|
25
|
+
['L', @options[:city], OpenSSL::ASN1::PRINTABLESTRING],
|
26
|
+
['O', @options[:organization], OpenSSL::ASN1::UTF8STRING],
|
27
|
+
['OU', @options[:department], OpenSSL::ASN1::UTF8STRING],
|
28
|
+
['CN', @options[:common_name], OpenSSL::ASN1::UTF8STRING],
|
29
|
+
['emailAddress', @options[:email], OpenSSL::ASN1::UTF8STRING]
|
30
|
+
])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/eassl/key.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'eassl'
|
3
|
+
module EaSSL
|
4
|
+
# == EaSSL::Key creates and manages openSSL keys
|
5
|
+
#
|
6
|
+
# Author:: Paul Nicholson (mailto:paul@webpowerdesign.net)
|
7
|
+
# Co-Author:: Adam Williams (mailto:adam@thewilliams.ws)
|
8
|
+
# Copyright:: Copyright (c) 2006 WebPower Design
|
9
|
+
# License:: Distributes under the same terms as Ruby
|
10
|
+
#
|
11
|
+
# ==== Usage
|
12
|
+
#
|
13
|
+
# ===== Availible Methods - including methods provided by openSSL::PKey:
|
14
|
+
# * public_key
|
15
|
+
# * private_key
|
16
|
+
# * to_text
|
17
|
+
class Key
|
18
|
+
# Create new Key using the provided options or using the defaults
|
19
|
+
def initialize(options = {}) #:params: options
|
20
|
+
@options = {
|
21
|
+
:bits => 2048,
|
22
|
+
:password => 'ssl_password',
|
23
|
+
}.update(options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def ssl
|
27
|
+
unless @ssl
|
28
|
+
$stderr.puts "Generating #{@options[:bits]} bit key\n" # <Should use some kind of logger on this>
|
29
|
+
@ssl = OpenSSL::PKey::RSA::new(@options[:bits])
|
30
|
+
end
|
31
|
+
@ssl
|
32
|
+
end
|
33
|
+
|
34
|
+
# This method is used to intercept and pass-thru calls to openSSL methods and instance
|
35
|
+
# variables.
|
36
|
+
def method_missing(method) # :nodoc:
|
37
|
+
ssl.send(method)
|
38
|
+
end
|
39
|
+
|
40
|
+
def private_key
|
41
|
+
ssl
|
42
|
+
end
|
43
|
+
|
44
|
+
# Export the encrypted key, returns a string
|
45
|
+
def to_pem
|
46
|
+
ssl.export(OpenSSL::Cipher::DES.new('EDE3-CBC'), @options[:password])
|
47
|
+
end
|
48
|
+
|
49
|
+
# Decrypt and load a PEM encoded Key from the file system with the provided password.
|
50
|
+
def self.load(pem_file_path, password=nil)
|
51
|
+
new.load(File.read(pem_file_path), password)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Decrypt and load a PEM encoded Key from provided string with the provided password.
|
55
|
+
def load(pem_string, password=nil)
|
56
|
+
begin
|
57
|
+
@ssl = OpenSSL::PKey::RSA::new(pem_string, password || @options[:password])
|
58
|
+
rescue
|
59
|
+
raise "KeyLoader: Error decrypting key with password"
|
60
|
+
end
|
61
|
+
self
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'eassl'
|
3
|
+
module EaSSL
|
4
|
+
# Author:: Paul Nicholson (mailto:paul@webpowerdesign.net)
|
5
|
+
# Co-Author:: Adam Williams (mailto:adam@thewilliams.ws)
|
6
|
+
# Copyright:: Copyright (c) 2006 WebPower Design
|
7
|
+
# License:: Distributes under the same terms as Ruby
|
8
|
+
class SigningRequest
|
9
|
+
def initialize(options = {})
|
10
|
+
@options = {
|
11
|
+
:name => {}, #required, CertificateName
|
12
|
+
:key => nil, #required
|
13
|
+
}.update(options)
|
14
|
+
@options[:key] ||= Key.new(@options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def ssl
|
18
|
+
unless @ssl
|
19
|
+
@ssl = OpenSSL::X509::Request.new
|
20
|
+
@ssl.version = 0
|
21
|
+
@ssl.subject = CertificateName.new(@options[:name]).ssl
|
22
|
+
@ssl.public_key = key.public_key
|
23
|
+
@ssl.sign(key.private_key, OpenSSL::Digest::MD5.new)
|
24
|
+
end
|
25
|
+
@ssl
|
26
|
+
end
|
27
|
+
|
28
|
+
def key
|
29
|
+
@options[:key]
|
30
|
+
end
|
31
|
+
|
32
|
+
# This method is used to intercept and pass-thru calls to openSSL methods and instance
|
33
|
+
# variables.
|
34
|
+
def method_missing(method)
|
35
|
+
ssl.send(method)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.load(pem_file_path)
|
39
|
+
new.load(File.read(pem_file_path))
|
40
|
+
end
|
41
|
+
|
42
|
+
def load(pem_string)
|
43
|
+
begin
|
44
|
+
@ssl = OpenSSL::X509::Request.new(pem_string)
|
45
|
+
rescue
|
46
|
+
raise "SigningRequestLoader: Error loading signing request"
|
47
|
+
end
|
48
|
+
self
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/eassl.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
$:.unshift File.expand_path(File.dirname(__FILE__))
|
2
|
+
# = About EaSSL
|
3
|
+
#
|
4
|
+
# Author:: Paul Nicholson (mailto:paul@webpowerdesign.net)
|
5
|
+
# Co-Author:: Adam Williams (mailto:adam@thewilliams.ws)
|
6
|
+
# Copyright:: Copyright (c) 2006 WebPower Design
|
7
|
+
# License:: Distributes under the same terms as Ruby
|
8
|
+
#
|
9
|
+
# By requiring <tt>eassl</tt>, you can load the full set of EaSSL classes.
|
10
|
+
#
|
11
|
+
# For a full list of features and instructions, see the #README.
|
12
|
+
#
|
13
|
+
# EaSSL is a module containing all of the great EaSSL classes for creating
|
14
|
+
# and managing openSSL keys, signing request, and certificates.
|
15
|
+
#
|
16
|
+
# * EaSSL::Key: the class for loading and creating SSL keys
|
17
|
+
# * EaSSL::SigningRequest: the class for creating SSL signing requests
|
18
|
+
|
19
|
+
module EaSSL
|
20
|
+
VERSION = '0.1'
|
21
|
+
|
22
|
+
def self.generate_self_signed(options)
|
23
|
+
ca = CertificateAuthority.new({:bits => 1024}.update(options[:ca_options]||{}))
|
24
|
+
sr = SigningRequest.new(options)
|
25
|
+
cert = ca.create_certificate(sr)
|
26
|
+
[ca, sr, cert]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'eassl/key'
|
31
|
+
require 'eassl/certificate_name'
|
32
|
+
require 'eassl/signing_request'
|
33
|
+
require 'eassl/certificate'
|
34
|
+
require 'eassl/authority_certificate'
|
35
|
+
require 'eassl/certificate_authority'
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: eassl
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.1635
|
7
|
+
date: 2006-11-16 00:00:00 -05:00
|
8
|
+
summary: EaSSL is a library aimed at making openSSL certificate generation and management easier and more ruby-ish.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email:
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: eassl
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
authors:
|
29
|
+
- Paul Nicholson
|
30
|
+
files:
|
31
|
+
- README
|
32
|
+
- Rakefile
|
33
|
+
- lib/eassl
|
34
|
+
- lib/eassl.rb
|
35
|
+
- lib/eassl/authority_certificate.rb
|
36
|
+
- lib/eassl/certificate.rb
|
37
|
+
- lib/eassl/certificate_authority.rb
|
38
|
+
- lib/eassl/certificate_name.rb
|
39
|
+
- lib/eassl/key.rb
|
40
|
+
- lib/eassl/signing_request.rb
|
41
|
+
test_files: []
|
42
|
+
|
43
|
+
rdoc_options: []
|
44
|
+
|
45
|
+
extra_rdoc_files:
|
46
|
+
- README
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
requirements: []
|
52
|
+
|
53
|
+
dependencies: []
|
54
|
+
|