class MCollective::SSL

A class that assists in encrypting and decrypting data using a combination of RSA and AES

Data will be AES encrypted for speed, the Key used in # the AES stage will be encrypted using RSA

ssl = SSL.new(public_key, private_key, passphrase)

data = File.read("largefile.dat")

crypted_data = ssl.encrypt_with_private(data)

pp crypted_data

This will result in a hash of data like:

crypted = {:key  => "crd4NHvG....=",
           :data => "XWXlqN+i...=="}

The key and data will all be base 64 encoded already by default you can pass a 2nd parameter as false to #encrypt_with_private and counterparts that will prevent the base 64 encoding

You can pass the data hash into ssl.decrypt_with_public which should return your original data

There are matching methods for using a public key to encrypt data to be decrypted using a private key

Attributes

private_key_file[R]
public_key_file[R]
ssl_cipher[R]

Public Class Methods

base64_decode(string) click to toggle source
# File lib/mcollective/ssl.rb, line 180
def self.base64_decode(string)
    Base64.decode64(string)
end
base64_encode(string) click to toggle source
# File lib/mcollective/ssl.rb, line 171
def self.base64_encode(string)
    Base64.encode64(string)
end
new(pubkey=nil, privkey=nil, passphrase=nil, cipher=nil) click to toggle source
# File lib/mcollective/ssl.rb, line 36
def initialize(pubkey=nil, privkey=nil, passphrase=nil, cipher=nil)
    @public_key_file = pubkey
    @private_key_file = privkey

    @public_key  = read_key(:public, pubkey)
    @private_key = read_key(:private, privkey, passphrase)

    @ssl_cipher = "aes-256-cbc"
    @ssl_cipher = Config.instance.ssl_cipher if Config.instance.ssl_cipher
    @ssl_cipher = cipher if cipher

    raise "The supplied cipher '#{@ssl_cipher}' is not supported" unless OpenSSL::Cipher.ciphers.include?(@ssl_cipher)
end

Public Instance Methods

aes_decrypt(key, crypt_string) click to toggle source

decrypts a string given key, iv and data

# File lib/mcollective/ssl.rb, line 157
def aes_decrypt(key, crypt_string)
    cipher = OpenSSL::Cipher::Cipher.new(ssl_cipher)

    cipher.decrypt
    cipher.key = key
    cipher.pkcs5_keyivgen(key)
    decrypted_data = cipher.update(crypt_string) + cipher.final
end
aes_encrypt(plain_string) click to toggle source

encrypts a string, returns a hash of key, iv and data

# File lib/mcollective/ssl.rb, line 143
def aes_encrypt(plain_string)
    cipher = OpenSSL::Cipher::Cipher.new(ssl_cipher)
    cipher.encrypt

    key = cipher.random_key

    cipher.key = key
    cipher.pkcs5_keyivgen(key)
    encrypted_data = cipher.update(plain_string) + cipher.final

    {:key => key, :data => encrypted_data}
end
base64_decode(string) click to toggle source

base 64 decode a string

# File lib/mcollective/ssl.rb, line 176
def base64_decode(string)
    SSL.base64_decode(string)
end
base64_encode(string) click to toggle source

base 64 encode a string

# File lib/mcollective/ssl.rb, line 167
def base64_encode(string)
    SSL.base64_encode(string)
end
decrypt_with_private(crypted, base64=true) click to toggle source

Decrypts data, expects a hash as create with crypt_with_public

# File lib/mcollective/ssl.rb, line 87
def decrypt_with_private(crypted, base64=true)
    raise "Crypted data should include a key" unless crypted.include?(:key)
    raise "Crypted data should include data" unless crypted.include?(:data)

    if base64
        key = rsa_decrypt_with_private(base64_decode(crypted[:key]))
        aes_decrypt(key, base64_decode(crypted[:data]))
    else
        key = rsa_decrypt_with_private(crypted[:key])
        aes_decrypt(key, crypted[:data])
    end
end
decrypt_with_public(crypted, base64=true) click to toggle source

Decrypts data, expects a hash as create with crypt_with_private

# File lib/mcollective/ssl.rb, line 101
def decrypt_with_public(crypted, base64=true)
    raise "Crypted data should include a key" unless crypted.include?(:key)
    raise "Crypted data should include data" unless crypted.include?(:data)

    if base64
        key = rsa_decrypt_with_public(base64_decode(crypted[:key]))
        aes_decrypt(key, base64_decode(crypted[:data]))
    else
        key = rsa_decrypt_with_public(crypted[:key])
        aes_decrypt(key, crypted[:data])
    end
end
encrypt_with_private(plain_text, base64=true) click to toggle source

Encrypts supplied data using AES and then encrypts using RSA the key and IV

Return a hash with everything optionally base 64 encoded

# File lib/mcollective/ssl.rb, line 72
def encrypt_with_private(plain_text, base64=true)
    crypted = aes_encrypt(plain_text)

    if base64
        key = base64_encode(rsa_encrypt_with_private(crypted[:key]))
        data = base64_encode(crypted[:data])
    else
        key = rsa_encrypt_with_private(crypted[:key])
        data = crypted[:data]
    end

    {:key => key, :data => data}
end
encrypt_with_public(plain_text, base64=true) click to toggle source

Encrypts supplied data using AES and then encrypts using RSA the key and IV

Return a hash with everything optionally base 64 encoded

# File lib/mcollective/ssl.rb, line 54
def encrypt_with_public(plain_text, base64=true)
    crypted = aes_encrypt(plain_text)

    if base64
        key = base64_encode(rsa_encrypt_with_public(crypted[:key]))
        data = base64_encode(crypted[:data])
    else
        key = rsa_encrypt_with_public(crypted[:key])
        data = crypted[:data]
    end

    {:key => key, :data => data}
end
read_key(type, key=nil, passphrase=nil) click to toggle source

Reads either a :public or :private key from disk, uses an optional passphrase to read the private key

# File lib/mcollective/ssl.rb, line 186
def read_key(type, key=nil, passphrase=nil)
    return key if key.nil?

    raise "Could not find key #{key}" unless File.exist?(key)

    if type == :public
        return OpenSSL::PKey::RSA.new(File.read(key))
    elsif type == :private
        return OpenSSL::PKey::RSA.new(File.read(key), passphrase)
    else
        raise "Can only load :public or :private keys"
    end
end
rsa_decrypt_with_private(crypt_string) click to toggle source

Use the private key to RSA decrypt data

# File lib/mcollective/ssl.rb, line 122
def rsa_decrypt_with_private(crypt_string)
    raise "No private key set" unless @private_key

    @private_key.private_decrypt(crypt_string)
end
rsa_decrypt_with_public(crypt_string) click to toggle source

Use the public key to RSA decrypt data

# File lib/mcollective/ssl.rb, line 136
def rsa_decrypt_with_public(crypt_string)
    raise "No public key set" unless @public_key

    @public_key.public_decrypt(crypt_string)
end
rsa_encrypt_with_private(plain_string) click to toggle source

Use the private key to RSA encrypt data

# File lib/mcollective/ssl.rb, line 129
def rsa_encrypt_with_private(plain_string)
    raise "No private key set" unless @private_key

    @private_key.private_encrypt(plain_string)
end
rsa_encrypt_with_public(plain_string) click to toggle source

Use the public key to RSA encrypt data

# File lib/mcollective/ssl.rb, line 115
def rsa_encrypt_with_public(plain_string)
    raise "No public key set" unless @public_key

    @public_key.public_encrypt(plain_string)
end