Created
October 17, 2025 08:03
-
-
Save alfuken/b4d0cae0c831657da1fb452f4c6f1dad to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # frozen_string_literal: true | |
| # LICENSE: MIT | |
| # | |
| # A very simple deterministic string encryption. | |
| # Variation of a Caesar cipher. | |
| # | |
| # Intended to be used with strings, | |
| # primary purpose of this approach is to merely make it *harder* for an eavesdropper | |
| # to see the actual data contained in a string. | |
| # | |
| # This is in no way a replacement for a "proper" encryption, but it's fast as all hells, | |
| # and, unlike "proper" encryption methods, increases string length only slightly | |
| # (`Base64.urlsafe_encode64` overhead), which can sometimes be crucial. | |
| # | |
| # | |
| # Usage: | |
| # | |
| # require "dencrypt" | |
| # | |
| # things = "Eggs, brains, signals, wires." | |
| # things.length #=> 29 | |
| # mush = Dencrypt.scramble(things) #=> "3tbFotPazpak3dnXu-CujojhmNHQ3N1U0Y6S0N0" | |
| # mash = Dencrypt.scramble(things) #=> "3tbFotPazpak3dnXu-CujojhmNHQ3N1U0Y6S0N0" | |
| # mush == mash #=> true | |
| # mush.length #=> 39 | |
| # neat = Dencrypt.unscramble(mush) #=> "Eggs, brains, signals, wires." | |
| # neat == things #=> true | |
| # | |
| module Dencrypt | |
| class DencryptionError < StandardError; end | |
| class EncryptionError < DencryptionError; end | |
| class DecryptionError < DencryptionError; end | |
| DENCRYPTION_KEY = defined?(Rails) ? Rails.application.secret_key_base : ENV.fetch("DENCRYPTION_KEY") | |
| module_function def scramble(data) | |
| seed = Digest::MD5.hexdigest(DENCRYPTION_KEY.to_s).to_i(16) # deterministic seed integer for Random | |
| key = DENCRYPTION_KEY.bytes.cycle | |
| data.bytes. # for each byte in the string stream, | |
| map{|byte| ((byte + key.next) % 255).chr }. # perform a simple byte shift | |
| shuffle(random: Random.new(seed)). # then sprinkle with deterministic Array#shuffle on top, | |
| join. # to make things interesting. | |
| then{ Base64.urlsafe_encode64 _1, padding: false } | |
| rescue | |
| raise EncryptionError.new | |
| end | |
| # Well, duh. | |
| module_function def unscramble(data) | |
| seed = Digest::MD5.hexdigest(DENCRYPTION_KEY.to_s).to_i(16) # same deterministic seed int | |
| key = DENCRYPTION_KEY.bytes.cycle | |
| Base64.urlsafe_decode64(data).bytes. | |
| unshuffle(random: Random.new(seed)). # <- hero of the day! | |
| map{|byte| ((byte - key.next) % 255).chr }. # shift that byte back | |
| join | |
| rescue | |
| raise DecryptionError.new | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment