Rocksolid Light

News from da outaworlds

mail  files  register  groups  login

Message-ID:  

Your goose is cooked. (Your current chick is burned up too!)


sci / sci.crypt / Re: xorpng

Subject: Re: xorpng
From: Chris M. Thomasson
Newsgroups: sci.crypt
Organization: A noiseless patient Spider
Date: Sun, 5 Jan 2025 23:14 UTC
References: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Path: news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail
From: chris.m.thomasson.1@gmail.com (Chris M. Thomasson)
Newsgroups: sci.crypt
Subject: Re: xorpng
Date: Sun, 5 Jan 2025 15:14:07 -0800
Organization: A noiseless patient Spider
Lines: 559
Message-ID: <vlf3nv$18h0m$1@dont-email.me>
References: <vl243l$3jkpe$1@paganini.bofh.team> <vlc891$k8s5$2@dont-email.me>
<vlc8om$k8s5$3@dont-email.me> <vlc9d8$irra$1@paganini.bofh.team>
<vlcahc$ks00$1@dont-email.me> <vlcbki$j00g$1@paganini.bofh.team>
<vlccrh$lb6a$1@dont-email.me> <vlchr0$j921$1@paganini.bofh.team>
<vlcivh$md8n$2@dont-email.me> <vlcjan$oal1$2@paganini.bofh.team>
<vld86b$tdna$1@dont-email.me> <vldj6q$pqvr$2@paganini.bofh.team>
<vldk3q$psnq$1@paganini.bofh.team> <vlecdg$13phn$2@dont-email.me>
<vlenpl$rjtu$1@paganini.bofh.team> <vles9r$16v92$2@dont-email.me>
<vlesgd$rrnh$1@paganini.bofh.team> <vlf27d$17vsk$5@dont-email.me>
<vlf2cd$17vsk$6@dont-email.me> <vlf3ae$s6de$1@paganini.bofh.team>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Mon, 06 Jan 2025 00:14:09 +0100 (CET)
Injection-Info: dont-email.me; posting-host="4f498e3dd7b2f539b15c36783567d08a";
logging-data="1328150"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18ZO5BMEhv9uSRgxCp2VQF89PWwOzLxMbU="
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:8lzGvSlS6mx57DgOReKbufuyghI=
In-Reply-To: <vlf3ae$s6de$1@paganini.bofh.team>
Content-Language: en-US
View all headers

