Class: R509::PrivateKey

Inherits:
Object
  • Object
show all
Includes:
IOHelpers
Defined in:
lib/r509/privatekey.rb

Overview

private key management

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from IOHelpers

#read_data, read_data, #write_data, write_data

Constructor Details

- (PrivateKey) initialize(opts)

A new instance of PrivateKey

Parameters:

  • opts (Hash)

    a customizable set of options

Options Hash (opts):

  • :type (Symbol)

    :rsa/:dsa

  • :bit_strength (Integer)
  • :password (String)
  • :key (String, OpenSSL::PKey::RSA, OpenSSL::PKey::DSA)
  • :engine (OpenSSL::Engine)
  • :key_name (string) — default: used with engine


16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/r509/privatekey.rb', line 16

def initialize(opts)
    if not opts.kind_of?(Hash)
        raise ArgumentError, 'Must provide a hash of options'
    end

    if opts.has_key?(:engine) and opts.has_key?(:key)
        raise ArgumentError, 'You can\'t pass both :key and :engine'
    elsif opts.has_key?(:key_name) and not opts.has_key?(:engine)
        raise ArgumentError, 'When providing a :key_name you MUST provide an :engine'
    elsif opts.has_key?(:engine) and not opts.has_key?(:key_name)
        raise ArgumentError, 'When providing an :engine you MUST provide a :key_name'
    elsif opts.has_key?(:engine) and opts.has_key?(:key_name)
        if not opts[:engine].kind_of?(OpenSSL::Engine)
            raise ArgumentError, 'When providing an engine, it must be of type OpenSSL::Engine'
        end
        @engine = opts[:engine]
        @key_name = opts[:key_name]
    end

    if opts.has_key?(:key)
        password = opts[:password] || nil
        #OpenSSL::PKey.read solves this begin/rescue garbage but is only
        #available to Ruby 1.9.3+
        begin
            @key = OpenSSL::PKey::RSA.new(opts[:key],password)
        rescue OpenSSL::PKey::RSAError
            begin
                @key = OpenSSL::PKey::DSA.new(opts[:key],password)
            rescue
                raise R509::R509Error, "Failed to load private key. Invalid key or incorrect password."
            end
        end
    else
        bit_strength = opts[:bit_strength] || 2048
        type = opts[:type] || :rsa
        case type
        when :rsa
            @key = OpenSSL::PKey::RSA.new(bit_strength)
        when :dsa
            @key = OpenSSL::PKey::DSA.new(bit_strength)
        else
            raise ArgumentError, 'Must provide :rsa or :dsa as type when key or engine is nil'
        end
    end
end

Class Method Details

+ (R509::PrivateKey) load_from_file(filename, password = nil)

Helper method to quickly load a private key from the filesystem

Parameters:

  • filename (String)

    Path to file you want to load

Returns:



66
67
68
# File 'lib/r509/privatekey.rb', line 66

def self.load_from_file( filename, password = nil )
  return R509::PrivateKey.new(:key => IOHelpers.read_data(filename), :password => password )
end

Instance Method Details

- (Integer) bit_strength

Returns:

  • (Integer)


72
73
74
75
76
77
78
# File 'lib/r509/privatekey.rb', line 72

def bit_strength
    if self.rsa?
        return self.public_key.n.num_bits
    elsif self.dsa?
        return self.public_key.p.num_bits
    end
end

- (Boolean) dsa?

Returns whether the public key is DSA

Returns:

  • (Boolean)

    true if the public key is DSA, false otherwise



181
182
183
# File 'lib/r509/privatekey.rb', line 181

def dsa?
    self.key.kind_of?(OpenSSL::PKey::DSA)
end

- (Boolean) in_hardware?

Whether the key is resident in hardware or not

Returns:

  • (Boolean)

    whether the key is resident in hardware or not



90
91
92
93
94
95
96
# File 'lib/r509/privatekey.rb', line 90

def in_hardware?
    if not @engine.nil?
        true
    else
        false
    end
end

- (OpenSSL::PKey::RSA, ...) key

This method may return the PKey object itself or a handle to the private key in the HSM (which will not show the private key, just public)

Returns:

  • (OpenSSL::PKey::RSA, OpenSSL::PKey::DSA, OpenSSL::Engine pkey)

    this method may return the PKey object itself or a handle to the private key in the HSM (which will not show the private key, just public)



81
82
83
84
85
86
87
# File 'lib/r509/privatekey.rb', line 81

def key
    if in_hardware?
        @engine.load_private_key(@key_name)
    else
        @key
    end
end

- (OpenSSL::PKey::RSA, OpenSSL::PKey::DSA) public_key Also known as: to_s

Public key

Returns:

  • (OpenSSL::PKey::RSA, OpenSSL::PKey::DSA)

    public key



99
100
101
# File 'lib/r509/privatekey.rb', line 99

def public_key
    self.key.public_key
end

- (Boolean) rsa?

Returns whether the public key is RSA

Returns:

  • (Boolean)

    true if the public key is RSA, false otherwise



174
175
176
# File 'lib/r509/privatekey.rb', line 174

def rsa?
    self.key.kind_of?(OpenSSL::PKey::RSA)
end

- (String) to_der

Converts the key into the DER format

Returns:

  • (String)

    the key converted into DER format.



134
135
136
137
138
139
# File 'lib/r509/privatekey.rb', line 134

def to_der
    if in_hardware?
        raise R509::R509Error, "This method cannot be called when using keys in hardware"
    end
    self.key.to_der
end

- (String) to_encrypted_pem(cipher, password)

Converts the key into encrypted PEM format

full list of available ciphers can be obtained with OpenSSL::Cipher.ciphers (common ones are des3, aes256, aes128)

Parameters:

  • cipher (String, OpenSSL::Cipher)

    to use for encryption

  • password (String)

    password

Returns:

  • (String)

    the key converted into encrypted PEM format.



122
123
124
125
126
127
128
# File 'lib/r509/privatekey.rb', line 122

def to_encrypted_pem(cipher,password)
    if in_hardware?
        raise R509::R509Error, "This method cannot be called when using keys in hardware"
    end
    cipher = OpenSSL::Cipher::Cipher.new(cipher)
    self.key.to_pem(cipher,password)
end

- (String) to_pem

Converts the key into the PEM format

Returns:

  • (String)

    the key converted into PEM format.



108
109
110
111
112
113
# File 'lib/r509/privatekey.rb', line 108

def to_pem
    if in_hardware?
        raise R509::R509Error, "This method cannot be called when using keys in hardware"
    end
    self.key.to_pem
end

- (Object) write_der(filename_or_io)

Writes the key into the DER format

Parameters:

  • filename_or_io (String, #write)

    Either a string of the path for the file that you'd like to write, or an IO-like object.



166
167
168
# File 'lib/r509/privatekey.rb', line 166

def write_der(filename_or_io)
    write_data(filename_or_io, self.to_der)
end

- (Object) write_encrypted_pem(filename_or_io, cipher, password)

Writes the key into encrypted PEM format with specified cipher

full list of available ciphers can be obtained with OpenSSL::Cipher.ciphers (common ones are des3, aes256, aes128)

Parameters:

  • filename_or_io (String, #write)

    Either a string of the path for the file that you'd like to write, or an IO-like object.

  • cipher (String, OpenSSL::Cipher)

    to use for encryption

  • password (String)

    password



158
159
160
# File 'lib/r509/privatekey.rb', line 158

def write_encrypted_pem(filename_or_io,cipher,password)
    write_data(filename_or_io, to_encrypted_pem(cipher,password))
end

- (Object) write_pem(filename_or_io)

Writes the key into the PEM format

Parameters:

  • filename_or_io (String, #write)

    Either a string of the path for the file that you'd like to write, or an IO-like object.



145
146
147
# File 'lib/r509/privatekey.rb', line 145

def write_pem(filename_or_io)
    write_data(filename_or_io, self.to_pem)
end