Простое шифрование в Ruby без внешних камней

Мне нужно простое шифрование для некоторых текстовых строк. Я хочу создать коды купонов и заставить их выглядеть круто, поэтому впоследствии созданный код должен выглядеть совсем по-другому. (И, кроме того, выглядеть круто, не должно быть легко угадать код. Но я хочу иметь возможность расшифровать их снова. Поэтому алгоритм должен быть обратимым.

Я alread пробовал некоторые вещи с движущимися битами, поэтому они выглядят уже случайными. Но два последующих кода (только один бит отличается), конечно, выглядят очень подобный.

какие предложения? Я хотел бы сделать это без использования внешних камней.

Филипп

8 ответов


Вы можете использовать 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"

но промежуточная форма не поддается печати


учитывая вашу мысль, что было бы неплохо, если бы промежуточная форма была одинаковой длины, вы могли бы просто использовать простую карту одного символа к другому.

ПОЖАЛУЙСТА, ПОЙМИТЕ, ЧТО ЭТО НЕ БЕЗОПАСНО

Вы можете легко грубая сила ключ, но он, кажется, согласуется с вашим требования.

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"

Если вам не нужно реальное шифрование, вы можете использовать простой шифр. (Это можно использовать, когда вам не нужна безопасность или шифровать короткие случайные/одноразовые строки.)

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

для основной цели кодирования / декодирования я думаю, что встроенная библиотека Base64 ruby может быть удобна:

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 методы версии в случае, если закодированные строки должны использоваться в URL-адресах.

ссылка:http://ruby-doc.org/stdlib-2.3.0/libdoc/base64/rdoc/Base64.html


Я могу порекомендовать вам uuencode и uudecode utils вы можете использовать их wuth standart ruby function pack:

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

(образец из рубинового пути Хэла Фултона)


вы действительно хотите доверять пользователю, чтобы вернуть правильное значение? Если Вы доверяете тому, что клиент возвращает вам, и пользователь выясняет вашу схему шифрования, вы будете использовать данные, которые они предоставляют. Звучит как очень плохая идея.

Мне непонятно, почему вы не хотите давать им ключ в базу данных, которая отображает случайные числа, возможно, с некоторыми свойствами исправления ошибок, к скидкам купона. Таким образом, вы контролируете конечный результат. Они обеспечивают вас ключ, вы ищете связанный купон и применяете купон. Таким образом, вы используете только свои собственные данные, и если вы хотите удалить купон, все это на стороне сервера.

Если вы сохраняете все коды ключей, вы также можете проверить, что новые коды отличаются от ранее выпущенных.


Я думаю, что самый простой способ-a * x + b (mod 2^n)

обратите внимание, что вам нужно вычислить обратный от a на 2^n, вы можете это сделать с Wolfram Alpha с помощью расширенного GCD.


необязательный метод шифрования и дешифрования

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)

вы можете проверить все различные способы шифрования / дешифрования с помощью ruby в этом gist:https://gist.github.com/iufuenza/183a45c601a5c157a5372c5f1cfb9e3e

Если вы не хотите использовать драгоценный камень, я бы полностью рекомендовал Openssl как самый безопасный, который также очень легко реализовать, поскольку он имеет очень хорошую поддержку Ruby.