#! /usr/local/bin/ruby1.9 -w
#  encoding: utf-8
#
#  Code based on:
#     http://stuff-things.net/2008/02/05/encrypting-lots-of-sensitive-data-with-ruby-on-rails/
#
require 'openssl'

TEST_MESSAGE = "The quick brown fox jumped over the lazy fox."

module EncryptDecrypt
    
    def self.encryptData(data, publicKey)
        #  Create Cipher to encrypt using 256 bit AES with CBC
        cipher = OpenSSL::Cipher.new('aes-256-cbc')
        cipher.encrypt
        
        # Generate random keys and IVs
        cipher.key = random_key = cipher.random_key
        cipher.iv  = random_iv  = cipher.random_iv
        
        #  Encrypt the data
        encrypted_data = cipher.update(data)
        encrypted_data << cipher.final
        
        #  Encrypt the key
        encrypted_key = publicKey.public_encrypt(random_key)
        encrypted_iv  = publicKey.public_encrypt(random_iv)
        
        return encrypted_data, encrypted_key, encrypted_iv
    end
    
    def self.decryptData(data, key, iv, privateKey)
        
        #  Create Cipher to decrypt using 256 bit AES with CBC
        cipher = OpenSSL::Cipher.new('aes-256-cbc')
        cipher.decrypt
        
        #  Decrypt the key and iv
        cipher.key = privateKey.private_decrypt(key)
        cipher.iv  = privateKey.private_decrypt(iv)
        
        #  Decrypt the message
        decrypted_data = cipher.update(data)
        decrypted_data << cipher.final
        
        return decrypted_data
    end
end

publicKeyPEM = <<PUBLIC
-----BEGIN PUBLIC KEY-----
MIHfMA0GCSqGSIb3DQEBAQUAA4HNADCByQKBwQDa+BX2/hhNkn1NUkeE3D7kZyOX
TtHmFZFtxQXuJ+cN4lzPaBf4SWekpUvD4yrn3Qyv25Ro08REaMh0uyMfQtPD4J1V
KyF/4KDv0wC2F1pOBJOyTUqU6hGPL2eqJgP25X2S43dY8HBaL+BuEvZ6yUcZfqWO
MOACd7V+X/GqPkHxvDwi6kVZoAPVwJsOPvz4K2VRNEWCrwRZFj2JDmiWA/94W0W9
d3wYTS0rBBTBKGPdZ6+DmdEyd1fFkOpNJCNL4tsCAwEAAQ==
-----END PUBLIC KEY-----
PUBLIC
    
privateKeyPEM = <<PRIVATE
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,1684A1CF92F241FB

74FWxQ0b25BEQfcB1V/u7HazRdRSt/tu4SuWhX1xfmoAH/HB4UEvP3X8iJQ3ggUP
j58Jnc5yWzWvG6aPI5TqxA5mda2dyE0ATpZjOECkEjspAht8GGzjbjA08sCUhhRN
yMWEigtPciJeT0Kn31SxbgMypucSHXW/R5Ki0MMsnbOoGUlECfSef+y6m4s8queT
EYcMxpZV9k2D3sMVAJcKE2Ki6uirLEDxruv6kvREsXXmva4d5+Cv+WsPlBFIKNGS
Wb2LXST1aLTXjIE3V/qX+zf5J+X2WofXUn/mHrfNmPzC4XbhFsoeqoTrQuaqklWU
lW7l5JuogzCjDDdEORUCOd1MY1r/U6atQx/dm6eQFat+eU1RpV3nSEzpPsTGCua0
8/xeJ4Qxun7uqLw2CLb31ifDFAR3KsmyC+hAJThSuwABDy+JqdX4hgXH7YLkIEPY
YJYEAewRu2roNMBaMSn0MeQi7LRavctGyDjJU/JfFYg1T02qV39x7Wx2rLbi7Kyi
8QQI1A+QoS6cLYscsb76Rq9+wtw6irUVYmzk7Hn0/73sblM6GKhp9hNgalUEzUv8
0c0SBVl9A8Vat/KKaUylKmRNN9kKxSNQr2Ra+ezw/SgX3wZPXtbhjMh8if20ylMR
C8C/wocDyw7/hKRJS8LcaOOD4kKXQvAErrsZm82j/vIrm0rTLJBxqKRn3yyuiA+n
CkzzD1+okCbKEKHxaws9JXs1Y2HmnlByvwgHxFj4jnWMEviZSqNjniCvKBDk0UQD
Do52uY/ki5BJZ0BvL+nqwjnijQW8eD4vi3xh48wKHMaZdew+CImoHhh+PSIFPV6G
dvPF2FK15tz7kAbzhX0U7OryUqLg+2wtVPKGdxo3JeNhg/brlPxwkZ3bhZKvjGXO
J8FSd8KwJqnmJb4LMRCE/YE8Ur9GdBaK7D+cPUMmmHkfGqcBnMeGNxk7T9S3n7Dp
oXSQOQoEwRtviFmdnWSAsLgcdyUMtYSCpWThrAN3bSN/Nbdr78+Db+SLtmUqfZ29
UTP9Cgthp/f6Ny/n6typOvaJWgeW3t9cNn3uPpFWyVR1MryPcZkOsxATpxbxibvB
gw84EqeOnOndOkpCOtlX4DtTLUyLNymDlPk2Eu+2cSXOY4zUNwSsrnpVaYXIcQPm
UI9eGw80ijY8gg9OMLBGsYamQJkRuh4GLu8jJzLZn+IfFD8ENXdvQQ==
-----END RSA PRIVATE KEY-----
PRIVATE
    
publicKey  = OpenSSL::PKey::RSA.new(publicKeyPEM)
privateKey = OpenSSL::PKey::RSA.new(privateKeyPEM,'macruby')

data, key, iv = EncryptDecrypt.encryptData(TEST_MESSAGE, publicKey)
puts EncryptDecrypt.decryptData(data, key, iv, privateKey)


