Initial catchat commit.

This commit is contained in:
Monqui 2025-07-16 01:48:49 +00:00
commit 8b30fe923c
9 changed files with 460 additions and 0 deletions

1
README.md Normal file
View file

@ -0,0 +1 @@
🐱

BIN
arty_new.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

51
decode_image.rb Normal file
View file

@ -0,0 +1,51 @@
class DecodeImage
@@password = ""
@@utils
def initialize(pass, image)
@@password = pass
# initializing utils...
@@utils = ImageUtils.new(@@password, image)
@@table = @@utils.generateLookupTable
end
def decode
s = @@utils.getImage.getSize
msg_bits = 0
@@table.reverse.each do |loc|
pixel = @@utils.getImage.getPixel(loc[:x], loc[:y])
msg_bits = (msg_bits << 6) | pixel.decodeBits
end
#this trash needs to move somewhere...
puts "Try to convert the message..."
len = msg_bits & 0xffff
msg_bits = msg_bits >> 16
# check the padding bits....
if (msg_bits & 255) != 0 then
puts "Padding failed scrutiny! "
puts msg_bits.to_s(2)
return false
end
msg_bits = msg_bits >> 8
puts "Padding passed scrutiny..."
msg_chars = []
while msg_bits > 0 do
byte = msg_bits & 0xff
msg_chars.push(byte.chr)
msg_bits = msg_bits >> 8
end
msg = msg_chars.reverse.join
return msg
end
end

88
encode_image.rb Normal file
View file

@ -0,0 +1,88 @@
class EncodeImage
@@password = ""
@@message = ""
@@img = nil
@@utils = nil
def initialize(p, m, i)
@@password = p
@@message = m
@@utils = ImageUtils.new(@@password, @@message, i)
@@table = @@utils.generateLookupTable
end
def encode
msg_bits = @@utils.getImage.getBits(@@message)
msg_bits = msg_bits << 8 | 0
msg_bits = msg_bits << 16 | @@message.length
s = @@utils.getImage.getSize
original_img = @@utils.getImage.fuzzImage
@@table.each do |loc|
pixel = @@utils.getImage.getPixel(loc[:x], loc[:y])
msg_bits = pixel.encodeBits(msg_bits)
end
# for x in 0..s[:width]-1
# for y in 0..s[:height]-1
# loc = {"x": x, "y": y}
# if @@table.include? loc then
# pixel = @@utils.getImage.getPixel(x, y)
# msg_bits = pixel.encodeBits(msg_bits)
# end
# end
# end
@@utils.getImage.saveImage
end
# Need to properly sever this at some point...
def decode
puts "Hacked in decode..."
s = @@utils.getImage.getSize
msg_bits = 0
@@table.reverse.each do |loc|
pixel = @@utils.getImage.getPixel(loc[:x], loc[:y])
msg_bits = (msg_bits << 6) | pixel.decodeBits
end
#this trash needs to move somewhere...
puts "Try to convert the message..."
len = msg_bits & 0xffff
msg_bits = msg_bits >> 16
# check the padding bits....
if (msg_bits & 255) != 0 then
puts "Padding failed scrutiny! "
puts msg_bits.to_s(2)
return false
end
msg_bits = msg_bits >> 8
puts "Padding passed scrutiny..."
msg_chars = []
while msg_bits > 0 do
byte = msg_bits & 0xff
msg_chars.push(byte.chr)
msg_bits = msg_bits >> 8
end
msg = msg_chars.reverse.join
return msg
end
end

81
image_utils.rb Normal file
View file

@ -0,0 +1,81 @@
require "./pixel_image.rb"
require "digest"
class ImageUtils
@@magickImg = nil
@@pixelImg = nil
@@password = ""
@@message = ""
@@hash = nil
def initialize(pass, msg, i)
@@password = pass
@@message = msg
if msg.length > 400 then
puts "Maximum length exceeded. Exiting."
exit
end
@@magickImg = i
@@pixelImg = PixelImage.new(@@magickImg)
self.generateHash
end
def getImage
return @@pixelImg
end
def generateHash
h = Digest::SHA512.hexdigest(@@password)
s = @@pixelImg.getSalt
merge_to_i = h + s
@@hash = Digest::SHA512.hexdigest(h+s)
end
def generateLookupTable
tbl = []
hash_bits = @@pixelImg.getBits(@@hash)
msg_bits = @@pixelImg.getBits(@@message)
# gross, but pad in the 24 bits that will become the msg length
# and padding bits...
msg_bits = msg_bits << 24
while msg_bits > 0 do
loc = nil
loop do
x = (hash_bits.to_i % @@pixelImg.getSize[:width])
y = (hash_bits.to_i % @@pixelImg.getSize[:height])
loc = {"x": x, "y": y}
break if !tbl.include?(loc)
hash_bits = hash_bits >> 1
if hash_bits <= 0 then
puts
puts "wow too much data"
puts "leftover bits: " + msg_bits.to_s(36)
exit
end
end
hash_bits = hash_bits >> 1
tbl.push(loc)
msg_bits = msg_bits >> 6
end
return tbl
end
end

BIN
images/original/arty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 KiB

