Simple Encryption in Ruby without external gems

2019-01-17 07:06发布

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

8条回答
Viruses.
2楼-- · 2019-01-17 07:45

I can recommend you uuencode and uudecode utils you can use them wuth standart ruby function pack:

str = "\007\007\002\abcde"
new_string = [str].pack("u")
original = new_string.unpack("u")

(sample from Hal Fulton's Ruby Way)

查看更多
Emotional °昔
3楼-- · 2019-01-17 07:48

You could use OpenSSL::Cypher

# 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"
查看更多
We Are One
4楼-- · 2019-01-17 07:52

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
查看更多
Root(大扎)
5楼-- · 2019-01-17 07:58

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)
查看更多
贪生不怕死
6楼-- · 2019-01-17 07:59

You can check all different ways of encryption/decryption using ruby in this gist: https://gist.github.com/iufuenza/183a45c601a5c157a5372c5f1cfb9e3e

If you don't want to use a gem, I would totally recommend Openssl as the most secure which is also very easy to implement as it has very good Ruby support.

查看更多
看我几分像从前
7楼-- · 2019-01-17 08:01

Do you really want to trust the user to give you back the right value? If you trust what the client gives you back and the user figures out your encryption scheme you'll be using data they provide. That sounds like a very bad idea.

It's not clear to me why you don't want to give them a key into a database that maps a random numbers, perhaps with some error correction properties, to the coupon discounts. That way you have control of the final result. They provide you a key, you look up the associated coupon and apply the coupon. In this way you're only using your own data and if you want to remove a coupon it's all on the server side.

If you keep all the key-codes you can also check that new codes are different from previously released ones.

查看更多
登录 后发表回答