On 1/5/2025 3:06 PM, Stefan Claas wrote:
> Chris M. Thomasson wrote:
>> On 1/5/2025 2:48 PM, Chris M. Thomasson wrote:
>>> On 1/5/2025 1:10 PM, Stefan Claas wrote:
>>>> Rich wrote:
>>>>> Stefan Claas <pollux@tilde.club> wrote:
>>>>>> Rich wrote:
>>>>>>> Stefan Claas <pollux@tilde.club> wrote:
>>>>>>>> Stefan Claas wrote:
>>>>>>>>> Rich wrote:
>>>>>>>>>> Stefan Claas <pollux@tilde.club> wrote:
>>>>>>>>>>> Rich wrote:
>>>>>>>>>>>
>>>>>>>>>>>> If instead you mean some kind of "special, PNG aware,
>>>>>>>>>>>> encryptor that only encrypted the bitmap data of a PNG",
>>>>>>>>>>>> but left the file as otherwise a proper PNG image
>>>>>>>>>>>> structure, then that is slightly tricky (and an algorithm
>>>>>>>>>>>> that is only useful for PNG's alone).
>>>>>>>>>>>
>>>>>>>>>>> Yes, this is what I mean.
>>>>>>>>>>
>>>>>>>>>> Which brings up the question of: why?
>>>>>>>>>>
>>>>>>>>>> Why go to the trouble to create an encryptor that is
>>>>>>>>>> specalized for just encrypting the internal bitmap data within
>>>>>>>>>> a PNG, leaving the rest as a PNG file, when a generic "byte
>>>>>>>>>> stream" encryptor will encrypt the entire PNG with no extra
>>>>>>>>>> effort?
>>>>>>>>>
>>>>>>>>> To make more content as allowed postable on social media, like
>>>>>>>>> X.
>>>>>>>>
>>>>>>>> I.e, first you put data with file2png in a .png and then encrypt
>>>>>>>> it to finally post it.  I can do this now with my xorpic program,
>>>>>>>> but I thought a solution with AES-GCM or XChaCha20+ploy1305 is
>>>>>>>> better.
>>>>>>>
>>>>>>> The "path" I outlined in my previous post, where you utilize the
>>>>>>> netpbm image format as your 'intermediary' would allow you to use
>>>>>>> any generic encryption routine you like, while also allowing you to
>>>>>>> convert the encrypted binary data to/from an image format of your
>>>>>>> choice (well, your choice within the set of other formats for which
>>>>>>> NetPBM has to/from converters available).
>>>>>>>
>>>>>>> This frees you from having to understand the internal structure of
>>>>>>> the various image formats.  You just work with the netpbm format (a
>>>>>>> raw binary bit/pixel block) for the encrypt/decrypt/padding
>>>>>>> operations, and delegate all the "image format" complexity to the
>>>>>>> netpbm library.
>>>>>>
>>>>>> Thank you!  My ppmenc tool works nicely, here are the test images:
>>>>>>
>>>>>> https://jmp.sh/HZM9ML9f
>>>>>>
>>>>>> The big problem I face when converting the encryypted image to .png
>>>>>> and back a diff shows a difference and the decryption fails.
>>>>>>
>>>>>> Maybe someone can figure out what to do, so that a converted .ppm can
>>>>>> be posted online , for viewers/readers and then can be converted back
>>>>>> to the original .ppm, which shows no difference.
>>>>>
>>>>> We can't read your mind over Usenet so can you show how you converted
>>>>> the encrypted image to a png and back.
>>>>>
>>>>
>>>> I used Gimp with compression set to 0 and the netbmp tools.
>>>>
>>>
>>> You should write your own program for it. The Gimp altered some bytes,
>>> right?
>>
>> Fwiw, the Cairo lib is fairly nice, well, to me at least... I use it a
>> lot for my 2d work. it allows you to gain access to the raw underlying
>> buffer. So, I can create PNG's with payloads that are intact.
>
> Ok, here is the deal ... I have file2png (Go and Python3) which converts
> any (encrypted) payload to valid noise .png images and back. I have xorpng
> in Go which can create .png keys of random noise (crypto/rand) and xor
> then .png images with them, to create encrypted noise images. I have ppmenc
> in Go which encrypts ppm (P6) images to noise images. What I can not work
> out is to convert a ppm to .png and back to the *original* .ppm (P6) file,
> because .png with programs used or the Go library alter the conversion,
> back to .ppm (P6). I tried many things and always failed.
>
> *Please* try to write a .ppm (P6) to .png converter (and back) in C(++)
> and see if you can get the *original* data back. The sci.crypt community
> and me of course would appreciate your help very much!
>

I can, but I am busy with other things. I wrote a PPM reader a long time
ago. decades. Just parse the PPM (P6) format. Here is a program I wrote
in C that stores PPM's as a series of slices for a 3d volumetric object.
The ct_canvas_save_ppm creates a PPM. The fun part is that the image
stack is a volumetric object that can even be made into a hologram.

_______________________

/*
A Simple 2d Plane For Owen, with proper aspect ratios!
Color adder, single channel
By: Chris M. Thomasson
*_____________________________________________________________*/

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <complex.h>
#include <tgmath.h>
#include <stdbool.h>

#define CT_WIDTH 1920
#define CT_HEIGHT 1080
#define CT_N 10000000

struct ct_rgb
{ unsigned char r;
unsigned char g;
unsigned char b;
};

struct ct_canvas
{ unsigned long width;
unsigned long height;
//unsigned char* buf;
struct ct_rgb* buf;
};

bool
ct_canvas_create(
struct ct_canvas* const self,
unsigned long width,
unsigned long height
){
size_t size = width * height * sizeof(*self->buf);

self->buf = calloc(1, size);

if (self->buf)
{
self->width = width;
self->height = height;

return true;
}

return false;
}

void
ct_canvas_destroy(
struct ct_canvas const* const self
){
free(self->buf);
}

bool
ct_canvas_save_ppm(
struct ct_canvas const* const self,
char const* fname
){
FILE* fout = fopen(fname, "wb");

if (fout)
{
// P6 by Bart over on:
//
https://groups.google.com/forum/#!original/comp.lang.c/4196m3Raggs/2moZ67o5EwAJ

char const ppm_head[] =
"P6\n"
"# Chris M. Thomasson Simple 2d Plane ver:0.0.0.0 (pre-alpha)";

fprintf(fout, "%s\n%lu %lu\n%u\n",
ppm_head,
self->width, self->height,
255U);

size_t size = self->width * self->height;

for (size_t i = 0; i < size; ++i)
{
//unsigned int c = self->buf[i];
struct ct_rgb* c = self->buf + i;

fprintf(fout, "%c%c%c", c->r, c->g, c->b);
//fprintf(fout, "%c%c%c", c, 0U, 0U);
}

if (! fclose(fout))
{
return true;
}
}

return false;
}

struct ct_axes
{ double xmin;
double xmax;
double ymin;
double ymax;
};

struct ct_axes
ct_axes_from_point(
double complex z,
double radius
){
struct ct_axes axes = {
creal(z) - radius, creal(z) + radius,
cimag(z) - radius, cimag(z) + radius
};

return axes;
}

struct ct_plane
{ struct ct_axes axes;
double xstep;
double ystep;
};

void
ct_plane_init(
struct ct_plane* const self,
struct ct_axes const* axes,
unsigned long width,
unsigned long height
){
self->axes = *axes;

double awidth = self->axes.xmax - self->axes.xmin;
double aheight = self->axes.ymax - self->axes.ymin;

assert(width > 0 && height > 0 && awidth > 0.0);

double daspect = fabs((double)height / width);
double waspect = fabs(aheight / awidth);

if (daspect > waspect)
{
double excess = aheight * (daspect / waspect - 1.0);
self->axes.ymax += excess / 2.0;
self->axes.ymin -= excess / 2.0;
}

else if (daspect < waspect)
{
double excess = awidth * (waspect / daspect - 1.0);
self->axes.xmax += excess / 2.0;
self->axes.xmin -= excess / 2.0;
}

self->xstep = (self->axes.xmax - self->axes.xmin) / width;
self->ystep = (self->axes.ymax - self->axes.ymin) / height;
}

struct ct_plot
{ struct ct_plane plane;
struct ct_canvas* canvas;
};

void
ct_plot_init(
struct ct_plot* const self,
struct ct_axes const* axes,
struct ct_canvas* canvas
){
ct_plane_init(&self->plane, axes, canvas->width - 1, canvas->height
- 1);
self->canvas = canvas;
}

bool
ct_plot_add(
struct ct_plot* const self,
double complex z,
struct ct_rgb const* color
){
long x = (creal(z) - self->plane.axes.xmin) / self->plane.xstep;
long y = (self->plane.axes.ymax - cimag(z)) / self->plane.ystep;

if (x > -1 && x < (long)self->canvas->width &&
y > -1 && y < (long)self->canvas->height)
{
// Now, we can convert to index.
size_t i = x + y * self->canvas->width;

assert(i < self->canvas->height * self->canvas->width);

struct ct_rgb exist = self->canvas->buf[i];

exist.r += 1;

self->canvas->buf[i] = exist;
return true;
}

return true;
}

bool
ct_plot_pixel(
struct ct_plot* const self,
long x,
long y,
struct ct_rgb const* color
){
if (x > -1 && x < (long)self->canvas->width &&
y > -1 && y < (long)self->canvas->height)
{
// Now, we can convert to index.
size_t i = x + y * self->canvas->width;

assert(i < self->canvas->height * self->canvas->width);

self->canvas->buf[i] = *color;
return true;
}

return false;
}

double complex
ct_project_to_xy(
struct ct_plot* const self,
long x,
long y
){
double complex p =
(self->plane.axes.xmin + x * self->plane.xstep) +
(self->plane.axes.ymax - y * self->plane.ystep) * I;

return p;
}

bool
ct_plot_point(
struct ct_plot* const self,
double complex z,
struct ct_rgb const* color
){
long x = (creal(z) - self->plane.axes.xmin) / self->plane.xstep;
long y = (self->plane.axes.ymax - cimag(z)) / self->plane.ystep;

if (x > -1 && x < (long)self->canvas->width &&
y > -1 && y < (long)self->canvas->height)
{
// Now, we can convert to index.
size_t i = x + y * self->canvas->width;

assert(i < self->canvas->height * self->canvas->width);

self->canvas->buf[i] = *color;
return true;
}

return false;
}

// slow, so what for now... ;^)
void ct_circle(
struct ct_plot* const plot,
double complex c,
double radius,
unsigned int n
){
double abase = 6.2831853071 / n;

for (unsigned int i = 0; i < n; ++i)
{
double angle = abase * i;

double complex z =
(creal(c) + cos(angle) * radius) +
(cimag(c) + sin(angle) * radius) * I;

struct ct_rgb rgb = { 255, 255, 255 };

ct_plot_point(plot, z, &rgb);
}
}

// Simple 3-ary vector impl, just what I need.
struct ct_vec3
{ double x;
double y;
double z;
};

double ct_vev3_length(
struct ct_vec3 const p
){
double sum = p.x * p.x + p.y * p.y + p.z * p.z;
return sqrt(sum);
}

struct ct_vec3
ct_vec3_add(
struct ct_vec3 const p,
struct ct_vec3 const addend
){
struct ct_vec3 sum = {
p.x + addend.x,
p.y + addend.y,
p.z + addend.z
};

return sum;
}

// The Mandelbulb, slice hardcoded
// Animation comes next Owen.
void
ct_iterate_mbulb_pixel(
struct ct_plot* const plot,
struct ct_vec3 const z0,
struct ct_vec3 const c0,
long x,
long y,
unsigned int n
){
struct ct_vec3 zs = z0;
struct ct_vec3 cs = c0;

double power = 3.0;

for (unsigned long i = 0; i < n; ++i)
{
double r = ct_vev3_length(zs);
double rpower = pow(r, power);

double angle0 = atan2(zs.z, sqrt(zs.x * zs.x + zs.y * zs.y));
double angle1 = atan2(zs.y, zs.x);

struct ct_vec3 znew;
znew.x = rpower * cos(power * angle1) * cos(power * angle0);
znew.y = rpower * sin(power * angle1) * cos(power * angle0);
znew.z = rpower * sin(power * angle0);

zs = ct_vec3_add(znew, cs);

if (r > 2.0)
{
return;
}
}

struct ct_rgb rgb = { 0, 255, 0 };
ct_plot_pixel(plot, x, y, &rgb);
}

// Gain the field...
void
ct_iterate_mbulb_plane(
struct ct_plot* const plot,
unsigned int n
){
for (long y = 0; y < plot->canvas->height; ++y)
{
for (long x = 0; x < plot->canvas->width; ++x)
{
double complex cz = ct_project_to_xy(plot, x, y);

// Well, our per slice coords...
struct ct_vec3 z;

z.x = creal(cz);
z.y = cimag(cz);
z.z = 0.1;

// Iterate the slice
ct_iterate_mbulb_pixel(plot, z, z, x, y, n);
}
}
}

void ct_test_plane(
struct ct_plot* const plot
){
ct_iterate_mbulb_plane(plot, 64);

ct_circle(plot, 0+0*I, 1.0, 2048);
}

int main(void)
{ struct ct_canvas canvas;

if (ct_canvas_create(&canvas, CT_WIDTH, CT_HEIGHT))
{
double complex plane_origin = 0+0*I;
double plane_radius = 2.0;

struct ct_axes axes = ct_axes_from_point(plane_origin,
plane_radius);

struct ct_plot plot;
ct_plot_init(&plot, &axes, &canvas);

ct_test_plane(&plot);

// Our unit circle
ct_circle(&plot, 0+0*I, 1.0, 2048);
ct_circle(&plot, 2+0*I, 2.0, 2048);
ct_circle(&plot, -2+0*I, 2.0, 2048);
ct_circle(&plot, 0+2*I, 2.0, 2048);
ct_circle(&plot, 0-2*I, 2.0, 2048);

ct_canvas_save_ppm(&canvas, "ct_plane.ppm");

ct_canvas_destroy(&canvas);

return EXIT_SUCCESS;
}

return EXIT_FAILURE;
}

_______________________

SubjectRepliesAuthor
o Ternary Encoding :-)

By: Stefan Claas on Wed, 1 Jan 2025

98Stefan Claas

rocksolid light 0.9.8
clearnet tor