class EzCrypto::Key
The Key is the only class you need to understand for simple use.
Algorithms¶ ↑
The crypto algorithms default to aes-128-cbc however on any of the class
methods you can change it to one of the standard openssl cipher names using
the optional :algorithm=>alg name
parameter.
Eg.
Key.new @raw, :algorithm=>"des" Key.generate :algorithm=>"blowfish" Key.with_password @pwd,@salt,:algorithm=>"aes256"
License¶ ↑
ActiveCrypto and EzCrypto are released under the MIT license.
Support¶ ↑
To contact the author, send mail to pelleb@gmail.com
Also see my blogs at: stakeventures.com and neubia.com
This project was based on code used in my project StakeItOut, where you can securely share web services with your partners. stakeitout.com
(C) 2005 Pelle Braendgaard
Attributes
Public Class Methods
Return the block-size for IO-operations.
# File lib/ezcrypto.rb, line 59 def self.block_size @@block_size end
Set the block-size for IO-operations (default: 512 bytes)
# File lib/ezcrypto.rb, line 52 def self.block_size=(size) @@block_size = size end
Given an algorithm this calculates the keysize. This is used by both the generate and ::with_password methods. This is not yet 100% complete.
# File lib/ezcrypto.rb, line 123 def self.calculate_key_size(algorithm) if !algorithm.nil? algorithm=~/^([[:alnum:]]+)(-(\d+))?/ if $3 size=($3.to_i)/8 else case $1 when "bf" size = 16 when "blowfish" size = 16 when "des" size = 8 when "des3" size = 24 when "aes128" size = 16 when "aes192" size = 24 when "aes256" size = 32 when "rc2" size = 16 when "rc4" size = 16 else size = 16 end end end if size.nil? size = 16 end size end
Initialize the key with Base64 encoded key data.
# File lib/ezcrypto.rb, line 90 def self.decode(encoded,options = {}) Key.new(Base64.decode64(encoded),options) end
Decrypts the data with the given password and a salt. Short hand for:
key=Key.with_password(password,salt,options) key.decrypt(data)
# File lib/ezcrypto.rb, line 114 def self.decrypt_with_password(password,salt,data,options = {}) key=Key.with_password(password,salt,options) key.decrypt(data) end
Encrypts the data with the given password and a salt. Short hand for:
key=Key.with_password(password,salt,options) key.encrypt(data)
# File lib/ezcrypto.rb, line 101 def self.encrypt_with_password(password,salt,data,options = {}) key=Key.with_password(password,salt,options) key.encrypt(data) end
Generate random key.
# File lib/ezcrypto.rb, line 76 def self.generate(options = {}) Key.new(EzCrypto::Digester.generate_key(calculate_key_size(options[:algorithm])),options) end
Load a key from a yaml_file generated via #store.
# File lib/ezcrypto.rb, line 290 def self.load(filename) require 'yaml' hash = YAML::load_file(filename) req = proc { |k| hash[k] or raise "Missing element #{k} in #{filename}" } key = self.new Base64.decode64(req.call(:key)) , :algorithm => req.call(:algorithm) return key end
Initialize the key with raw unencoded binary key data. This needs to be at least 16 bytes long for the default aes-128 algorithm.
# File lib/ezcrypto.rb, line 68 def initialize(raw,options = {}) @raw=raw @algorithm=options[:algorithm]||"aes-128-cbc" end
Create key generated from the given password and salt
# File lib/ezcrypto.rb, line 83 def self.with_password(password,salt,options = {}) Key.new(EzCrypto::Digester.get_key(password,salt,calculate_key_size(options[:algorithm])),options) end
Public Instance Methods
Decrypts the data passed to it in binary format.
# File lib/ezcrypto.rb, line 196 def decrypt(data) if data==nil || data=="" nil else decrypter("") @cipher.gulp(data) end # rescue # puts @algorithm # puts self.encode # puts data.size # throw $! end
Decrypts a Base64 formatted string
# File lib/ezcrypto.rb, line 213 def decrypt64(data) decrypt(Base64.decode64(data)) end
Decrypt a file 'inplace' and remove a suffix see cipher_file IMPORTANT: The inputfile will be deleted by default.
# File lib/ezcrypto.rb, line 383 def decrypt_file(src, tgt=nil, options = {} ) options = { :suffix => '.ez', :autoclean => 'true' }.update(options) unless tgt tgt = src tgt = tgt.gsub(/#{options[:suffix]}$/, '') end cipher_file :on_decrypter, src, tgt, options[:autoclean] end
Get a Decrypter object. You have to call final on it by yourself!
# File lib/ezcrypto.rb, line 327 def decrypter(target='') @cipher = EzCrypto::Decrypter.new(self,target,@algorithm) end
returns the Base64 encoded key.
# File lib/ezcrypto.rb, line 163 def encode Base64.encode64(@raw).chop end
Encrypts the data and returns it in encrypted binary form.
# File lib/ezcrypto.rb, line 177 def encrypt(data) if data==nil || data=="" nil else encrypter("") @cipher.encrypt(data) end end
Encrypts the data and returns it in encrypted Base64 encoded form.
# File lib/ezcrypto.rb, line 189 def encrypt64(data) Base64.encode64(encrypt(data)) end
Encrypt a file 'inplace' and add a suffix see cipher_file. IMPORTANT: The inputfile will be deleted by default.
# File lib/ezcrypto.rb, line 371 def encrypt_file(src, tgt=nil, options = {} ) options = { :suffix => '.ez', :autoclean => 'true' }.update(options) tgt = "#{src}#{options[:suffix]}" unless tgt cipher_file :on_encrypter, src, tgt, options[:autoclean] end
Get a Encrypter object. You have to call final on it by yourself!
# File lib/ezcrypto.rb, line 319 def encrypter(target='') @cipher = EzCrypto::Encrypter.new(self,target,@algorithm) end
Allows keys to be marshalled
# File lib/ezcrypto.rb, line 220 def marshal_dump "#{self.algorithm}$$$#{self.encode}" end
Allows keys to be unmarshalled
# File lib/ezcrypto.rb, line 227 def marshal_load(s) a, r = s.split '$$$' @algorithm = a @raw = Base64.decode64(r) end
Create a Decrypter object and yield it to a block. You must not call final by yourself, the method does this.
# File lib/ezcrypto.rb, line 336 def on_decrypter(target='', &block) decrypter(target) on_cipher(&block) end
Create an Encrypter object and yield it to a block. You must not call final by yourself, the method does this.
# File lib/ezcrypto.rb, line 346 def on_encrypter(target='', &block) encrypter(target) on_cipher(&block) end
Save the key data into a file, try to do this in a secure manner. NOTE: YAML::store & friends are not used to encance control over the generated file format.
# File lib/ezcrypto.rb, line 304 def store(filename) safe_create(filename) do |f| selfenc = self.encode f.puts "---" f.puts ":EZCRYPTO KEY FILE: KEEP THIS SECURE !" f.puts ":created: #{Time.now}" f.puts ":algorithm: #{@algorithm}" f.puts ":key: #{selfenc}" end end
returns the Base64 encoded key. Synonym for encode.
# File lib/ezcrypto.rb, line 170 def to_s encode end
Private Instance Methods
uses either on_decrypter or on_encrypter to transform a given sourcefile to a targetfile. the sourcefile is deleted after sucessful transformation the delete_source is 'true'.
# File lib/ezcrypto.rb, line 398 def cipher_file(method, sourcefile, targetfile, delete_source) raise(ArgumentError, "source == target #{sourcefile}") if sourcefile == targetfile safe_create(targetfile,0600) do |o| self.send(method, o) do |c| safe_read(sourcefile) do |i| loop do buffer = i.read(Key.block_size) or break c << buffer end end end end safe_delete(sourcefile) if delete_source && File.exists?(targetfile) return targetfile end
Helper method, yields the current cipher to a block.
# File lib/ezcrypto.rb, line 355 def on_cipher(&block) begin block.call @cipher ensure @cipher.final end end
Create a file with minimal permissions, and yield it to a block. By default only the owner may read it.
# File lib/ezcrypto.rb, line 237 def safe_create(file, mod=0400, mask=0066) begin old_umask = File.umask File.umask(mask) File.open(file, File::CREAT | File::EXCL | File::WRONLY) do |f| yield(f) if block_given? end ensure File.umask(old_umask) end File.chmod(mod, file) if File.exists?(file) File.size(file) end
Overwrite a file with zero values before removing it's filesystem inode. This is not very safe :-)
# File lib/ezcrypto.rb, line 256 def safe_delete(file) begin to_clear = File.size(file) zeroes = Array.new(Key.block_size, "\0").join File.chmod(0600, file) File.open(file, File::WRONLY) do |f| f.rewind while to_clear > 0 f.write(zeroes) to_clear -= Key.block_size end f.flush end ensure File.delete(file) if File.exists?(file) end return !File.exists?(file) end
Open a file readonly and yield it to a block.
# File lib/ezcrypto.rb, line 279 def safe_read(file) File.open(file, File::RDONLY) do |i| yield(i) if block_given? end end