Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple Encryption in Ruby without external gems

I need a simple encryption for some text strings. I want to create coupon codes and make them look cool so subsequently created code should look very different. (And besides looking cool, it shouldn't be easy to guess a code.) But I want to be able to decrypt them again. So the algorithm must be reversible.

I alread tried some stuff with moving bits around so they look kind of random already. But two subsequent codes (just one bit different) of course look very similar.

Any suggestions? I would like to do that without using external gems.

Philip

like image 751
Philip Avatar asked Nov 08 '10 22:11

Philip


4 Answers

You could use OpenSSL::Cipher

# for more info, see http://ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/Cipher.html

require 'openssl'
require 'digest/sha1'

# create the cipher for encrypting
cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
cipher.encrypt

# you will need to store these for later, in order to decrypt your data
key = Digest::SHA1.hexdigest("yourpass")
iv = cipher.random_iv

# load them into the cipher
cipher.key = key
cipher.iv = iv

# encrypt the message
encrypted = cipher.update('This is a secure message, meet at the clock-tower at dawn.')
encrypted << cipher.final
puts "encrypted: #{encrypted}\n"

# now we create a sipher for decrypting
cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
cipher.decrypt
cipher.key = key
cipher.iv = iv

# and decrypt it
decrypted = cipher.update(encrypted)
decrypted << cipher.final
puts "decrypted: #{decrypted}\n"

But the intermediate form doesn't lend itself well to printing


Given your thought that it would be nice if the intermediate form was the same length, you might just use a simple map of one char to another.

PLEASE UNDERSTAND THAT THIS IS NOT SECURE

You can easily brute force the key, but it seems to be congruent with your requirements.

class Cipher
  
  def initialize(shuffled)
    normal = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a + [' ']
    @map = normal.zip(shuffled).inject(:encrypt => {} , :decrypt => {}) do |hash,(a,b)|
      hash[:encrypt][a] = b
      hash[:decrypt][b] = a
      hash
    end
  end

  def encrypt(str)
    str.split(//).map { |char| @map[:encrypt][char] }.join
  end
  
  def decrypt(str)
    str.split(//).map { |char| @map[:decrypt][char] }.join
  end
  
end

# pass the shuffled version to the cipher
cipher = Cipher.new ["K", "D", "w", "X", "H", "3", "e", "1", "S", "B", "g", "a", "y", "v", "I", "6", "u", "W", "C", "0", "9", "b", "z", "T", "A", "q", "U", "4", "O", "o", "E", "N", "r", "n", "m", "d", "k", "x", "P", "t", "R", "s", "J", "L", "f", "h", "Z", "j", "Y", "5", "7", "l", "p", "c", "2", "8", "M", "V", "G", "i", " ", "Q", "F"]

msg = "howdy pardner"

crypted = cipher.encrypt msg
crypted # => "1IzXAF6KWXvHW"

decrypted = cipher.decrypt crypted
decrypted # => "howdy pardner"
like image 180
Joshua Cheek Avatar answered Nov 07 '22 13:11

Joshua Cheek


If you don't need real encryption, you can use a simple cipher. (This can be used when you don't need security, or to encrypt short random/one-off strings.)

ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

#generated with ALPHABET.split('').shuffle.join
ENCODING = "MOhqm0PnycUZeLdK8YvDCgNfb7FJtiHT52BrxoAkas9RWlXpEujSGI64VzQ31w"

def encode(text)
  text.tr(ALPHABET, ENCODING)
end

def decode(text)
  text.tr(ENCODING, ALPHABET)
end
like image 20
Ari Avatar answered Nov 07 '22 12:11

Ari


Optional method for encryption and decryption

gem 'activesupport'

require 'active_support'

key = SecureRandom.random_bytes(32)
crypt = ActiveSupport::MessageEncryptor.new(key)
encrypted_data = crypt.encrypt_and_sign("your password")
password = crypt.decrypt_and_verify(encrypted_data)
like image 18
Prashanth Sams Avatar answered Nov 07 '22 12:11

Prashanth Sams


For basic encoding/decode purpose I guess ruby's inbuilt Base64 library can be handy:

2.2.1 :001 > require 'base64'
 => true 
2.2.1 :002 > str = "[email protected]"
 => "[email protected]" 
2.2.1 :003 > Base64.encode64(str)
 => "YWJjQGV4YW1wbGUuY29t\n" 

It also has the urlsafe version methods in case the encoded strings are to be used in urls.

Reference: http://ruby-doc.org/stdlib-2.3.0/libdoc/base64/rdoc/Base64.html

like image 10
Jignesh Gohel Avatar answered Nov 07 '22 14:11

Jignesh Gohel