r509 0.10.0 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.mdown +2 -2
- data/Rakefile +2 -3
- data/bin/r509 +77 -80
- data/bin/r509-parse +4 -4
- data/doc/R509.html +60 -60
- data/doc/R509/ASN1.html +158 -48
- data/doc/R509/ASN1/GeneralName.html +157 -154
- data/doc/R509/ASN1/GeneralNames.html +246 -237
- data/doc/R509/CRL.html +41 -39
- data/doc/R509/CRL/Administrator.html +105 -100
- data/doc/R509/CRL/FileReaderWriter.html +146 -98
- data/doc/R509/CRL/ReaderWriter.html +57 -54
- data/doc/R509/CRL/SQLiteReaderWriter.html +727 -0
- data/doc/R509/CRL/SignedList.html +83 -80
- data/doc/R509/CSR.html +184 -162
- data/doc/R509/Cert.html +271 -269
- data/doc/R509/Cert/Extensions.html +62 -63
- data/doc/R509/Cert/Extensions/AuthorityInfoAccess.html +138 -108
- data/doc/R509/Cert/Extensions/AuthorityKeyIdentifier.html +100 -84
- data/doc/R509/Cert/Extensions/BasicConstraints.html +89 -88
- data/doc/R509/Cert/Extensions/CRLDistributionPoints.html +87 -83
- data/doc/R509/Cert/Extensions/CertificatePolicies.html +78 -76
- data/doc/R509/Cert/Extensions/ExtendedKeyUsage.html +128 -125
- data/doc/R509/Cert/Extensions/GeneralNamesMixin.html +83 -78
- data/doc/R509/Cert/Extensions/InhibitAnyPolicy.html +69 -67
- data/doc/R509/Cert/Extensions/KeyUsage.html +138 -135
- data/doc/R509/Cert/Extensions/NameConstraints.html +82 -81
- data/doc/R509/Cert/Extensions/NoticeReference.html +59 -56
- data/doc/R509/Cert/Extensions/OCSPNoCheck.html +70 -69
- data/doc/R509/Cert/Extensions/PolicyConstraints.html +71 -69
- data/doc/R509/Cert/Extensions/PolicyInformation.html +63 -60
- data/doc/R509/Cert/Extensions/PolicyQualifiers.html +60 -57
- data/doc/R509/Cert/Extensions/SubjectAlternativeName.html +91 -87
- data/doc/R509/Cert/Extensions/SubjectKeyIdentifier.html +72 -71
- data/doc/R509/Cert/Extensions/UserNotice.html +60 -57
- data/doc/R509/Cert/Extensions/ValidationMixin.html +43 -40
- data/doc/R509/CertificateAuthority.html +39 -37
- data/doc/R509/CertificateAuthority/OptionsBuilder.html +58 -55
- data/doc/R509/CertificateAuthority/Signer.html +277 -60
- data/doc/R509/Config.html +40 -38
- data/doc/R509/Config/CAConfig.html +255 -188
- data/doc/R509/Config/CAConfigPool.html +64 -61
- data/doc/R509/Config/CertProfile.html +119 -116
- data/doc/R509/Config/SubjectItemPolicy.html +94 -93
- data/doc/R509/Engine.html +60 -56
- data/doc/R509/Helpers.html +99 -96
- data/doc/R509/MessageDigest.html +69 -68
- data/doc/R509/NameSanitizer.html +51 -48
- data/doc/R509/OCSP.html +39 -37
- data/doc/R509/OCSP/Request.html +39 -37
- data/doc/R509/OCSP/Request/Nonce.html +67 -67
- data/doc/R509/OCSP/Response.html +93 -90
- data/doc/R509/OIDMapper.html +48 -46
- data/doc/R509/PrivateKey.html +170 -169
- data/doc/R509/R509Error.html +45 -42
- data/doc/R509/SPKI.html +99 -89
- data/doc/R509/Subject.html +86 -83
- data/doc/R509/Validity.html +57 -57
- data/doc/R509/Validity/Checker.html +63 -93
- data/doc/R509/Validity/DefaultChecker.html +58 -55
- data/doc/R509/Validity/DefaultWriter.html +62 -59
- data/doc/R509/Validity/Status.html +77 -74
- data/doc/R509/Validity/Writer.html +75 -123
- data/doc/_index.html +37 -31
- data/doc/class_list.html +25 -27
- data/doc/css/full_list.css +32 -31
- data/doc/css/style.css +221 -78
- data/doc/file.CONTRIBUTING.html +29 -30
- data/doc/file.LICENSE.html +29 -30
- data/doc/file.README.html +31 -32
- data/doc/file.YAML.html +33 -34
- data/doc/file.r509.html +39 -48
- data/doc/file_list.html +39 -30
- data/doc/frames.html +10 -21
- data/doc/index.html +31 -32
- data/doc/js/app.js +100 -71
- data/doc/js/full_list.js +168 -130
- data/doc/method_list.html +1788 -1119
- data/doc/top-level-namespace.html +45 -49
- data/lib/r509.rb +21 -7
- data/lib/r509/asn1.rb +45 -32
- data/lib/r509/cert.rb +45 -51
- data/lib/r509/cert/extensions/authority_info_access.rb +49 -23
- data/lib/r509/cert/extensions/authority_key_identifier.rb +16 -11
- data/lib/r509/cert/extensions/base.rb +22 -23
- data/lib/r509/cert/extensions/basic_constraints.rb +11 -12
- data/lib/r509/cert/extensions/certificate_policies.rb +26 -26
- data/lib/r509/cert/extensions/crl_distribution_points.rb +5 -7
- data/lib/r509/cert/extensions/extended_key_usage.rb +5 -5
- data/lib/r509/cert/extensions/inhibit_any_policy.rb +4 -3
- data/lib/r509/cert/extensions/key_usage.rb +5 -5
- data/lib/r509/cert/extensions/name_constraints.rb +16 -16
- data/lib/r509/cert/extensions/ocsp_no_check.rb +3 -3
- data/lib/r509/cert/extensions/policy_constraints.rb +8 -8
- data/lib/r509/cert/extensions/subject_alternative_name.rb +5 -4
- data/lib/r509/cert/extensions/subject_key_identifier.rb +5 -5
- data/lib/r509/cert/extensions/validation_mixin.rb +11 -10
- data/lib/r509/certificate_authority/options_builder.rb +19 -21
- data/lib/r509/certificate_authority/signer.rb +26 -27
- data/lib/r509/config.rb +1 -0
- data/lib/r509/config/ca_config.rb +70 -75
- data/lib/r509/config/cert_profile.rb +9 -8
- data/lib/r509/config/subject_item_policy.rb +25 -28
- data/lib/r509/crl/administrator.rb +19 -20
- data/lib/r509/crl/reader_writer.rb +10 -8
- data/lib/r509/crl/signed_list.rb +4 -4
- data/lib/r509/crl/sqlite_reader_writer.rb +75 -0
- data/lib/r509/csr.rb +54 -60
- data/lib/r509/ec-hack.rb +3 -2
- data/lib/r509/engine.rb +5 -6
- data/lib/r509/exceptions.rb +1 -1
- data/lib/r509/helpers.rb +11 -14
- data/lib/r509/io_helpers.rb +7 -7
- data/lib/r509/message_digest.rb +5 -6
- data/lib/r509/ocsp.rb +11 -13
- data/lib/r509/oid_mapper.rb +2 -2
- data/lib/r509/private_key.rb +28 -32
- data/lib/r509/spki.rb +17 -20
- data/lib/r509/subject.rb +26 -27
- data/lib/r509/trollop.rb +1 -0
- data/lib/r509/validity.rb +30 -21
- data/lib/r509/version.rb +4 -2
- data/r509.yaml +9 -17
- data/spec/asn1_spec.rb +145 -146
- data/spec/cert/extensions/authority_info_access_spec.rb +41 -41
- data/spec/cert/extensions/authority_key_identifier_spec.rb +29 -23
- data/spec/cert/extensions/base_spec.rb +38 -34
- data/spec/cert/extensions/basic_constraints_spec.rb +21 -21
- data/spec/cert/extensions/certificate_policies_spec.rb +99 -87
- data/spec/cert/extensions/crl_distribution_points_spec.rb +24 -25
- data/spec/cert/extensions/extended_key_usage_spec.rb +40 -36
- data/spec/cert/extensions/inhibit_any_policy_spec.rb +12 -12
- data/spec/cert/extensions/key_usage_spec.rb +44 -39
- data/spec/cert/extensions/name_constraints_spec.rb +83 -83
- data/spec/cert/extensions/ocsp_no_check_spec.rb +10 -10
- data/spec/cert/extensions/policy_constraints_spec.rb +19 -19
- data/spec/cert/extensions/subject_alternative_name_spec.rb +46 -47
- data/spec/cert/extensions/subject_key_identifier_spec.rb +10 -10
- data/spec/cert_spec.rb +105 -101
- data/spec/certificate_authority/options_builder_spec.rb +90 -90
- data/spec/certificate_authority/signer_spec.rb +41 -41
- data/spec/config/ca_config_spec.rb +169 -119
- data/spec/config/cert_profile_spec.rb +33 -33
- data/spec/config/subject_item_policy_spec.rb +22 -22
- data/spec/crl/administrator_spec.rb +65 -65
- data/spec/crl/reader_writer_spec.rb +20 -19
- data/spec/crl/signed_list_spec.rb +26 -26
- data/spec/crl/sqlite_reader_writer_spec.rb +42 -0
- data/spec/csr_spec.rb +149 -145
- data/spec/engine_spec.rb +14 -14
- data/spec/fixtures.rb +56 -39
- data/spec/fixtures/crl_list.sql +13 -0
- data/spec/fixtures/csr1.der +0 -0
- data/spec/fixtures/csr1.pem +6 -6
- data/spec/message_digest_spec.rb +43 -43
- data/spec/ocsp_spec.rb +25 -25
- data/spec/oid_mapper_spec.rb +18 -19
- data/spec/private_key_spec.rb +79 -81
- data/spec/r509_spec.rb +16 -16
- data/spec/spec_helper.rb +3 -3
- data/spec/spki_spec.rb +94 -94
- data/spec/subject_spec.rb +107 -107
- data/spec/validity_spec.rb +25 -25
- metadata +113 -111
- metadata.gz.sig +0 -0
data/lib/r509/ec-hack.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# a method named #private? on the PKey object. OpenSSL::PKey::RSA and OpenSSL::PKey::DSA
|
5
5
|
# both define this method, but OpenSSL::PKey::EC defines #private_key? instead. This
|
6
6
|
# will open up the class and add #private? as an alias to allow successful signing
|
7
|
-
if defined?(OpenSSL::PKey::EC)
|
7
|
+
if defined?(OpenSSL::PKey::EC) && !OpenSSL::PKey::EC.method_defined?('private?')
|
8
8
|
# marked as @private so it won't appear in the yard doc
|
9
9
|
# @private
|
10
10
|
module OpenSSL::PKey
|
@@ -16,7 +16,7 @@ if defined?(OpenSSL::PKey::EC) and not OpenSSL::PKey::EC.method_defined?('privat
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
19
|
-
elsif
|
19
|
+
elsif !defined?(OpenSSL::PKey::EC)
|
20
20
|
# this is a stub implementation for when EC is unavailable. Any method called against
|
21
21
|
# it will raise an R509Error
|
22
22
|
# marked as @private so it won't appear in the yard doc
|
@@ -29,6 +29,7 @@ elsif not defined?(OpenSSL::PKey::EC)
|
|
29
29
|
def initialize(*args)
|
30
30
|
raise R509::R509Error, "EC is unavailable. You may need to recompile Ruby with an OpenSSL that has elliptic curve support."
|
31
31
|
end
|
32
|
+
|
32
33
|
def method_missing(method, *args, &block)
|
33
34
|
raise R509::R509Error, "EC is unavailable. You may need to recompile Ruby with an OpenSSL that has elliptic curve support."
|
34
35
|
end
|
data/lib/r509/engine.rb
CHANGED
@@ -14,7 +14,7 @@ module R509
|
|
14
14
|
# @return OpenSSL::Engine object
|
15
15
|
def load(hash)
|
16
16
|
validate_hash(hash)
|
17
|
-
if @engines.
|
17
|
+
if @engines.key?(hash[:id])
|
18
18
|
@engines[hash[:id]]
|
19
19
|
else
|
20
20
|
init_engine(hash)
|
@@ -31,16 +31,15 @@ module R509
|
|
31
31
|
def init_engine(hash)
|
32
32
|
OpenSSL::Engine.load
|
33
33
|
@engines[hash[:id]] = OpenSSL::Engine.by_id("dynamic") do |e|
|
34
|
-
e.ctrl_cmd("SO_PATH",hash[:so_path])
|
35
|
-
e.ctrl_cmd("ID",hash[:id])
|
34
|
+
e.ctrl_cmd("SO_PATH", hash[:so_path])
|
35
|
+
e.ctrl_cmd("ID", hash[:id])
|
36
36
|
e.ctrl_cmd("LOAD")
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
40
|
def validate_hash(hash)
|
41
|
-
|
42
|
-
|
43
|
-
end
|
41
|
+
return unless !hash.respond_to?(:key?) || !hash.key?(:so_path) || !hash.key?(:id)
|
42
|
+
raise ArgumentError, "You must supply a hash with both :so_path and :id"
|
44
43
|
end
|
45
44
|
end
|
46
45
|
end
|
data/lib/r509/exceptions.rb
CHANGED
data/lib/r509/helpers.rb
CHANGED
@@ -2,26 +2,25 @@ module R509
|
|
2
2
|
# Various helper methods to reduce duplication across classes. These methods
|
3
3
|
# are used in the Cert, CSR, SPKI, and PrivateKey classes.
|
4
4
|
module Helpers
|
5
|
-
|
6
5
|
# Returns whether the public key is RSA
|
7
6
|
#
|
8
7
|
# @return [Boolean] true if the public key is RSA, false otherwise
|
9
8
|
def rsa?
|
10
|
-
internal_obj.public_key.
|
9
|
+
internal_obj.public_key.is_a?(OpenSSL::PKey::RSA)
|
11
10
|
end
|
12
11
|
|
13
12
|
# Returns whether the public key is DSA
|
14
13
|
#
|
15
14
|
# @return [Boolean] true if the public key is DSA, false otherwise
|
16
15
|
def dsa?
|
17
|
-
internal_obj.public_key.
|
16
|
+
internal_obj.public_key.is_a?(OpenSSL::PKey::DSA)
|
18
17
|
end
|
19
18
|
|
20
19
|
# Returns whether the public key is EC
|
21
20
|
#
|
22
21
|
# @return [Boolean] true if the public key is EC, false otherwise
|
23
22
|
def ec?
|
24
|
-
internal_obj.public_key.
|
23
|
+
internal_obj.public_key.is_a?(OpenSSL::PKey::EC)
|
25
24
|
end
|
26
25
|
|
27
26
|
# Returns key algorithm (RSA/DSA/EC)
|
@@ -60,7 +59,7 @@ module R509
|
|
60
59
|
raise R509::R509Error, 'Bit length is not available for EC at this time.'
|
61
60
|
end
|
62
61
|
end
|
63
|
-
|
62
|
+
alias_method :bit_strength, :bit_length
|
64
63
|
|
65
64
|
# Writes the object into PEM format
|
66
65
|
# @param [String, #write] filename_or_io Either a string of the path for
|
@@ -80,24 +79,23 @@ module R509
|
|
80
79
|
#
|
81
80
|
# @return [String] the object converted into PEM format.
|
82
81
|
def to_pem
|
83
|
-
|
82
|
+
internal_obj.to_pem
|
84
83
|
end
|
85
84
|
|
86
85
|
# Converts the object into DER format
|
87
86
|
#
|
88
87
|
# @return [String] the object converted into DER format.
|
89
88
|
def to_der
|
90
|
-
|
89
|
+
internal_obj.to_der
|
91
90
|
end
|
92
91
|
|
93
92
|
# @private
|
94
93
|
def load_private_key(opts)
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
end
|
94
|
+
return unless opts.key?(:key)
|
95
|
+
if opts[:key].is_a?(R509::PrivateKey)
|
96
|
+
return opts[:key]
|
97
|
+
else
|
98
|
+
return R509::PrivateKey.new(:key => opts[:key])
|
101
99
|
end
|
102
100
|
end
|
103
101
|
|
@@ -105,6 +103,5 @@ module R509
|
|
105
103
|
def internal_obj
|
106
104
|
raise R509::R509Error, "Internal object for helpers not implemented"
|
107
105
|
end
|
108
|
-
|
109
106
|
end
|
110
107
|
end
|
data/lib/r509/io_helpers.rb
CHANGED
@@ -7,12 +7,12 @@ module R509
|
|
7
7
|
# the file that you'd like to write, or an IO-like object.
|
8
8
|
# @param [String] data The data that we want to write
|
9
9
|
# @param [String] mode The write mode
|
10
|
-
def self.write_data(filename_or_io, data, mode='wb:ascii-8bit')
|
10
|
+
def self.write_data(filename_or_io, data, mode = 'wb:ascii-8bit')
|
11
11
|
if filename_or_io.respond_to?(:write)
|
12
|
-
if filename_or_io.
|
12
|
+
if filename_or_io.is_a?(StringIO) && mode != "a:ascii-8bit"
|
13
13
|
# Writing to a StringIO in a non-append mode. This requires
|
14
14
|
# us to rewind and truncate it first.
|
15
|
-
filename_or_io.rewind
|
15
|
+
filename_or_io.rewind
|
16
16
|
filename_or_io.truncate(0)
|
17
17
|
end
|
18
18
|
filename_or_io.write(data)
|
@@ -28,10 +28,10 @@ module R509
|
|
28
28
|
# the file that you'd like to read, or an IO-like object.
|
29
29
|
def self.read_data(filename_or_io)
|
30
30
|
if filename_or_io.respond_to?(:read)
|
31
|
-
if filename_or_io.
|
32
|
-
filename_or_io.rewind
|
31
|
+
if filename_or_io.is_a?(StringIO)
|
32
|
+
filename_or_io.rewind
|
33
33
|
end
|
34
|
-
filename_or_io.read
|
34
|
+
filename_or_io.read
|
35
35
|
else
|
36
36
|
return File.open(filename_or_io, 'rb:ascii-8bit') do |f|
|
37
37
|
f.read
|
@@ -43,7 +43,7 @@ module R509
|
|
43
43
|
# @param [String, #write] filename_or_io Either a string of the path for
|
44
44
|
# the file that you'd like to write, or an IO-like object.
|
45
45
|
# @param [String] data The data that we want to write
|
46
|
-
def write_data(filename_or_io, data, mode='wb:ascii-8bit')
|
46
|
+
def write_data(filename_or_io, data, mode = 'wb:ascii-8bit')
|
47
47
|
IOHelpers.write_data(filename_or_io, data, mode)
|
48
48
|
end
|
49
49
|
|
data/lib/r509/message_digest.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
require 'openssl'
|
2
2
|
|
3
3
|
module R509
|
4
|
-
#MessageDigest allows you to specify MDs in a more friendly fashion
|
4
|
+
# MessageDigest allows you to specify MDs in a more friendly fashion
|
5
5
|
class MessageDigest
|
6
6
|
# a list of message digests that this class understands
|
7
|
-
KNOWN_MDS = ['SHA1','SHA224','SHA256','SHA384','SHA512','DSS1','MD5']
|
7
|
+
KNOWN_MDS = ['SHA1', 'SHA224', 'SHA256', 'SHA384', 'SHA512', 'DSS1', 'MD5']
|
8
8
|
|
9
9
|
# this constant defines the default message digest if it is not supplied
|
10
10
|
# or an invalid digest is passed
|
11
|
-
DEFAULT_MD = '
|
11
|
+
DEFAULT_MD = 'SHA256'
|
12
12
|
|
13
13
|
attr_reader :name, :digest
|
14
14
|
|
15
15
|
# @param [String,OpenSSL::Digest] arg
|
16
|
-
def initialize(arg=nil)
|
17
|
-
if arg.
|
16
|
+
def initialize(arg = nil)
|
17
|
+
if arg.is_a?(String)
|
18
18
|
@name = arg.downcase
|
19
19
|
@digest = translate_name_to_digest
|
20
20
|
elsif arg.nil?
|
@@ -60,4 +60,3 @@ module R509
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
63
|
-
|
data/lib/r509/ocsp.rb
CHANGED
@@ -2,14 +2,13 @@ require 'openssl'
|
|
2
2
|
require 'r509/exceptions'
|
3
3
|
require 'r509/config'
|
4
4
|
|
5
|
-
#OCSP module
|
5
|
+
# OCSP module
|
6
6
|
module R509::OCSP
|
7
|
-
|
8
|
-
#builds OCSP responses
|
7
|
+
# builds OCSP responses
|
9
8
|
class Response
|
10
9
|
# @param ocsp_response [OpenSSL::OCSP::Response]
|
11
10
|
def initialize(ocsp_response)
|
12
|
-
|
11
|
+
unless ocsp_response.is_a?(OpenSSL::OCSP::Response)
|
13
12
|
raise R509::R509Error, 'You must pass an OpenSSL::OCSP::Response object to the constructor. See R509::OCSP::Response.parse if you are trying to parse'
|
14
13
|
end
|
15
14
|
@ocsp_response = ocsp_response
|
@@ -42,7 +41,7 @@ module R509::OCSP
|
|
42
41
|
# @return [Boolean] true if the response is valid according to the given root
|
43
42
|
def verify(certs)
|
44
43
|
store = OpenSSL::X509::Store.new
|
45
|
-
if certs.
|
44
|
+
if certs.is_a?(Array)
|
46
45
|
stack = certs
|
47
46
|
certs.each do |cert|
|
48
47
|
store.add_cert(cert)
|
@@ -52,14 +51,14 @@ module R509::OCSP
|
|
52
51
|
store.add_cert(certs)
|
53
52
|
end
|
54
53
|
|
55
|
-
#suppress verbosity since #verify will output a warning if it does not match
|
56
|
-
#as well as returning false. we just want the boolean
|
54
|
+
# suppress verbosity since #verify will output a warning if it does not match
|
55
|
+
# as well as returning false. we just want the boolean
|
57
56
|
original_verbosity = $VERBOSE
|
58
57
|
$VERBOSE = nil
|
59
|
-
#still a bit unclear on why we add to store and pass in array to verify
|
58
|
+
# still a bit unclear on why we add to store and pass in array to verify
|
60
59
|
result = @ocsp_response.basic.verify(stack, store)
|
61
60
|
$VERBOSE = original_verbosity
|
62
|
-
|
61
|
+
result
|
63
62
|
end
|
64
63
|
|
65
64
|
# @param [OpenSSL::OCSP::Request] ocsp_request the OCSP request whose nonce to check
|
@@ -69,12 +68,12 @@ module R509::OCSP
|
|
69
68
|
end
|
70
69
|
end
|
71
70
|
|
72
|
-
#holds OCSP request related items
|
71
|
+
# holds OCSP request related items
|
73
72
|
module Request
|
74
73
|
# contains constants r509 uses for OCSP responses
|
75
74
|
module Nonce
|
76
|
-
#these values are defined at
|
77
|
-
#http://www.ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/OCSP/Request.html
|
75
|
+
# these values are defined at
|
76
|
+
# http://www.ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/OCSP/Request.html
|
78
77
|
# nonce is present and matches
|
79
78
|
PRESENT_AND_EQUAL = 1
|
80
79
|
|
@@ -89,7 +88,6 @@ module R509::OCSP
|
|
89
88
|
|
90
89
|
# nonce is present in request only
|
91
90
|
REQUEST_ONLY = -1
|
92
|
-
|
93
91
|
end
|
94
92
|
end
|
95
93
|
end
|
data/lib/r509/oid_mapper.rb
CHANGED
@@ -8,7 +8,7 @@ module R509
|
|
8
8
|
# @param [String] short_name The short name (e.g. CN, O, OU, emailAddress)
|
9
9
|
# @param [String] long_name Optional long name. Defaults to the same as short_name
|
10
10
|
# @return [Boolean] success/failure
|
11
|
-
def self.register(oid,short_name,long_name=nil)
|
11
|
+
def self.register(oid, short_name, long_name = nil)
|
12
12
|
if long_name.nil?
|
13
13
|
long_name = short_name
|
14
14
|
end
|
@@ -24,7 +24,7 @@ module R509
|
|
24
24
|
# ]
|
25
25
|
def self.batch_register(oids)
|
26
26
|
oids.each do |oid_hash|
|
27
|
-
self.register(oid_hash[:oid],oid_hash[:short_name],oid_hash[:long_name])
|
27
|
+
self.register(oid_hash[:oid], oid_hash[:short_name], oid_hash[:long_name])
|
28
28
|
end
|
29
29
|
nil
|
30
30
|
end
|
data/lib/r509/private_key.rb
CHANGED
@@ -3,12 +3,12 @@ require 'r509/io_helpers'
|
|
3
3
|
require 'r509/exceptions'
|
4
4
|
|
5
5
|
module R509
|
6
|
-
#private key management
|
6
|
+
# private key management
|
7
7
|
class PrivateKey
|
8
8
|
include R509::IOHelpers
|
9
9
|
|
10
10
|
# a list of key types
|
11
|
-
KNOWN_TYPES = ["RSA","DSA","EC"]
|
11
|
+
KNOWN_TYPES = ["RSA", "DSA", "EC"]
|
12
12
|
# the default type
|
13
13
|
DEFAULT_TYPE = "RSA"
|
14
14
|
# default bit length for DSA/RSA
|
@@ -24,13 +24,13 @@ module R509
|
|
24
24
|
# @option opts [String,OpenSSL::PKey::RSA,OpenSSL::PKey::DSA,OpenSSL::PKey::EC] :key
|
25
25
|
# @option opts [OpenSSL::Engine] :engine
|
26
26
|
# @option opts [string] :key_name (used with engine)
|
27
|
-
def initialize(opts={})
|
28
|
-
|
27
|
+
def initialize(opts = {})
|
28
|
+
unless opts.is_a?(Hash)
|
29
29
|
raise ArgumentError, 'Must provide a hash of options'
|
30
30
|
end
|
31
31
|
validate_engine(opts)
|
32
32
|
|
33
|
-
if opts.
|
33
|
+
if opts.key?(:key)
|
34
34
|
validate_key(opts)
|
35
35
|
else
|
36
36
|
generate_key(opts)
|
@@ -41,11 +41,10 @@ module R509
|
|
41
41
|
#
|
42
42
|
# @param [String] filename Path to file you want to load
|
43
43
|
# @return [R509::PrivateKey] PrivateKey object
|
44
|
-
def self.load_from_file(
|
45
|
-
|
44
|
+
def self.load_from_file(filename, password = nil)
|
45
|
+
R509::PrivateKey.new(:key => IOHelpers.read_data(filename), :password => password)
|
46
46
|
end
|
47
47
|
|
48
|
-
|
49
48
|
# Returns the bit length of the key
|
50
49
|
#
|
51
50
|
# @return [Integer]
|
@@ -58,7 +57,7 @@ module R509
|
|
58
57
|
raise R509::R509Error, 'Bit length is not available for EC at this time.'
|
59
58
|
end
|
60
59
|
end
|
61
|
-
|
60
|
+
alias_method :bit_strength, :bit_length
|
62
61
|
|
63
62
|
# Returns the short name of the elliptic curve used to generate the private key
|
64
63
|
# if the key is EC. If not, raises an error.
|
@@ -83,7 +82,7 @@ module R509
|
|
83
82
|
|
84
83
|
# @return [Boolean] whether the key is resident in hardware or not
|
85
84
|
def in_hardware?
|
86
|
-
if
|
85
|
+
if @engine
|
87
86
|
true
|
88
87
|
else
|
89
88
|
false
|
@@ -99,14 +98,14 @@ module R509
|
|
99
98
|
# We have to supply the curve name to the temporary key object or else #public_key= fails
|
100
99
|
curve_name = self.key.group.curve_name
|
101
100
|
temp_key = OpenSSL::PKey::EC.new(curve_name)
|
102
|
-
temp_key.public_key=self.key.public_key
|
101
|
+
temp_key.public_key = self.key.public_key
|
103
102
|
temp_key
|
104
103
|
else
|
105
104
|
self.key.public_key
|
106
105
|
end
|
107
106
|
end
|
108
107
|
|
109
|
-
|
108
|
+
alias_method :to_s, :public_key
|
110
109
|
|
111
110
|
# Converts the key into the PEM format
|
112
111
|
#
|
@@ -125,15 +124,14 @@ module R509
|
|
125
124
|
# (common ones are des3, aes256, aes128)
|
126
125
|
# @param [String] password password
|
127
126
|
# @return [String] the key converted into encrypted PEM format.
|
128
|
-
def to_encrypted_pem(cipher,password)
|
127
|
+
def to_encrypted_pem(cipher, password)
|
129
128
|
if in_hardware?
|
130
129
|
raise R509::R509Error, "This method cannot be called when using keys in hardware"
|
131
130
|
end
|
132
131
|
cipher = OpenSSL::Cipher::Cipher.new(cipher)
|
133
|
-
self.key.to_pem(cipher,password)
|
132
|
+
self.key.to_pem(cipher, password)
|
134
133
|
end
|
135
134
|
|
136
|
-
|
137
135
|
# Converts the key into the DER format
|
138
136
|
#
|
139
137
|
# @return [String] the key converted into DER format.
|
@@ -152,7 +150,6 @@ module R509
|
|
152
150
|
write_data(filename_or_io, self.to_pem)
|
153
151
|
end
|
154
152
|
|
155
|
-
|
156
153
|
# Writes the key into encrypted PEM format with specified cipher
|
157
154
|
#
|
158
155
|
# @param [String, #write] filename_or_io Either a string of the path for
|
@@ -161,8 +158,8 @@ module R509
|
|
161
158
|
# full list of available ciphers can be obtained with OpenSSL::Cipher.ciphers
|
162
159
|
# (common ones are des3, aes256, aes128)
|
163
160
|
# @param [String] password password
|
164
|
-
def write_encrypted_pem(filename_or_io,cipher,password)
|
165
|
-
write_data(filename_or_io, to_encrypted_pem(cipher,password))
|
161
|
+
def write_encrypted_pem(filename_or_io, cipher, password)
|
162
|
+
write_data(filename_or_io, to_encrypted_pem(cipher, password))
|
166
163
|
end
|
167
164
|
|
168
165
|
# Writes the key into the DER format
|
@@ -173,39 +170,38 @@ module R509
|
|
173
170
|
write_data(filename_or_io, self.to_der)
|
174
171
|
end
|
175
172
|
|
176
|
-
|
177
173
|
# Returns whether the key is RSA
|
178
174
|
#
|
179
175
|
# @return [Boolean] true if the key is RSA, false otherwise
|
180
176
|
def rsa?
|
181
|
-
self.key.
|
177
|
+
self.key.is_a?(OpenSSL::PKey::RSA)
|
182
178
|
end
|
183
179
|
|
184
180
|
# Returns whether the key is DSA
|
185
181
|
#
|
186
182
|
# @return [Boolean] true if the key is DSA, false otherwise
|
187
183
|
def dsa?
|
188
|
-
self.key.
|
184
|
+
self.key.is_a?(OpenSSL::PKey::DSA)
|
189
185
|
end
|
190
186
|
|
191
187
|
# Returns whether the key is EC
|
192
188
|
#
|
193
189
|
# @return [Boolean] true if the key is EC, false otherwise
|
194
190
|
def ec?
|
195
|
-
self.key.
|
191
|
+
self.key.is_a?(OpenSSL::PKey::EC)
|
196
192
|
end
|
197
193
|
|
198
194
|
private
|
199
195
|
|
200
196
|
def validate_engine(opts)
|
201
|
-
if opts.
|
197
|
+
if opts.key?(:engine) && opts.key?(:key)
|
202
198
|
raise ArgumentError, 'You can\'t pass both :key and :engine'
|
203
|
-
elsif opts.
|
199
|
+
elsif opts.key?(:key_name) && !opts.key?(:engine)
|
204
200
|
raise ArgumentError, 'When providing a :key_name you MUST provide an :engine'
|
205
|
-
elsif opts.
|
201
|
+
elsif opts.key?(:engine) && !opts.key?(:key_name)
|
206
202
|
raise ArgumentError, 'When providing an :engine you MUST provide a :key_name'
|
207
|
-
elsif opts.
|
208
|
-
|
203
|
+
elsif opts.key?(:engine) && opts.key?(:key_name)
|
204
|
+
unless opts[:engine].is_a?(OpenSSL::Engine)
|
209
205
|
raise ArgumentError, 'When providing an engine, it must be of type OpenSSL::Engine'
|
210
206
|
end
|
211
207
|
@engine = opts[:engine]
|
@@ -215,16 +211,16 @@ module R509
|
|
215
211
|
|
216
212
|
def validate_key(opts)
|
217
213
|
password = opts[:password] || nil
|
218
|
-
#OpenSSL::PKey.read solves this begin/rescue garbage but is only
|
219
|
-
#available to Ruby 1.9.3+ and may not solve the EC portion
|
214
|
+
# OpenSSL::PKey.read solves this begin/rescue garbage but is only
|
215
|
+
# available to Ruby 1.9.3+ and may not solve the EC portion
|
220
216
|
begin
|
221
|
-
@key = OpenSSL::PKey::RSA.new(opts[:key],password)
|
217
|
+
@key = OpenSSL::PKey::RSA.new(opts[:key], password)
|
222
218
|
rescue OpenSSL::PKey::RSAError
|
223
219
|
begin
|
224
|
-
@key = OpenSSL::PKey::DSA.new(opts[:key],password)
|
220
|
+
@key = OpenSSL::PKey::DSA.new(opts[:key], password)
|
225
221
|
rescue
|
226
222
|
begin
|
227
|
-
@key = OpenSSL::PKey::EC.new(opts[:key],password)
|
223
|
+
@key = OpenSSL::PKey::EC.new(opts[:key], password)
|
228
224
|
rescue
|
229
225
|
raise R509::R509Error, "Failed to load private key. Invalid key or incorrect password."
|
230
226
|
end
|