Ruby中的简单加密,没有外部宝石

时间:2010-11-08 22:52:55

标签: ruby encryption encryption-symmetric

我需要对某些文本字符串进行简单加密。我想创建优惠券代码并使它们看起来很酷,因此随后创建的代码应该看起来非常不同。 (除了看起来很酷,猜测代码也不容易。)但我希望能够再次解密它们。所以算法必须是可逆的。

我已经尝试了一些移动位的东西,所以它们看起来有点随机。但是两个后续代码(只有一点不同)当然看起来非常相似。

有什么建议吗?我想在不使用外部宝石的情况下这样做。

菲利普

9 个答案:

答案 0 :(得分:42)

您可以使用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"

但是中间形式不适合印刷


鉴于您认为如果中间形式长度相同会很好,您可能只使用一个char的简单映射到另一个。

请理解这不安全

您可以轻松强制关键,但它似乎与您的要求一致。

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"

答案 1 :(得分:16)

如果您不需要真正的加密,可以使用简单的密码。 (当您不需要安全性或加密短随机/一次性字符串时,可以使用此方法。)

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

答案 2 :(得分:7)

对于基本的编码/解码目的,我猜ruby内置的Base64库可以很方便:

2.2.1 :001 > require 'base64'
 => true 
2.2.1 :002 > str = "abc@example.com"
 => "abc@example.com" 
2.2.1 :003 > Base64.encode64(str)
 => "YWJjQGV4YW1wbGUuY29t\n" 

如果要在网址中使用编码字符串,它还有 urlsafe 版本方法。

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

答案 3 :(得分:3)

我可以推荐你uuencode和uudecode utils 您可以将它们与标准的ruby功能包一起使用:

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

(来自Hal Fulton的Ruby Way的样本)

答案 4 :(得分:3)

加密和解密的可选方法

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)

答案 5 :(得分:2)

您真的想要信任用户给您正确的价值吗?如果您信任客户端回馈的内容并且用户确定您的加密方案,那么您将使用他们提供的数据。这听起来是一个非常糟糕的主意。

我不清楚为什么你不想给他们一个密钥到一个数据库,该数据库将随机数(可能带有一些纠错属性)映射到优惠券折扣。这样你就可以控制最终的结果了。他们为您提供钥匙,您查找相关的优惠券并申请优惠券。通过这种方式,您只使用自己的数据,如果要删除优惠券,则只需在服务器端进行。

如果保留所有密钥代码,您还可以检查新代码是否与以前发布的密码不同。

答案 6 :(得分:2)

我猜最简单的方法是* x + b(mod 2 ^ n)

请注意,你需要计算on 2 ^ n的倒数,你可以使用扩展GCD计算Wolfram Alpha的倒数。

答案 7 :(得分:0)

您可以在此要点中使用ruby检查所有不同的加密/解密方式:https://gist.github.com/iufuenza/183a45c601a5c157a5372c5f1cfb9e3e

如果您不想使用gem,我会完全推荐Openssl作为最安全的,因为它具有非常好的Ruby支持,因此也很容易实现。

答案 8 :(得分:0)

我知道您正在寻找一种没有宝石的加密方法,但是仍然希望向那些在这里且不用担心使用外部宝石的人提供加密服务。尝试glogin(我是作者):

require 'glogin/codec'
codec = GLogin:Codec.new('the secret')
encrypted = codec.encrypt('Hello, world!')
decrypted = codec.decrypt(encrypted)

它基于OpenSSL和Base58。