Skip to content

Instantly share code, notes, and snippets.

@knugie
Created March 26, 2022 07:56
Show Gist options
  • Save knugie/0637a1bcfd38302a64358b88c4b3b70f to your computer and use it in GitHub Desktop.
Save knugie/0637a1bcfd38302a64358b88c4b3b70f to your computer and use it in GitHub Desktop.
WIP: Ruby AES Encryption using AES-256-GCM
require 'openssl'
################
# Public Input #
################
hex_message = 'a9a08f273d9e96d567ccc3db8f6a6634c895973a260e2b7cb36c1dde457293102163900cc12ffe4ec51aa02db70a0979b510911fa99d50aeadd67f7ff0c37a8ab82e5e45cb4b7d713e8365b1f0e67e188e2807fa31f674f25318de6de122517a06cfa018e0edf308eeaa87530720ecdcac42'
auth_data = 'something'
################
# Secret Input #
################
password = 'Pa$$w0rd!'
################################################################################
message = [hex_message].pack('H*')
cipher_text = message[0..-29]
iv = message[-28..-17]
auth_tag = message[-16..-1]
alg = 'aes-256-gcm'
cipher = OpenSSL::Cipher.new(alg)
cipher.decrypt
cipher.iv = iv
cipher.key = Digest::SHA256.new.update(password).digest
cipher.auth_data = auth_data
cipher.auth_tag = auth_tag
plain_text = cipher.update(cipher_text) + cipher.final
#################
# Secret Output #
#################
puts plain_text
require 'openssl'
# We use the AES 256 bit Galois/Counter Mode (GCM) symetric encryption.
# AES 256 is virtually impenetrable using brute-force methods.
# However, CBC introduces a data integrity vulnerability (stream cipher attacks).
# We use GCM to mitigate the issue. This mode of operation is an authenticated
# encryption algorithm designed to provide both data authenticity (integrity) and confidentiality.
alg = 'aes-256-gcm'
cipher = OpenSSL::Cipher.new(alg)
cipher.encrypt
cipher.auth_tag_len = 128
# => OpenSSL::Cipher::CipherError: unable to set authentication tag length
# :-( Ferguson and Saarinen: If the tag length t is shorter than 128, then each successful forgery in this attack increases the probability that subsequent targeted forgeries will succeed
################
# Secret Input #
################
plain_text = 'All the non-obvious zeros of the zeta function are complex numbers with real part 1/2.'
password = 'Pa$$w0rd!' # Please choose a strong password! Hackers don't break in – they log in ;-)
################
# Public Input #
################
# For security as part of the encryption algorithm, we create a random
# initialization vector. An initialization vector (iv) is used to prevent
# a sequence of text that is identical to a previous sequence from producing
# the same exact ciphertext when encrypted. It does not need to be kept secret.
iv = cipher.random_iv
# For security as part of the encryption algorithm, we set any additional
# authenticated data (AAD) in order to generate a suitable authentication tag.
# The authentication strength depends on the length of the authentication tag,
# like with all symmetric message authentication codes. The use of shorter authentication
# tags with GCM is discouraged. The bit-length of the tag, denoted t, is a security parameter.
auth_data = 'something'
################################################################################
# We use SHA256 as a key derivation function to get a 256 bit key from the initial password
key = Digest::SHA256.new.update(password).digest
raise 'iv must have length 12' unless iv.length == 12
cipher.iv = iv
raise 'key must have length 32' unless key.length == 32
cipher.key = key
cipher.auth_data = auth_data
cipher_text = cipher.update(plain_text) + cipher.final
cipher.auth_tag_len=128
auth_tag = cipher.auth_tag
raise 'auth_tag must have length 16' unless auth_tag.length == 16
message = cipher_text + iv + auth_tag
hex_message = (message).unpack('H*').first
#################
# Public Output #
#################
puts hex_message
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment