module PCO::URL::Encryption

Constants

TABLE

avoid vowels to not generate four-letter words, etc. this is important because those words can trigger spam filters when URLs are used in emails

Public Class Methods

decrypt(data, key: @default_key) click to toggle source
# File lib/pco/url/encryption.rb, line 76
def decrypt(data, key: @default_key)
  raise MissingKeyError, "default key or key: argument must be set" if key.nil?
  iv, encrypted = case_corrected(data).split("Z").map { |part| decode(part) }
  raise DecryptError, "not a valid string to decrypt" unless iv && encrypted
  decrypter = cipher(:decrypt, key: key)
  decrypter.iv = iv
  decrypter.update(encrypted) + decrypter.final
end
default_key=(key) click to toggle source
# File lib/pco/url/encryption.rb, line 63
        def default_key=(key)
          raise(<<~ERR) if defined?(@default_key) && @default_key != key
            Don't change the default_key during the life of a process.
            This configuration variable is meant to be set once on boot and not
            touched again.

            If your app needs to use multiple keys, pass them in explicitly to `encrypt`
            and `decrypt`
          ERR

          @default_key = key
        end
encrypt(data, key: @default_key) click to toggle source
# File lib/pco/url/encryption.rb, line 85
def encrypt(data, key: @default_key)
  raise MissingKeyError, "default key or key: argument must be set" if key.nil?
  crypter = cipher(:encrypt, key: key)
  crypter.iv = iv = crypter.random_iv
  "#{encode(iv)}Z#{encode(crypter.update(data) + crypter.final)}"
end

Private Class Methods

case_corrected(data) click to toggle source
# File lib/pco/url/encryption.rb, line 94
def case_corrected(data)
  return data unless data[26] == "z"
  data.tr("a", "A").sub(/\A([#{TABLE}]{26})z/, '\1Z')
end
chunks(str, size) click to toggle source
# File lib/pco/url/encryption.rb, line 99
def chunks(str, size)
  result = []
  bytes = str.bytes
  while bytes.any?
    result << Chunk.new(bytes.take(size))
    bytes = bytes.drop(size)
  end
  result
end
cipher(mode, key:) click to toggle source
# File lib/pco/url/encryption.rb, line 118
def cipher(mode, key:)
  cipher = OpenSSL::Cipher.new("aes-256-cbc")
  cipher.public_send(mode)
  cipher.key = key
  cipher
end
decode(data) click to toggle source
# File lib/pco/url/encryption.rb, line 114
def decode(data)
  chunks(data, 8).collect(&:decode).flatten.join
end
encode(data) click to toggle source

strip “=” padding, because we don“t need it

# File lib/pco/url/encryption.rb, line 110
def encode(data)
  chunks(data, 5).collect(&:encode).flatten.join.tr("=", "")
end