61
pixel.rb Normal file
View file

@ -0,0 +1,61 @@
class Pixel
@mp = nil
@r = 0
@g = 0
@b = 0
def initialize(mp)
@mp = mp
@r = @mp.red
@g = @mp.green
@b = @mp.blue
end
def randomize
@r = ((@r >> 2) << 2) | rand(4)
@g = ((@g >> 2) << 2) | rand(4)
@b = ((@b >> 2) << 2) | rand(4)
end
def getMagickPixel
@mp.red = @r
@mp.green = @g
@mp.blue = @b
return @mp
end
def getPixelBits()
bits = 0
bits = (bits << 8) | @r
bits = (bits << 8) | @g
bits = (bits << 8) | @b
return bits
end
def encodeBits(bits)
@r = ((@r >> 2) << 2) | (bits & 3)
bits = bits >> 2
@g = ((@g >> 2) << 2) | (bits & 3)
bits = bits >> 2
@b = ((@b >> 2) << 2) | (bits & 3)
bits = bits >> 2
return bits
end
def decodeBits
bits = 0
bits = (bits << 2) | (@b & 3)
bits = (bits << 2) | (@g & 3)
bits = (bits << 2) | (@r & 3)
return bits
end
end

128
pixel_image.rb Normal file
View file

@ -0,0 +1,128 @@
require "./pixel.rb"
class PixelImage
@@magickImg = nil
@@pixels = []
def initialize(i)
@@magickImg = i
@@width = @@magickImg.columns
@@height = @@magickImg.rows
self.buildPixels
end
def buildPixels
tmp_pixels = @@magickImg.get_pixels(0, 0, @@width, @@height)
for x in 0..@@width-1
@@pixels[x] = []
for y in 0..@@height-1
@@pixels[x][y] = Pixel.new(tmp_pixels.pop)
end
end
end
# Only used for generating truly random base images
def randomPixels
for x in 0..@@width-1
@@pixels[x] = []
for y in 0..@@height-1
pixel = 0
r = rand(256)
g = rand(256)
b = rand(256)
pixel = (pixel << 8) | r
pixel = (pixel << 8) | g
pixel = (pixel << 8) | b
@@pixels[x][y] = Pixel.new(pixel)
end
end
end
def saveImage
puts "and the mult is..."
puts @@width * @@height
pixel_array = []
for x in @@pixels.reverse.each do
for y in x.reverse.each do
pix = y.getMagickPixel
pixel_array.append(pix.red)
pixel_array.append(pix.green)
pixel_array.append(pix.blue)
end
end
new_img = Magick::Image.new(@@width, @@height)
new_img.import_pixels(0, 0, @@width, @@height, "RGB", pixel_array)
new_img.write("arty_new.png")
end
def getPixels
return @@pixels
end
def getPixel(x, y)
return @@pixels[x][y]
end
def setPixelBits(x, y, bits)
@@pixels[x][y] = Pixel.new(bits)
end
def getSize
return {"width": @@width, "height": @@height}
end
def fuzzImage
for x in 0..@@width-1 do
for y in 0..@@height-1 do
@@pixels[x][y].randomize
end
end
end
def getSalt
salt = 0
for x in 0..@@width-1
for y in 0..@@height-1
pix = @@pixels[x][y].getPixelBits
salt = salt << 6 | ((pix >> 2) & 0b111111)
pix = pix >> 8
salt = salt << 6 | ((pix >> 2) & 0b111111)
pix = pix >> 8
salt = salt << 6 | ((pix >> 2) & 0b111111)
pix = pix >> 8
end
end
h = Digest::SHA512.hexdigest(salt.to_s(16))
return h
end
def getBits(o)
msg_bytes = o.unpack("c*")
msg_bits = 0
for b in msg_bytes
msg_bits = (msg_bits << 8) | b
end
return msg_bits
end
end

50
runner.rb Normal file
View file

@ -0,0 +1,50 @@
require "rmagick"
require "./image_utils.rb"
require "./encode_image.rb"
img = Magick::ImageList.new "./images/original/arty.png"
#srand(12345)
pass = "my_password"
message = "This is the message that I would like to save please " +
"and thank you also I love you? AND apostrophe's, and " +
"also some commas somewhere hiding around here, It's " +
"gonna be pushing it a bit here... 1234567 let's huck " +
"some more stuff in here to bump it to 255. Wow. We " +
"are going even further. further than anyone believed " +
"`~!@\#\{$%^&*()-_=+\][}{';:'}]} Wooow. 123456789!1234" +
"56789! so put 15 more??????400!"
#message = "tests"
puts message.length
puts message
puts
puts "Initializing EncodeImage..."
start = Time.new.to_f
em = EncodeImage.new(pass, message, img)
puts em.encode
puts "Took " + (Time.new.to_f - start).to_s + " seconds to encode... 🐱"
puts
start = Time.new.to_f
result = em.decode
puts result
puts "Took " + (Time.new.to_f - start).to_s + " seconds to decode... 🐱"
if message == result then
puts "WOW THEY MATCH! 🐱🐱🐱🐱🐱🐱🐱🐱"
end
exit
puts
puts "Done!"