Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Funny Fractal Encryption online experiment...

189 views
Skip to first unread message

Chris M. Thomasson

unread,
Oct 31, 2015, 9:54:53 PM10/31/15
to
FWIW, I have made a small change in the online version of my cipher:

http://funwithfractals.atspace.cc/ffe

I made it far easier for a user to copy the ciphertext. Before, they would
have to
copy the content of 4 text boxes comprising the public key, along with the
ciphertext.

This was a total bitch!

So, I simply added the public key to the ciphertext and created a little
parser that
automatically separates it from the ciphertext for decrypting.

Now a user can simply copy and paste ciphertext, and the public
automatically
comes along for the ride!

;^)

For instance, here is some ciphertext encrypted with the default private
key. To
decrypt it, simply copy-and-paste the following text into the “Cipher Text”
text box,
and click the decrypt button to see the message:
_______________________________________________
-0.32833967893446225 0.06772234646207564
-0.06252863483583193 0.47056145733894683

F7 A0 16 B8 A3 0E AF ED 54 80 3D E7 9B 76 C8 0C 25 45
7E 31 6A 4B 44 4F 90 42 93 8C 8C 53 10 37 0B DF E7 E1 67
CF BD 33 D0 32 F5 0C 98 3C D4 6D 28 25 D0 C4 A9 58 B0
1B D1 98 EA 93 35 BC 08 79 5D 30 9A 83 3D F3 CE C0 0A
20 F0 38 E2 03 B6 72 63 03 AA 14 B3 F5 32 3F A6 3B 4A 30
CA A4 49 68 52 E2 F3 DA 4F 53 F7 65 30 D1 8E F4 7F 39 EB
C6 25 21 FE
_______________________________________________

You might have to hit reload, or do something to make sure you have the
updated site.
If you do not see four floating point numbers in the ciphertext after the
page loads,
well, you are using the old version...

Can you decrypt it?

Also, the hexbytes in the ciphertext are for visualization/convenience
purposes only for
this cipher is 8-bit clean!

:^)

Thank you all.

Sparky

unread,
Nov 1, 2015, 5:22:10 AM11/1/15
to
-0.19427015956283789 0.09932322560161555
-0.15219402946403482 0.5441902672660524

FF 30 EF EC 21 89 E9 DC F1 17 74 E8 23 96 A4 DC 08 45 A4

wizzofozz

unread,
Nov 1, 2015, 10:33:31 AM11/1/15
to
On 1-11-2015 2:54, Chris M. Thomasson wrote:
> FWIW, I have made a small change in the online version of my cipher:
>
> http://funwithfractals.atspace.cc/ffe
>
> I made it far easier for a user to copy the ciphertext. Before, they
> would have to
> copy the content of 4 text boxes comprising the public key, along with
> the ciphertext.

Since I have nothing else I'll keep on nagging about that public/private
key terminology of yours. ;-)
If you fix that, potential reviewers may find it easier to follow along.

> _______________________________________________
> -0.32833967893446225 0.06772234646207564
> -0.06252863483583193 0.47056145733894683
>
> F7 A0 16 B8 A3 0E AF ED 54 80 3D E7 9B 76 C8 0C 25 45
> 7E 31 6A 4B 44 4F 90 42 93 8C 8C 53 10 37 0B DF E7 E1 67
> CF BD 33 D0 32 F5 0C 98 3C D4 6D 28 25 D0 C4 A9 58 B0
> 1B D1 98 EA 93 35 BC 08 79 5D 30 9A 83 3D F3 CE C0 0A
> 20 F0 38 E2 03 B6 72 63 03 AA 14 B3 F5 32 3F A6 3B 4A 30
> CA A4 49 68 52 E2 F3 DA 4F 53 F7 65 30 D1 8E F4 7F 39 EB
> C6 25 21 FE
> _______________________________________________
>
>
> Can you decrypt it?
>

Yes, that worked. But you can also abuse the 'public keys' quite a bit
and still get at a decent plaintext. Is that a problem?

I varied in the 'private key' section the params:
julia x and y change: decrypt returns garbage
x-min: init value -0.5, can change from -0.1,-1.0 without affecting
decryption
x-max: can be varied without affecting decryption
Same goes for y.

I also changed all x and y from the private key at once and still the
decryption seems OK. It seems that only julia-x and julia-y matter
during decryption.

So, what are valid values for julia-x and julia-y? How big is the keyspace?

Ozz









Chris M. Thomasson

unread,
Nov 1, 2015, 11:41:25 AM11/1/15
to
> > On 1-11-2015 2:54, Chris M. Thomasson wrote:
> > FWIW, I have made a small change in the online version of my cipher:
> >
> > http://funwithfractals.atspace.cc/ffe
> >
> > I made it far easier for a user to copy the ciphertext. Before, they
> > would have to
> > copy the content of 4 text boxes comprising the public key, along with
> > the ciphertext.

> Since I have nothing else I'll keep on nagging about that public/private
> key terminology of yours. ;-)
> If you fix that, potential reviewers may find it easier to follow along.

[...]

> > Can you decrypt it?

> Yes, that worked. But you can also abuse the 'public keys' quite a bit
> and still get at a decent plaintext. Is that a problem?

I don't think its a problem because these public keys are useless
without the correct private key.

The private key describes the fractal formula, and the public keys
are simply locations/axes into it.


> I varied in the 'private key' section the params:
> julia x and y change: decrypt returns garbage
> x-min: init value -0.5, can change from -0.1,-1.0 without affecting
> decryption
> x-max: can be varied without affecting decryption
> Same goes for y.

> I also changed all x and y from the private key at once and still the
> decryption seems OK. It seems that only julia-x and julia-y matter
> during decryption.

Yes. In this preliminary version, the julia-x/y are the most sensitive
aspect of decryption. I do not yet have the axes in the private key
properly hooked up to the decryption process. They are only used as a
base for generation of the axes in the public key.

> So, what are valid values for julia-x and julia-y? How big is the
keyspace?

This is a great question. For this version the valid values seem to be
in a range of:

-999999.9999999 through 999999.9999999

This is a rather limited keyspace, but once I get the private axes
hooked up then the key space will be larger. In my experiments with
the current version the range for each axis seems to be around:

-999.99999999999 through 999.99999999999

I need to put an iteration count and some ability for altering the
coloring in the private key. Also, I am going to allow for multiple
Julia points to be embedded into a single fractal, right now I am only
using a single point. Once you can use three or four Julia points, well,
the key space will be greatly expanded.

The next version will allow for any change to any part of the private
key to effect decryption. Right now, as you figured out, it is only
using the julia-x/y!

Eve can brute force all of the possible values of the single julia point,
and is eventually going to find the right values!

;^o


The next version will be posted in a day or two.


With your excellent observations Wizz, this thing is just going to get
better and better!

:^)


Thank you.

Chris M. Thomasson

unread,
Nov 4, 2015, 3:57:54 AM11/4/15
to
The all wise Wizz kindly point out a major limitation in the old site...

They key space was limited to a single Julia point, and changing the
private key axes would not destroy a decrypt attempt. Here is an updated
version of the pre-alpha version of the online tool I am currently working
on:

http://funwithfractals.atspace.cc/ffe

(make sure to reload the site to get the fresh one: You should see a heck
of a lot more settings! ;))


Now, I ask you, beg of you, to try to create some plaintext, encrypt it and
softly change the settings in the private key, and finally hit the decrypt
button. Do you get the plaintext, or garbage? How sensitive can you get
before
a decrypt actually gains “some” of the plaintext? Keep in mind that damn
garbage is the goal here wrt defending against hacks for Eve is so darn
smart
_and_ elegant... ;^)


I need some major help here with regard to “users”, or anybody who wants to
tear the shi% out of this monstrosity I dared to put online. ;)


Any help, comments, criticisms are greatly appreciated. Actually, the more
bad
things you can find, the better: damn it!


I know the GUI is rather terrible, but try to focus on the cipher for now!
;^)


I need to get this done in conjunction with a paper I am writing. This will
be
done before the end of the year. I just have to dial out this online
version,
and use it as a reference within the paper...

;^o


Also, I make the rendering of the cipher image smaller, and better color.
So, it
should load much faster on a “small” device...

Richard Heathfield

unread,
Nov 4, 2015, 4:10:37 AM11/4/15
to
On 04/11/15 08:57, Chris M. Thomasson wrote:
> The all wise Wizz kindly point out a major limitation in the old site...
>
> They key space was limited to a single Julia point, and changing the
> private key axes would not destroy a decrypt attempt. Here is an updated
> version of the pre-alpha version of the online tool I am currently
> working on:

Chris, some weeks (or possibly even months) ago, I suggested that you
prepare a thorough description and specification of your algorithm, in
sufficient detail so that people could implement it themselves at home
in the language of their choice, as a *prerequisite* of discussion of
that algorithm. That is, until the algorithm is nailed down, there isn't
much point trying to discuss it, let alone cryptanalyse it.

You seem to think that this documentation can wait until the discussion
of the algorithm is complete, whereas in fact the discussion can't
really get under way until everybody knows what the algorithm is. The
discussions you've had so far have been with people who are prepared to
guess in the absence of a spec, which is fine, but think of all the
fruitful discussions you might have had but haven't had with people who
aren't yet ready to get involved because they haven't yet seen the spec.

No skin off my nose, of course - you do what you like - but I thought it
would be worth reminding you of why some people are *not* chipping in to
this thread.

<snip>

--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

Chris M. Thomasson

unread,
Nov 7, 2015, 4:55:30 PM11/7/15
to
> "Richard Heathfield" wrote in message news:n1chu5$unm$1...@dont-email.me...

[...]

One question Richard, have you ever programmed a fractal such that you can
visualize
the resulting renderings? If not, read some of these links:

https://en.wikipedia.org/wiki/Mandelbrot_set

http://rosettacode.org/wiki/Mandelbrot_set

Once you get that done, then:



A very simple explanation using the escape time attribute only for my
cipher:
____________________________________________________
Take a plaintext P.

Encrypt:
-------------------------
Turn P into a 2d grid G.

Create axes A to convert G into the complex plane C.

For each cell/square in G, run a fractal iteration F on the corresponding C.

Use the escape time integer result from F to encrypt the corresponding byte
in P.
There is a unique F for every byte in P.

The resulting ciphertext is X.


Decrypt:
-------------------------
Turn X into a 2d grid G.

Use axes A to convert X into the complex plane C.

For each cell/square in G, run a fractal iteration F on the corresponding C.

Use the escape time result for F to decrypt the corresponding byte in X.
There is a unique F for every byte in X.

The resulting plaintext is P.
____________________________________________________

The formula used to make F is the private key.

The axes chosen to create C is the public key.


The base algorithm is actually not all that hard to code in any language
under the sun.

Can you tell me the problems you have with this simple algorithm outline?

Ben Bacarisse

unread,
Nov 7, 2015, 7:24:33 PM11/7/15
to
"Chris M. Thomasson" <nos...@nospam.nospam> writes:
<snip>
> A very simple explanation using the escape time attribute only for my
> cipher:

Ah! Just what I've been waiting for.

> Take a plaintext P.
>
> Encrypt:
> -------------------------
> Turn P into a 2d grid G.

How? Let me offer a way you can help people like me pin down what you
mean. P is a sequence of integers in 0-255 (the byte values) called
p_1, p_2, ... p_l (l is the message length). We define a mapping from N
(the counting numbers) to ZxZ (pairs of integers). You need to specify
the mapping from N to ZxZ. You might pick a single row so i -> (2, i),
or you might pick a diagonal so i -> (i, i). Maybe you intend a spiral
or some other way to do it.

Since the value of p_i is only used later, I'd leave this description
until later -- just before, or as part of, "Use the escape time integer
result...".

> Create axes A to convert G into the complex plane C.

Presumably you mean a linear map from grid point (p, q) to (ap, bq) for
real or rational numbers a, b? Do you allow more general mappings?
Anyway, you need to specify the form of the mapping.

> For each cell/square in G, run a fractal iteration F on the
> corresponding C.

This sounds clear but, but it needs to be explained a bit more because
of the last point below. The normal iteration is to calculate the
sequence F(c), F(F(c)), and so on for a single F used for all points c.

> Use the escape time integer result from F to encrypt the corresponding
> byte in P.

How? I can think of lots of ways, by you need to say what you mean.

> There is a unique F for every byte in P.

This is the first time I'm actually confused rather than simply wanting
more detail. The normal fractal image calculation uses a single F for
all the points so you need to explain this. You must state what F is
and how it depends on the byte (does it, for example depend on the byte
index or the byte value?).

The modern way to do this is to make the byte (or the index, or both)
arguments to F. So if you mean that the function to iterate depends on
the byte value, v, you'd re-write the earlier point as

With v the value of the byte that corresponds to each complex point c,
iterate F(v, c), F(v, F(v, c)), ... to calculate an "escape" integer,
e.

(Trival point: do you really mean unique? You might just mean that F
depends on the byte in P. If you rely on the fact that the F are really
unique, you need to say a lot more.)

> The resulting ciphertext is X.
>
>
> Decrypt:
> -------------------------
> Turn X into a 2d grid G.
>
> Use axes A to convert X into the complex plane C.
>
> For each cell/square in G, run a fractal iteration F on the
> corresponding C.

If the F used before depends on the byte, how can we run the same
calculation here?

> Use the escape time result for F to decrypt the corresponding byte in X.
> There is a unique F for every byte in X.
>
> The resulting plaintext is P.
> ____________________________________________________
>
> The formula used to make F is the private key.

That's a bad name. Please don't keep using it! It has a technical
meaning in cryptography that, as far as I can see does not apply here.
The formula appears to be a shared key: F is needed to encrypt and
decrypt.

> The axes chosen to create C is the public key.

Again, not a good name. It's just part of the method this is known to
everyone -- just like the mapping from byte indexes to grid points, or
the computaito used to combine the "escape" integer and the plaintext
byte into the encrupted byte. None of these appear to be public keys in
the sense meant in sci.crypt.

> The base algorithm is actually not all that hard to code in any
> language under the sun.
>
> Can you tell me the problems you have with this simple algorithm
> outline?

You just need a little more detail.

--
Ben.

Richard Heathfield

unread,
Nov 8, 2015, 9:01:27 AM11/8/15
to
On 07/11/15 21:55, Chris M. Thomasson wrote:
>> "Richard Heathfield" wrote in message news:n1chu5$unm$1...@dont-email.me...
>
> [...]
>
> One question Richard, have you ever programmed a fractal such that you
> can visualize
> the resulting renderings?

Yes, I am familiar with generating fractal images.

> A very simple explanation using the escape time attribute only for my
> cipher:
> ____________________________________________________
> Take a plaintext P.
>
> Encrypt:
> ------------------------- Turn P into a 2d grid G.

Plaintext:

The quick brown fox jumps over the lazy dog.

G1:

The quick brown fox jumps over the lazy dog.

G2:

The quick brown fox ju
mps over the lazy dog.

G3:

The quick brown
fox jumps over
the lazy dog.X

G4:

The quick b
rown fox ju
mps over th
e lazy dog.

G5:

The quick
brown fo
x jumps o
ver the l
azy dog.X

G6:

The quic
k brown
fox jump
s over t
he lazy
dog.XXXX

G7:

The qui
ck brow
n fox j
umps ov
er the
lazy do
g.XXXXX

etc etc.

I see no way of telling which you mean. Clearly we have different ideas
about what constitutes a precise description of the process.

Chris M. Thomasson

unread,
Nov 8, 2015, 2:25:50 PM11/8/15
to
> "Richard Heathfield" wrote in message news:n1nkfb$ck6$1...@dont-email.me...

>>On 07/11/15 21:55, Chris M. Thomasson wrote:
>> One question Richard, have you ever programmed a fractal such that you
>> can visualize
>> the resulting renderings?

> Yes, I am familiar with generating fractal images.

>> A very simple explanation using the escape time attribute only for my
>> cipher:
>> ____________________________________________________
>> Take a plaintext P.
>>
>> Encrypt:
>> ------------------------- Turn P into a 2d grid G.

> Plaintext:

> The quick brown fox jumps over the lazy dog.
[...]
> I see no way of telling which you mean. Clearly we have different ideas
> about what constitutes a precise description of the process.

Any of those would work. The way I am doing it now is making a square grid
by taking
the square root of the length of P and adding one. Then turn the result into
an unsigned
integer and use that as the width and height of G.




Richard Heathfield

unread,
Nov 8, 2015, 2:58:54 PM11/8/15
to
On 08/11/15 19:25, Chris M. Thomasson wrote:
>> "Richard Heathfield" wrote in message news:n1nkfb$ck6$1...@dont-email.me...
>
>>> On 07/11/15 21:55, Chris M. Thomasson wrote:
>>> One question Richard, have you ever programmed a fractal such that you
>>> can visualize
>>> the resulting renderings?
>
>> Yes, I am familiar with generating fractal images.
>
>>> A very simple explanation using the escape time attribute only for my
>>> cipher:
>>> ____________________________________________________
>>> Take a plaintext P.
>>>
>>> Encrypt:
>>> ------------------------- Turn P into a 2d grid G.
>
>> Plaintext:
>
>> The quick brown fox jumps over the lazy dog.
> [...]
>> I see no way of telling which you mean. Clearly we have different
>> ideas about what constitutes a precise description of the process.
>
> Any of those would work.

Then the specification should say that. People shouldn't have to guess.

Chris M. Thomasson

unread,
Nov 8, 2015, 3:14:25 PM11/8/15
to
> "Ben Bacarisse" wrote in message news:8737wht...@bsb.me.uk...

> > "Chris M. Thomasson" <nos...@nospam.nospam> writes:
<snip>
> > A very simple explanation using the escape time attribute only for my
> > cipher:

> Ah! Just what I've been waiting for.

> > Take a plaintext P.
> >
> > Encrypt:
> > -------------------------
> > Turn P into a 2d grid G.

> How? Let me offer a way you can help people like me pin down what you
> mean. P is a sequence of integers in 0-255 (the byte values) called
> p_1, p_2, ... p_l (l is the message length). We define a mapping from N
> (the counting numbers) to ZxZ (pairs of integers). You need to specify
> the mapping from N to ZxZ. You might pick a single row so i -> (2, i),
> or you might pick a diagonal so i -> (i, i). Maybe you intend a spiral
> or some other way to do it.

The way I am doing it now is making a square grid by taking
the square root of the length of P and adding one. Then turn the result into
an unsigned integer and use that as the width and height of G.

Here is a little program that shows this:

http://codepad.org/QkGmanQ6
____________________________________________
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

struct grid
{
unsigned int width;
unsigned int height;
};

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

struct point
{
double x;
double y;
};

void encrypt(
struct grid* G, // The grid
struct axes* A, // The axes
const char* P, // The plaintext
char* X, // The ciphertext
size_t L // The size of P and X
){
unsigned int x, y;
double xstep = (A->xmax - A->xmin) / (G->width - 1);
double ystep = (A->ymax - A->ymin) / (G->height - 1);

for (y = 0; y < G->height; ++y)
{
for (x = 0; x < G->width; ++x)
{
size_t i = y * G->height + x;
if (i >= L) return;

struct point c = {
A->xmin + x * xstep,
A->ymax - y * ystep
};

printf("encrypt %c using the point (%f, %f)\r\n", P[i], c.x,
c.y);
}
}
}

int main()
{
// The plaintext P
const char P[] = "The quick brown fox jumps over the lazy dog.";
size_t L = sizeof(P) - 1;

// Space for the ciphertext X
char X[sizeof(P)] = { '\0' };

// The grid G
unsigned int dim = (unsigned int)(sqrt(L) + 1);
struct grid G = { dim, dim };

// The axes A
struct axes A = { -2.0, 2.0, -2.0, 2.0 };

encrypt(&G, &A, P, X, L);

return 0;
}
____________________________________________


I am sorry that I don't have enough time to give you a detailed response.

Can you help me better explain the encrypt() function in the code above?

It converts every point in G to the corresponding point in the axes A.

That is a very simple explanation, but its just not enough.

Chris M. Thomasson

unread,
Nov 8, 2015, 3:20:44 PM11/8/15
to
>>>"Richard Heathfield" wrote in message news:n1o9dk$1pr$1...@dont-email.me...

>>On 08/11/15 19:25, Chris M. Thomasson wrote:
[...]
>>> The quick brown fox jumps over the lazy dog.
>> [...]
>>> I see no way of telling which you mean. Clearly we have different
>>> ideas about what constitutes a precise description of the process.
>>
>> Any of those would work.

> Then the specification should say that. People shouldn't have to guess.

Sorry about that. Can you help me explain the encrypt function in the simple
code below:
It basically converts every point in G to the corresponding point in the
axes A.

That is a very simple explanation, but its just not enough.

Can you help me out a bit here?

Thanks.

Richard Heathfield

unread,
Nov 8, 2015, 3:57:03 PM11/8/15
to
On 08/11/15 20:20, Chris M. Thomasson wrote:
>>>> "Richard Heathfield" wrote in message
>>>> news:n1o9dk$1pr$1...@dont-email.me...
>
>>> On 08/11/15 19:25, Chris M. Thomasson wrote:
> [...]
>>>> The quick brown fox jumps over the lazy dog.
>>> [...]
>>>> I see no way of telling which you mean. Clearly we have different
>>>> ideas about what constitutes a precise description of the process.
>>>
>>> Any of those would work.
>
>> Then the specification should say that. People shouldn't have to guess.
>
> Sorry about that. Can you help me explain the encrypt function in the
> simple code below:

There is a fundamental problem here. You are asking me to explain (or
help you to explain, which amounts to the same thing) exactly what you
meant. But if I knew exactly what you meant, I wouldn't be asking you
exactly what you meant.

Don't sweat it. I'm out. Other people here seem perfectly happy to
discuss your algorithm despite the absence of an unambiguous spec, so
it's probably not worth your time or mine for us to continue in this vein.

Jeffrey Goldberg

unread,
Nov 8, 2015, 6:44:01 PM11/8/15
to
[I haven't been paying attention to this conversation until now, so
forgive me if I ask something that has already been addressed.]
Aren't your results going to depend on some fairly fine details about
how floating point arithmetic is rounded and represented on whatever
machine this is running on? At the very least you should specify what
you expect "double" to mean in a way that will be consistent across
architectures and compilers.

Cheers,

-j


--
Jeffrey Goldberg http://goldmark.org/jeff/
I rarely read HTML or poorly quoting posts
Reply-To address is valid

Ben Bacarisse

unread,
Nov 8, 2015, 7:17:01 PM11/8/15
to
"Chris M. Thomasson" <nos...@nospam.nospam> writes:

>> "Ben Bacarisse" wrote in message news:8737wht...@bsb.me.uk...
>
>> > "Chris M. Thomasson" <nos...@nospam.nospam> writes:
> <snip>
>> > A very simple explanation using the escape time attribute only for my
>> > cipher:
>
>> Ah! Just what I've been waiting for.
>
>> > Take a plaintext P.
>> >
>> > Encrypt:
>> > -------------------------
>> > Turn P into a 2d grid G.
>
>> How? Let me offer a way you can help people like me pin down what you
>> mean. P is a sequence of integers in 0-255 (the byte values) called
>> p_1, p_2, ... p_l (l is the message length). We define a mapping from N
>> (the counting numbers) to ZxZ (pairs of integers). You need to specify
>> the mapping from N to ZxZ. You might pick a single row so i -> (2, i),
>> or you might pick a diagonal so i -> (i, i). Maybe you intend a spiral
>> or some other way to do it.
>
> The way I am doing it now is making a square grid by taking
> the square root of the length of P and adding one. Then turn the result into
> an unsigned integer and use that as the width and height of G.
>
> Here is a little program that shows this:
<snip code>

OK, the explains the first step. Your choice is a little odd since the
grid is not the smallest possible one. From the message length l, you
choose an integer size

s = floor(sqrt(l)) + 1.

The smallest square grid you need has size ceil(sqrt(l)). That's the
size I'd use just for neatness, but you can use any square or non-square
array you like.

> I am sorry that I don't have enough time to give you a detailed
> response.

That's OK. You don't owe anyone an explanation. Take it a step at a
time when you have time.

> Can you help me better explain the encrypt() function in the code above?

Given how you calculate the grid points, it's better to number the
message characters from 0 to l-1. You map plaintext byte i to point

(i mod s, floor(i / s)).

More useful for the later parts will be in the inverse of this map.
Grid point (p, q) is used for plaintext byte number p + s*q.

> It converts every point in G to the corresponding point in the axes A.

The mapping from the grid to the axes is relatively simple. It's just a
linear map derived from specified bounds: grid point (p, q) is mapped to

(x_min + p * (x_max - x_min), y_min + q * (y_max - y_min))

Eventually, it will help to specify what limits there are to all of the
various parts. Your code gives just one example, so you'll need to say
what's possible in general, but that can wait until the basics are
covered.

--
Ben.

Ben Bacarisse

unread,
Nov 8, 2015, 7:44:36 PM11/8/15
to
Jeffrey Goldberg <nob...@goldmark.org> writes:
> On 15-11-08 2:14 PM, Chris M. Thomasson wrote:
<example code>

> Aren't your results going to depend on some fairly fine details about
> how floating point arithmetic is rounded and represented on whatever
> machine this is running on?

In principle, yes, but it's possible (I don't yet have all the detail)
that the algorithm might be "statistically safe". I think the code
eventually uses a relatively course-grained property of a function from
C to C. If I'm right about that, the only results that will depend on
the details of the floating point calculation will be those very close
to the fractal boundary. These will be rare, and there will be no
knock-on effect -- only the byte at that point will be affected.

When more has been specified, it will be clearer how big a risk this is.

> At the very least you should specify what
> you expect "double" to mean in a way that will be consistent across
> architectures and compilers.

It's possible (again in principle) to do all the calculations with exact
rationals. That may result in slow code and very large numbers, but
it's theoretically possible -- none of the inputs are anything but
rational.

--
Ben.

Rich

unread,
Nov 8, 2015, 8:45:37 PM11/8/15
to
Chris M. Thomasson <nos...@nospam.nospam> wrote:
> >>>"Richard Heathfield" wrote in message news:n1o9dk$1pr$1...@dont-email.me...

> >>On 08/11/15 19:25, Chris M. Thomasson wrote:
> [...]
> >>> The quick brown fox jumps over the lazy dog.
> >> [...]
> >>> I see no way of telling which you mean. Clearly we have different
> >>> ideas about what constitutes a precise description of the process.
> >>
> >> Any of those would work.

> > Then the specification should say that. People shouldn't have to guess.

> Sorry about that. Can you help me explain the encrypt function in the simple
> code below:
> [code snipped
> Can you help me out a bit here?

Wrong question - very wrong question.

You wrote the code, so either:

1) you know what it does - therefore it is incumbent upon _you_ to put
in the effort to explain it to us

2) you have no idea what it does - therefore it is incumbent upon
_you_ to study your own code and what it does at sufficient length
and depth until you reach the understanding detailed in item #1
above - and then perform item #1.

wizzofozz

unread,
Nov 9, 2015, 7:13:39 AM11/9/15
to
Rich <ri...@example.invalid> wrote:
> Chris M. Thomasson <nos...@nospam.nospam> wrote:
>
>> Sorry about that. Can you help me explain the encrypt function in the simple
>> code below:
>> [code snipped
>> Can you help me out a bit here?
>
> Wrong question - very wrong question.
>
> You wrote the code, so either:
>
> 1) you know what it does - therefore it is incumbent upon _you_ to put
> in the effort to explain it to us
>

I think Chris knows what his code does, he's just strugling to explain it in a way which is accepted by readers of this group.
I think he's asking for help in how he would properly explain it.
He has put effort into this in several threads which obfuscates the fact that he's been trying to explain according to the 'rules' of this group.

Would a top down approach work better? So that he can start giving an overview of the algorithm and filling in the details later (but in the same post)?

Basically, what I believe he's doing;
1. create a fractal (indeed in the sense of a bunch of pixels with color values)
2. select a rectangle p by q pixels, from the bunch of pixels. Dimensions don't realy matter as long as p*q == l, where l is length of plaintext. Position does matter, e.g. a black region is probably not a good choice.
3. for each pixel, use the color value to encrypt one byte of the plaintext: E(P[i],F[i]), 0 <= i < l, where E is the encrypt function, P[i] the plaintext byte, F[i] the color value at (i/p,i%p) in the rectangle.

(in step 3 I may have made some mistakes in indexing)
(in step 2 pad as nessesary)

Questions:
What does E exactly do? (e.g. xor or something else)
Does the choice of the rectangle in the fractal matter (is the fractal random enough for the selected region?)
How is the fractal exactly generated and is it 'random' enough? The escapetime algorithm itself is too simple I believe, so he uses other properties of the complex numbers too.

HTH,
Ozz

Rich

unread,
Nov 9, 2015, 12:13:47 PM11/9/15
to
wizzofozz <wizz...@cuckoosnest.colo.transip.net> wrote:
> Rich <ri...@example.invalid> wrote:
> > Chris M. Thomasson <nos...@nospam.nospam> wrote:
> >
> >> Sorry about that. Can you help me explain the encrypt function in the simple
> >> code below:
> >> [code snipped
> >> Can you help me out a bit here?
> >
> > Wrong question - very wrong question.
> >
> > You wrote the code, so either:
> >
> > 1) you know what it does - therefore it is incumbent upon _you_ to put
> > in the effort to explain it to us
> >

> I think Chris knows what his code does, he's just strugling to
> explain it in a way which is accepted by readers of this group.

I assumed he knew what it did as well - I was trying to get him to
recognize the point.

> I think he's asking for help in how he would properly explain it.

> He has put effort into this in several threads which obfuscates the
> fact that he's been trying to explain according to the 'rules' of
> this group.

It has not helped that his explanation has been one or two sentences
here and there across multiple messages (and across great lengths of
time). No one else is going to ever be able to adequately piece back
together those disjoint fragments sufficiently to _ever_ be able to
understand.

> Would a top down approach work better? So that he can start giving an
> overview of the algorithm and filling in the details later (but in
> the same post)?

That would be significantly better than how he has gone about it so
far. And also, an _all in one_ approach, not a "scattered to the wind"
approach.

> Basically, what I believe he's doing;

> 1. create a fractal (indeed in the sense of a bunch of pixels with
> color values)

> 2. select a rectangle p by q pixels, from the bunch of pixels.
> Dimensions don't realy matter as long as p*q == l, where l is length
> of plaintext. Position does matter, e.g. a black region is probably
> not a good choice.

> 3. for each pixel, use the color value to encrypt one byte of the
> plaintext: E(P[i],F[i]), 0 <= i < l, where E is the encrypt function,
> P[i] the plaintext byte, F[i] the color value at (i/p,i%p) in the
> rectangle.

And, in what likely took you all of 5 minutes or less to type, you've
done _more_ to adequately explain Chris' algorithm than anything he's
done over the last few months.

> (in step 3 I may have made some mistakes in indexing)
> (in step 2 pad as nessesary)

> Questions:
> What does E exactly do? (e.g. xor or something else)

> Does the choice of the rectangle in the fractal matter (is the
> fractal random enough for the selected region?)

> How is the fractal exactly generated and is it 'random' enough? The
> escapetime algorithm itself is too simple I believe, so he uses other
> properties of the complex numbers too.

Valid questions, and the answers, when they arrive, should arrive at
least as edits to the complete description rather than as a one
sentence blurb on a subsequent posting. The extra blurb is fine to
describe what got edited, but each 'revision' should stand alone, not
require the location and reading of multiple disjoint (in time and
space) messages.



rsharris....@gmail.com

unread,
Nov 9, 2015, 4:38:31 PM11/9/15
to
On Monday, November 9, 2015 at 7:13:39 AM UTC-5, wizzofozz wrote:
> Basically, what I believe [Chris is] doing;
> [- snip -]
> 2. select a rectangle p by q pixels [from the image of a fractal]. Dimensions
> don't realy matter as long as p*q == l, where l is length of plaintext.

Surely that must be p*q >= l. Otherwise if l is a prime your choices for rectangles would be limited (as compared to a factorable l).

Bob H




wizzofozz

unread,
Nov 9, 2015, 5:07:47 PM11/9/15
to
Yes, you're right. In my defense, I did also write "(in step 2 pad as
necessary)". ;-)

Ozz

Jakob Bohm

unread,
Nov 9, 2015, 5:10:51 PM11/9/15
to
:-) They would indeed always be limited if equality was required,
just more so for prime lengths, less so for l having many factors.

Think of l=357, not prime, but no pretty choices anyway.


Enjoy

Jakob
--
Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com
Transformervej 29, 2860 Søborg, Denmark. Direct +45 31 13 16 10
This public discussion message is non-binding and may contain errors.
WiseMo - Remote Service Management for PCs, Phones and Embedded

Ben Bacarisse

unread,
Nov 9, 2015, 8:39:56 PM11/9/15
to
As a matter of fact this part has been specified. The choice is a
square grid large enough to have at least l points with the last
(highest index row) may not being fully used. Chris's code uses
floor(sqrt(l) + 1) as the size, but I think that's probably a
misunderstanding about floating point and rounding and so on. The
smallest square grid that's large enough, ceil(sqrt(l), is probably what
was intended.

--
Ben.

wizzofozz

unread,
Nov 10, 2015, 2:53:39 PM11/10/15
to
On 4-11-2015 9:57, Chris M. Thomasson wrote:
> I need some major help here with regard to “users”, or anybody who wants to
> tear the shi% out of this monstrosity I dared to put online. ;)
> I know the GUI is rather terrible, but try to focus on the cipher for
> now! ;^)

I'm willing to run some experiments with your cipher for fun and if I
have time, but it can't be done from the gui.
You can try it yourself by encrypting a 1 MB file, or use 1000 different
values for scale_y, or anything else that requires you to do more work
than filling in some values and hit the encrypt/decrypt button.

So, if you want people to start tearing the shi% out of anything, you'll
need to implement (again) something which can be run from the
commandline. I know you already published some code but that isn't as
recent as the functionality in the gui. Or you could focus on finishing
your paper which I'm just stating for the record.

Ozz


wizzofozz

unread,
Nov 10, 2015, 3:04:36 PM11/10/15
to
On 10-11-2015 2:39, Ben Bacarisse wrote:
>
> As a matter of fact this part has been specified. The choice is a
> square grid large enough to have at least l points with the last
> (highest index row) may not being fully used. Chris's code uses
> floor(sqrt(l) + 1) as the size, but I think that's probably a
> misunderstanding about floating point and rounding and so on. The
> smallest square grid that's large enough, ceil(sqrt(l), is probably what
> was intended.

Agreed. The floating point stuff is something which I need to get used
to anyway in this (crypto) context. But that's a different matter.

Ozz


wizzofozz

unread,
Nov 10, 2015, 3:22:56 PM11/10/15
to
On 9-11-2015 23:10, Jakob Bohm wrote:

> :-) They would indeed always be limited if equality was required,
> just more so for prime lengths, less so for l having many factors.
>
> Think of l=357, not prime, but no pretty choices anyway.

OK, you made me factor 357. :-) 21*17 seams reasonable to me.

Actually, I'm not convinced that a square is better than a rectangle or
better than a circle or better than a line. The area you choose just has
to contain a 'random enough' part of the fractal. But that's for Chris
to explain, I guess.

Ozz



Chris M. Thomasson

unread,
Nov 11, 2015, 6:07:33 PM11/11/15
to
> "Ben Bacarisse" wrote in message news:871tc0r...@bsb.me.uk...

>> "Chris M. Thomasson" <nos...@nospam.nospam> writes:
[...] [...]

Let me try again Ben. Starting small, with a hopefully better explanation of
how to map
a plaintext P to the grid G:

___________________________________________________
1: Create a plaintext P, with a length of L where L is the number of bytes
in P.



2: Take the floor of the square root of L, add one to it and call this D.
The reason for this will be explained.

// example...

D = floor(sqrt(L)) + 1;



3: Create a 2 dimensional grid G that has a width and height equal to D. G
is a DxD grid.

// example...

G { // the grid

width, // width of the grid equal to D
height // height of the grid equal to D
};



4: Create a mapping PG from every byte in P to the grid points in G.
Map each byte in P (P_0, P_1, …, P_n) where n is bound by L (n < L) to its
(x, y) counterpart in G.

// example...

for (n = 0; n < L; ++n)
{
(x, y) = (n - n / G.width * G.width, n / G.width);
}
___________________________________________________


Is this okay? If not, how can I improve on it?

Thanks.

Chris M. Thomasson

unread,
Nov 11, 2015, 6:28:33 PM11/11/15
to


"Chris M. Thomasson" wrote in message
news:n20hng$s6n$1...@speranza.aioe.org...
> Let me try again. Starting small, with a hopefully better explanation of
> how to map plaintext P to the grid G:

> ___________________________________________________
> [...]

> 3: Create a mapping PG from every byte in P to the grid points in G. Map
> each byte in P (P_0, P_1, …, P_n) where n is bound by L, to its (x, y)
> counterpart in G.

> // example...

> (x, y) = (n - n / G.width * G.width, n / G.width)

> [...]

Ummm. The mapping should be:

(x, y) = (n - floor(n / G.width) * G.width, floor(n / G.width))


I forgot that the length of the plaintext L, the number D and the
components of G are all unsigned integers. The division ops should all
given floored unsigned integer results.

Sorry about that!

Ben Bacarisse

unread,
Nov 11, 2015, 6:56:28 PM11/11/15
to
"Chris M. Thomasson" <nos...@nospam.nospam> writes:

>> "Ben Bacarisse" wrote in message news:871tc0r...@bsb.me.uk...
>
>>> "Chris M. Thomasson" <nos...@nospam.nospam> writes:
> [...] [...]
>
> Let me try again Ben. Starting small, with a hopefully better
> explanation of how to map
> a plaintext P to the grid G:

OK, but that bit, was, I thought cleared up. For me there were other
more important things that needed to be said.

> ___________________________________________________
> 1: Create a plaintext P, with a length of L where L is the number of
> bytes in P.
>
>
> 2: Take the floor of the square root of L, add one to it and call this D.
> The reason for this will be explained.
>
> // example...
>
> D = floor(sqrt(L)) + 1;

Yes, you posted code and that was clear form the code. I questioned why
you did this rather than ceil(sqrt(L)), but you can pick any D large
enough that you like.

> 3: Create a 2 dimensional grid G that has a width and height equal to
> D. G is a DxD grid.
>
> // example...
>
> G { // the grid
>
> width, // width of the grid equal to D
> height // height of the grid equal to D
> };

This is just noise. The grid is DxD.

> 4: Create a mapping PG from every byte in P to the grid points in G.
> Map each byte in P (P_0, P_1, …, P_n) where n is bound by L (n < L) to

"bounded by" is more normal but one would usually just show the
numbering and that would do:

"The L bytes of P (P_0, P_1, ... P_(L-1)) are mapped to grid points
with P_n at point (n mod D, n div D)."

> its (x, y) counterpart in G.
>
> // example...
>
> for (n = 0; n < L; ++n)
> {
> (x, y) = (n - n / G.width * G.width, n / G.width);

Correction elsewhere noted, but I'd write

(x, y) = (n mod D, n div D)

and explain what mod and div are. Or, if I were writing quasi C, I'd
write

(x, y) = (n % D, n / D);

> }

The complex C-style loop adds nothing when writing this sort of
specification. See above for one way to word it.

> ___________________________________________________
>
>
> Is this okay? If not, how can I improve on it?

It's fine for me, but then so was the code you posted! I obviously
(slightly) prefer the wording I've used, but your way is fine too. It
would not really do for a paper in a journal, but that's not what you
are writing here.

I'm more keen to understand the algorithm that to get the wording "just
right".

--
Ben.

Chris M. Thomasson

unread,
Nov 11, 2015, 10:10:01 PM11/11/15
to
> "Ben Bacarisse" wrote in message news:876118a...@bsb.me.uk...

> > "Chris M. Thomasson" <nos...@nospam.nospam> writes:

[...]

> > It's fine for me, but then so was the code you posted! I obviously
> > (slightly) prefer the wording I've used, but your way is fine too. It
> > would not really do for a paper in a journal, but that's not what you
> > are writing here.

> I'm more keen to understand the algorithm that to get the wording "just
> right".

I need to do this a step at a time and get something
sufficient/comprehensive enough.

I am trying to get the explanation good enough for Richard Heathfield, you
and
everybody else to implement.


Here is another try using some of your wording, but I kept the floor
functions.

I also introduce another mapping to get the actual complex numbers used for
the
fractal cipher:
________________________________________________________
1) Create a plaintext P, with a length of L where L is the number of bytes
in P.



2) Take the floor of the square root of L, add one to it and call this D.
The reason
for this will be explained.



3) The L bytes of P (P_0, P_1, ... P_(L-1)) are mapped to grid points with
P_n at point:

V_n = (n - floor(n / D) * D, floor(n / D))

where V is the set of points mapped from P to G.



4) Create a grid A consisting of bounded axes:

// example...
A {
xmin, xmax, // the bounds of the x-axis
ymin, ymax // the bounds of the y-axis
};

Where A has a width of (A.xmax – A.xmin), and a height of (A.ymax – A.ymin).



5: The L points in V (V_0, V_1, ...V_(L-1)) are mapped to grid points in A
with V_n
at complex number:

C_n = (A.xmin + V_n.x * (A.xmax - A.xmin) / (D – 1),
A.ymax - V_n.y * (A.ymax - A.ymin) / (D – 1))

Where C is the set of complex numbers mapped from V to A.
________________________________________________________


Can you write a program to gain the set of complex numbers C just from
following the steps above?

Thanks for your time Ben. I really do appreciate it.

The nice thing about this is that the next steps all involve the fractal and
the guts of the cipher.

:^D

Chris M. Thomasson

unread,
Nov 11, 2015, 10:59:43 PM11/11/15
to
> "wizzofozz" wrote in message news:n1thrn$dq3$1...@dont-email.me...
A command-line version that has all the functionality of the online gui
program is almost finished.

The paper is scraping along.

I have to stack 3 cords of wood tomorrow, so that’s going to be fun!

:^)

Ben Bacarisse

unread,
Nov 12, 2015, 6:32:30 AM11/12/15
to
"Chris M. Thomasson" <nos...@nospam.nospam> writes:
<snip>
> Can you write a program to gain the set of complex numbers C just from
> following the steps above?

Yes, but then I could before that explanation. Going over it again in
words I am almost certain to like less than my own just seems a waste of
time (for me).

> Thanks for your time Ben. I really do appreciate it.
>
> The nice thing about this is that the next steps all involve the
> fractal and the guts of the cipher.

I feel I should warn you that your approach might put people off.
There's a long tradition of Usenet cranks who use standard terms in
non-standard ways, and who dole out tiny bit of information and spend
ages going round and round about details. They fear being clear because
they know there is nothing interesting to be clear about. I am not
suggesting for one second that you are such a person, but there are
accidental similarities.

It takes time to write a good specification, but you can do it by
refinement and by answering questions as you go. The high-level
explanation of your method appears to be:

1. Assign to each byte p_i of the plaintext a complex number c_i.
2. Iteratively apply to c_i some function f.
3. Use the information from that iteration to transform p_i.

The details of 1 are now known and 2 is simple. How hard is 3 to
describe if only at the next level of detail?

--
Ben.

Chris M. Thomasson

unread,
Nov 12, 2015, 4:04:18 PM11/12/15
to
>"Ben Bacarisse" wrote in message news:87twora...@bsb.me.uk...

>>"Chris M. Thomasson" <nos...@nospam.nospam> writes:

[...]

Here is a link to some very crude, in progress, source code that shows the
encryption process. It just encrypts a plaintext of all "A"'s for it
is the base of the new command-line version of my cipher:

http://pastebin.com/X7vaeHkp

I remember that you were able to use the older command-line cipher program I
posted, you even found a bug in it. Thank you for that by the way...

Now, focus on the following structures in the code:
______________________________________________
struct grid
{
std::size_t m_width;
std::size_t m_height;
};


struct axes
{
double m_xmin;
double m_xmax;
double m_ymin;
double m_ymax;

double width() const
{
return m_xmax - m_xmin;
}

double height() const
{
return m_ymax - m_ymin;
}
};

struct iter_result
{
std::size_t m_iters; // Iteration at escape
double m_orbit_trap; // Trap of the lowest orbit radius
complex_t m_z; // The z complex number at the escape time at ` m_iters'
};

struct iter_settings
{
grid m_grid; // The grid G
axes m_axes; // The axes A
std::size_t m_iters; // Iteration max
complex_t m_jp[3]; // three Julia points
};
______________________________________________


These give all the information we need to encrypt P.

(struct grid) is the initial mapping from P to the 2d grid.

(struct axes) is the final mapping from (struct grid) to the final complex
numbers.


Okay, the results (iter_result) of the fractal iteration I apply to each
byte in P, is:

c = A complex number wrt mapping P_n to C_n:
_______________________________________________

// Iterate 3 points in triple mixed Julia mode...
static bool iterate_point(
complex_t const c, // complex number mapped to (P_n)
iter_settings const& isets, // the private fractal
iter_result& ires) // the result of this iteration of (c)
{
complex_t z = c;

complex_t scale(1.0, 0.0);

double orbit_trap = 99999999999999999.0;

std::size_t jstep = 0;

double escape =
std::abs(2.0 +
isets.m_jp[0].real() + isets.m_jp[0].imag() +
isets.m_jp[1].real() + isets.m_jp[1].imag() +
isets.m_jp[2].real() + isets.m_jp[2].imag()
);

for (std::size_t i = 1; i < isets.m_iters + 1; ++i)
{
z = z * z;

if (jstep == 0)
{
z = z + isets.m_jp[0];
}


else if (jstep == 1)
{
z = z + isets.m_jp[1];
}

else
{
z = z + isets.m_jp[2];
}

z = z * scale;

jstep = (jstep + 1) % 3;

double d = std::sqrt(z.real() * z.real() + z.imag() * z.imag());

if (d != 0)
{
orbit_trap = std::min(orbit_trap, d);
}

else
{
orbit_trap = std::min(orbit_trap, 0.1);
}

if (d > escape)
{
ires.m_iters = i;
ires.m_orbit_trap = orbit_trap;
ires.m_z = z;

return false;
}
}

ires.m_iters = isets.m_iters;
ires.m_orbit_trap = orbit_trap;
ires.m_z = z;

return true;
}

_______________________________________________




The result (iter_result) from the function above is applied to each complex
number.

Here the the callback function that is invoked for each complex number
mapped to each byte in P:
_______________________________________________
struct private_fractal : public fractal::iter_callback_base
{
bool callback(
std::size_t x,
std::size_t y,
fractal::complex_t const c,
fractal::iter_settings const& isets,
fractal::iter_result& ires)
{
double cipher_mutator_real = 0.0;
fractal::iterate_point(c, isets, ires);

if (isets.m_iters != ires.m_iters)
{
cipher_mutator_real = ires.m_iters * ires.m_orbit_trap *
(ires.m_z.real() + ires.m_z.imag());
cipher_mutator_real *= 5134.0413;
}

else
{
cipher_mutator_real = ires.m_iters * ires.m_orbit_trap *
(ires.m_z.real() + ires.m_z.imag());
cipher_mutator_real *= 178654.681;
}

std::size_t cipher_mutator =
((std::size_t)std::abs(fractal::round(cipher_mutator_real))) % FFE_BYTE_SZ;

// Encrypt the 9 A's in the plaintext. 65 = A in decimal wrt ASCII
std::size_t cipher_mutation = (65 + cipher_mutator) % FFE_BYTE_SZ;

std::cout << cipher_mutation << " ";

return true;
}
};


_______________________________________________

Where ( cipher_mutator) is the “salt”, and ( cipher_mutation) is the
encrypted byte of a bunch if (“A”)'s.


Is this okay Ben?

Can you help me make the encryption better wrt the ( cipher_mutator_real)
variable in the ( private_fractal::callback) function?


Thanks again.

:^)

Chris M. Thomasson

unread,
Nov 12, 2015, 4:11:05 PM11/12/15
to
> "Chris M. Thomasson" wrote in message
> news:n22usd$s8u$2...@speranza.aioe.org...
[...]

FWIW, you can compile the program with:

g++ -std=c++11 -o main *.cpp -lm

The code compiles with:

http://www.tutorialspoint.com/compile_cpp11_online.php

as well, with the command line above.


Just name the source code as "main.cpp"...

;^)


This code base is going to be a command line program that can
encrypt/decrypt
files with a more concise command line argument structure than the older one
you ran.

Can you help me explain the encrypt function wrt (fractal::iterate_point())
function.

That function is applied to each of the complex numbers that map to each
byte in P.

Thanks again Ben. I really appreciate your patience, and help.

:^)


BTW, I am using C++ now because it has a nice threading library, and the
encrypt/decrypt
process happens to be "embarrassingly parallel" in nature wrt escape time
fractals.

Ben Bacarisse

unread,
Nov 13, 2015, 12:35:26 PM11/13/15
to
"Chris M. Thomasson" <nos...@nospam.nospam> writes:

>>"Ben Bacarisse" wrote in message news:87twora...@bsb.me.uk...
>
>>>"Chris M. Thomasson" <nos...@nospam.nospam> writes:
>
> [...]
>
> Here is a link to some very crude, in progress, source code that shows the
> encryption process. It just encrypts a plaintext of all "A"'s for it
> is the base of the new command-line version of my cipher:
>
> http://pastebin.com/X7vaeHkp

The code is overly complex. It's clearly derived from something else
where there was a need for the organisation you've used. For example,
you have a grid structure, but in effect it's just one int. You pass a
big and complex structure to the iteration routine, but you only use two
parts of it.

Here, as an example, is how I'd write that function:

static bool iterate_point(
const complex_t c,
const std::size_t max_iterations,
const complex_t *const jpoint,
iter_result &ires)
{
double orbit_trap = std::numeric_limits<double>::max();

const double escape =
std::abs(2.0 +
jpoint[0].real() + jpoint[0].imag() +
jpoint[1].real() + jpoint[1].imag() +
jpoint[2].real() + jpoint[2].imag()
);

double d = 0;
std::size_t i = 0;
complex_t z = c;

while (d <= escape && i < max_iterations)
{
z = (z * z + jpoint[i % 3]);
d = std::abs(z);
orbit_trap = std::min(orbit_trap, d == 0 ? 0.1 : d);
i += 1;
}

ires.m_iters = i;
ires.m_orbit_trap = orbit_trap;
ires.m_z = z;

return d <= escape;
}

It makes it much clearer what's going on, but there are still some
rather odd "hacks". What's the 0.1 doing there when d == 0? (It just
looks like a random "smallish" number.) And what if d gets very close to
zero; is it still OK to use d? What's the point of the scale value of
(1,0)?

<snip>
> Here the the callback function that is invoked for each complex number
> mapped to each byte in P:

And this is very odd. There's no need to pass a "call-back" function --
the code the uses can just call it! It clarifies the computation that
modifies the bytes but again it has some arbitrary-looking data. Can you
explain the numbers? It also has some unused parameters. These obscure
the purpose.

> struct private_fractal : public fractal::iter_callback_base
> {
> bool callback(
> std::size_t x,
> std::size_t y,
> fractal::complex_t const c,
> fractal::iter_settings const& isets,
> fractal::iter_result& ires)
> {
> double cipher_mutator_real = 0.0;
> fractal::iterate_point(c, isets, ires);
>
> if (isets.m_iters != ires.m_iters)

This test could simply use the result of iterate_point. If you don't
use it, you might as well make it a void function.

> {
> cipher_mutator_real = ires.m_iters * ires.m_orbit_trap *
> (ires.m_z.real() + ires.m_z.imag());
> cipher_mutator_real *= 5134.0413;
> }
>
> else
> {
> cipher_mutator_real = ires.m_iters * ires.m_orbit_trap *
> (ires.m_z.real() + ires.m_z.imag());
> cipher_mutator_real *= 178654.681;
> }

You can simplify that code quite a lot!

> std::size_t cipher_mutator =
> ((std::size_t)std::abs(fractal::round(cipher_mutator_real))) % FFE_BYTE_SZ;
>
> // Encrypt the 9 A's in the plaintext. 65 = A in decimal wrt ASCII
> std::size_t cipher_mutation = (65 + cipher_mutator) %
> FFE_BYTE_SZ;

I get this is some sort of first-draft, but you need to get the
organisation right. This should simply be a function that is called
with the results of the iteration and a byte to mutate.

> std::cout << cipher_mutation << " ";
>
> return true;
> }
> };
<snip>
> Is this okay Ben?

Well it means I now know what the encryption algorithm is, but there are
few oddities that will make explaining it look more complex than it need
be.

What's the heart of the decryption? (There must be very little new code
that part.)

--
Ben.

Chris M. Thomasson

unread,
Nov 13, 2015, 3:41:07 PM11/13/15
to
> "Ben Bacarisse" wrote in message news:871tbtz...@bsb.me.uk...

> > "Chris M. Thomasson" <nos...@nospam.nospam> writes:
[...]

The reason for the callbacks is that I wanted to be able
to turn this into a general purpose graphical fractal
explorer _and_ cipher program, all in one package. So, a bitmap
generator can use its callback for that, and the cipher can
use another callback for encryption/decryption. Anyway, the
reason for the scale factor is that the scale can naturally
bring any fractal closer, and/or further away from the border.
Take the following Julia set into account:


Z^2+{-0.75;0.0}


Apply the following scale:

(Z^2+{-0.75;0.0})*{1.0;0.1}


This makes (Z^2+{-0.75;0.0}) get closer the imaginary axis,
and bam: The result is off axis and gains beauty wrt the
bitmap rendering.

FWIW, the formulas above can be run in Xaos:

http://matek.hu/xaos/doku.php

An older, but decent fractal explorer.




> Well it means I now know what the encryption algorithm is, but there are
> few oddities that will make explaining it look more complex than it need
> be.

> What's the heart of the decryption? (There must be very little new code
> that part.)

The code is very crude, but at least you understand the
encryption. Decryption is the same process, except the
final modular addition is reversed. Take a look at the
(ct_ffe_encrypt/decrypt) functions in the following code
that was the first version I ever posted about my cipher:

http://pastebin.com/Rjw3U7WK
_____________________________________________________
int
ct_ffe_encrypt(
struct ct_ffe* const self,
char const* omsg,
unsigned int omsg_size,
char* emsg,
unsigned int emsg_size
){
unsigned int i = 0;

if (emsg_size < omsg_size)
{
return 0;
}

for (i = 0; i < omsg_size; ++i)
{
unsigned int icount = self->icounts[i] % CT_FFE_ABET_MOD;
unsigned int cx = CT_FFE_ABET_LOOKUP(omsg[i]);
unsigned int ec = (cx + icount) % CT_FFE_ABET_MOD;

emsg[i] = CT_FFE_ABET[ec];
}

return 1;
}


int
ct_ffe_decrypt(
struct ct_ffe* const self,
char const* emsg,
unsigned int emsg_size,
char* dmsg,
unsigned int dmsg_size
){
unsigned int i = 0;

if (dmsg_size < emsg_size)
{
return 0;
}

for (i = 0; i < emsg_size; ++i)
{
unsigned int icount = self->icounts[i] % CT_FFE_ABET_MOD;
unsigned int cx = CT_FFE_ABET_LOOKUP(emsg[i]);

int ec = cx - icount;

if (ec < 0)
{
ec = cx + CT_FFE_ABET_MOD;
ec = abs(icount - ec);
}

dmsg[i] = CT_FFE_ABET[ec];
}

return 1;
}
_____________________________________________________


It's all modular arithmetic wrt mutating an actual byte
in the plaintext P_n with the result from running fractal
iteration F on a complex number C_n that are directly mapped
from P_n.

Ben Bacarisse

unread,
Nov 13, 2015, 4:06:54 PM11/13/15
to
"Chris M. Thomasson" <nos...@nospam.nospam> writes:

>> "Ben Bacarisse" wrote in message news:871tbtz...@bsb.me.uk...
>
>> > "Chris M. Thomasson" <nos...@nospam.nospam> writes:
> [...]
>
> The reason for the callbacks is that I wanted to be able to turn this
> into a general purpose graphical fractal explorer _and_ cipher
> program, all in one package.

That's an odd goal. I thought you were trying to write clear code
explain your encryption. If you are writing multi-purpose code then I
fear the two objectives will conflict.

> So, a bitmap generator can use its
> callback for that, and the cipher can use another callback for
> encryption/decryption. Anyway, the reason for the scale factor is that
> the scale can naturally bring any fractal closer, and/or further away
> from the border.

But now I don't know if that's part of the encryption algorithm (if so,
where does a non-trivial scale factor come from?) and if not it's just
muddying the waters.

<snip>
>> Well it means I now know what the encryption algorithm is, but there are
>> few oddities that will make explaining it look more complex than it need
>> be.
>
>> What's the heart of the decryption? (There must be very little new code
>> that part.)
>
> The code is very crude, but at least you understand the
> encryption. Decryption is the same process, except the final modular
> addition is reversed.

Ah, right. So it's a symmetric cipher; there's a shared key between
Alice and Bob, presumably some or all of the details of the iteration.
Is it the three points? Or the three points and the axes combined?

<snip>
--
Ben.

rsharris....@gmail.com

unread,
Nov 14, 2015, 9:53:04 AM11/14/15
to
On Friday, November 13, 2015 at 4:06:54 PM UTC-5, Ben Bacarisse wrote:
> "Chris M. Thomasson" <nos...@nospam.nospam> writes:
> > [...]
> > The reason for the callbacks is that I wanted to be able to turn this
> > into a general purpose graphical fractal explorer _and_ cipher
> > program, all in one package.
>
> That's an odd goal. I thought you were trying to write clear code explain your
> encryption. If you are writing multi-purpose code then I fear the two objectives
> will conflict.

I would guess he needs the graphical fractal explorer part so's he can find a 'random enough' part of the fractal. But I'd agree, it's an odd goal.

Chris earlier wrote:
> 2: Take the floor of the square root of L, add one to it and call this D.
> The reason for this will be explained.

This is a minor point, but I didn't see where the reason for this was explained. Why is floor(sqrt(L))+1 used when it would seem that ceil(sqrt(L)) is sufficient? Is there some part of the process that requires at least one more pixel in the fractal square than there are characters in the plain text?

And Chris also wrote:
> for (std::size_t i = 1; i < isets.m_iters + 1; ++i)
> {
> z = z * z;
> ...
> z = z + isets.m_jp[0];
> ...
> double d = std::sqrt(z.real() * z.real() + z.imag() * z.imag());
> ... etc.

Whenever I see floating point used I start worrying about getting the same results from different compilers. The problem will (probably) be that different compilers reorder the floating point operations and in some cases the results will differ in the least significant bits. Iterating those results tends to amplify those small differences. It will be difficult to guarantee that two different executables will produce the same fractal values to whatever level of precision your encryption step requires. Most pixels will probably be close enough but there is some probably that at least one could be different enough to misencrypt.

If you submit this as a manuscript, you're going to need to convince your audience, especially the reviewers, that you've considered the effects of FP rounding error, and that you've designed the process to be robust to differences in that error between executables no matter what the plaintext or fractal are.

Bob H

Chris M. Thomasson

unread,
Nov 14, 2015, 5:40:58 PM11/14/15
to
> rsharris wrote:

> > On Friday, November 13, 2015 at 4:06:54 PM UTC-5, Ben Bacarisse wrote:
> > > "Chris M. Thomasson" <nos...@nospam.nospam> writes:
> > > [...]
> > > The reason for the callbacks is that I wanted to be able to turn this
> > > into a general purpose graphical fractal explorer _and_ cipher
> > > program, all in one package.
> >
> > That's an odd goal. I thought you were trying to write clear code
> > explain your
> > encryption. If you are writing multi-purpose code then I fear the two
> > objectives
> > will conflict.

> I would guess he needs the graphical fractal explorer part so's he can
> find
> a 'random enough' part of the fractal. But I'd agree, it's an odd goal.

IMVHO, it is interesting to see the visual representation of the axes in
different settings. For instance, the online version of the cipher creates a
little thumbnail image that shows what the axes of the ciphertext look like.
The coloring for the thumbnail image is not the same as the cipher, because
it would/should resemble a bunch of static. Not very pretty. However, the
static, and the more appealing rendering are of the same axes, and therefore
deeply related to one another. I am thinking about creating two renderings
of
the cipher axes. A nice looking one, and the actual static used to render
the ciphertext. A simple visual representation showing the difference
between static and something more pleasing can be seen here:

https://plus.google.com/101799841244447089430/posts/hiLhZbushb3

In the case linked above the static is being confined within the Mset
(non-escaping), however the escaping values can also be turned into
“static”.

The heart of the cipher basically relies on the ability to turn a very
elegant
fractal rendering into a complete static mess that is terrible to the eye...
;^)


[...]

> Whenever I see floating point used I start worrying about getting
> the same results from different compilers. The problem will (probably)
> be that different compilers reorder the floating point operations and in
> some cases the results will differ in the least significant bits.
> Iterating
> those results tends to amplify those small differences. It will be
> difficult
> to guarantee that two different executables will produce the same fractal
> values to whatever level of precision your encryption step requires. Most
> pixels will probably be close enough but there is some probably that at
> least one could be different enough to misencrypt.

> If you submit this as a manuscript, you're going to need to convince your
> audience, especially the reviewers, that you've considered the effects of
> FP rounding error, and that you've designed the process to be robust to
> differences in that error between executables no matter what the plaintext
> or fractal are.

I am hoping that relying/requiring a standard floating point representation
would help. Something like JavaScript:

http://www.w3schools.com/js/js_numbers.asp

IEEE 754


WRT the dimensions D = floor(sqrt(L))+1, the mapping of P_n to the axes
A is:
__________________________________________
5: The L points in V (V_0, V_1, ...V_(L-1)) are mapped to grid points in A
with V_n at complex number:

C_n = (A.xmin + V_n.x * (A.xmax - A.xmin) / (D – 1),
A.ymax - V_n.y * (A.ymax - A.ymin) / (D – 1))

Where C is the set of complex numbers mapped from V to A.
__________________________________________

D has to be greater than or equal to one or else I get a divide-by-zero
condition.

There are a heck of a lot of choices wrt the mapping leading to the complex
numbers in the fractal cipher. You can go for sphere, circle, rect, square,
ect...
Parametric spirals, whatever.



Ummmm: I hope this does not make me sound like a complete kook!

;^/


IMVVHO, I think fractal ciphers can be make to work.

:^o

Chris M. Thomasson

unread,
Nov 14, 2015, 5:40:59 PM11/14/15
to
> "Ben Bacarisse" wrote in message news:87vb95y...@bsb.me.uk...

> > "Chris M. Thomasson" <nos...@nospam.nospam> writes:

[...]

> > So, a bitmap generator can use its
> > callback for that, and the cipher can use another callback for
> > encryption/decryption. Anyway, the reason for the scale factor is that
> > the scale can naturally bring any fractal closer, and/or further away
> > from the border.

> But now I don't know if that's part of the encryption algorithm (if so,
> where does a non-trivial scale factor come from?) and if not it's just
> muddying the waters.

The code I posted did not yet make the scale factor a part of encryption
because it was not yet a part of (fractal::iter_settings).

Actually, the online code creates a little thumbnail sized rendering that
allows a user to get a view of where the axes are in the fractal.


> Ah, right. So it's a symmetric cipher; there's a shared key between
> Alice and Bob, presumably some or all of the details of the iteration.
> Is it the three points? Or the three points and the axes combined?

The online version uses the scale parameter for the cipher. Every parameter
is used in the "Private Key" portion. Take a look at:

http://funwithfractals.atspace.cc/ffe/fractal.js

It should look very similar to the C++ code I posted. Search for the text
(mbrot_iter_xx)
to get to the function that is basically the same as
(fractal::iterate_point).

I just have not added the scale point to the `fractal::iter_settings'
structure yet.



The axes sent with the ciphertext are created on the fly using the bytes of
the
plaintext along with some random numbers. Examine the `generate_public_key'
function in:

http://funwithfractals.atspace.cc/ffe/ffe.js

The axes there are posted with the ciphertext, these are then added to the
private key axes.

I am going to change "private key" to "private fractal settings", and
"public key" to "public axes".

Sound better at all? the (fractal::iter_settings) is representing the
"private fractal settings".


As for adding the 0.1 in the orbit trap, well that is totally arbitrary.

The "magic" numbers in the cipher wrt the:

cipher_mutator_real *= 5134.0413;
cipher_mutator_real *= 178654.681;

parts are going to be incorporated into the private fractal settings.

Ben Bacarisse

unread,
Nov 14, 2015, 9:28:19 PM11/14/15
to
"Chris M. Thomasson" <nos...@nospam.nospam> writes:

>> "Ben Bacarisse" wrote in message news:87vb95y...@bsb.me.uk...
[This attribution line is messed up -- not my fault. If it refers to
the right message it should have one > in front of the line.]

>> Ah, right. So it's a symmetric cipher; there's a shared key between
>> Alice and Bob, presumably some or all of the details of the iteration.
>> Is it the three points? Or the three points and the axes combined?
>
> The online version uses the scale parameter for the cipher. Every parameter
> is used in the "Private Key" portion. Take a look at:
>
> http://funwithfractals.atspace.cc/ffe/fractal.js

Sorry, no. I don't want to look at different versions since there are
indications below that you've not finished the design yet. I can wait.
At some point, you will need to be clear about what the shared data is
that forms the key.

<snip>
> I am going to change "private key" to "private fractal settings", and
> "public key" to "public axes".
>
> Sound better at all? the (fractal::iter_settings) is representing the
> "private fractal settings".

I would advise (again!) that you avoid these loaded words in the
description of a symmetric cipher. I can't force you, but I also can't
understand why you cling to them. In general, a symmetric cipher has
some shared secret (loosely, "the key") and the rest is simply part of
the published algorithm.

<snip>
--
Ben.

rsharris....@gmail.com

unread,
Nov 15, 2015, 9:04:43 AM11/15/15
to
On Saturday, November 14, 2015 at 5:40:58 PM UTC-5, Chris M. Thomasson wrote:
> rsharris wrote:
> > [...]
> > Whenever I see floating point used I start worrying about getting the same results from different
> > compilers. The problem will (probably) be that different compilers reorder the floating point
> > operations and in some cases the results will differ in the least significant bits. Iterating those
> > results tends to amplify those small differences. It will be difficult to guarantee that two different
> > executables will produce the same fractal values to whatever level of precision your encryption
> > step requires. Most pixels will probably be close enough but there is some probably that at
> > least one could be different enough to misencrypt.
>
> > If you submit this as a manuscript, you're going to need to convince your audience, especially
> > the reviewers, that you've considered the effects of FP rounding error, and that you've designed
> > the process to be robust to differences in that error between executables no matter what the
> > plaintext or fractal are.
>
> I am hoping that relying/requiring a standard floating point representation would help. Something
> like JavaScript:
> http://www.w3schools.com/js/js_numbers.asp
> IEEE 754

Not to be mean-spirited, but just keep on "hoping".

Even the page you linked to shows an example of two algebraically equivalent expressions that produce a different floating point result (with the admonition that "floating point arithmetic is not always 100% accurate"). The problem goes beyond whether you have a standard floating point representation. The problem is that floating point is not exact.

Your code appears to be written in C++, not javascript. Given an expression, a C++ compiler is free to implement this expression in any algebraically equivalent order. They do so in order to optimize register usage (for example), not to guarantee the same exact result from one compiler to another. One compiler may choose to implement it one way, another compiler a different way, one of Alice's values differs from Bob's in the least significant bit and then you iterate with that a couple thousand times and you have very different results.

When you're just computing pretty pictures of fractals to hang on the wall, those differences wouldn't matter. I'm not familiar enough with this kind of fractal to know whether people do anything else with them. If so, then probably there have been some published papers that discuss this issue. You should look for those.

"Cross your fingers and hope the problem doesn't happen" isn't one of the hallmarks of a good design.

> WRT the dimensions D = floor(sqrt(L))+1, ... D has to be greater than or equal to one or else
> I get a divide-by-zero condition.

As I wrote, this is a minor point, and having D be larger than necessary (by one) in some cases is probably harmless.

But the only time ceil(sqrt(L)) will not be greater than or equal to one is when L is zero -- when the plaintext is an empty string. Looking at the code you posted, I can't tell what happens in this case. Your description makes me think there's going to be exactly one cipher text byte for every plaintext byte (but I can't easily determine if this is true from the code you posted). If that's true, nothing is going to be output for the L=0 case anyway.

Chris M. Thomasson

unread,
Nov 16, 2015, 4:51:10 PM11/16/15
to
> "wizzofozz" wrote in message news:n1thrn$dq3$1...@dont-email.me...

[...]

> So, if you want people to start tearing the shi% out of anything, you'll
> need to implement (again) something which can be run from the
> commandline.

FWIW, here is a new command line version of the program
that can encrypt/decrypt any file. Something to try to break
for fun? ;^)

http://pastebin.com/D7N4vBWa


I changed my terminology from “private/public key” to
secret key and salt respectively.

I hope this is okay!? ;^o


In order to compile this code on GCC you need the (-std=c99)
flag and link with the math library (-lm). Something like:

gcc -std=c99 ffe.c -o ffe -lm


Now, once you get this compiled, assume the name of the program
is (ffe) and execute the following command line:

ffe 0 default_secret_key


This will create a file named (default_secret_key) that contains
an example/default key to work with. The numbers in the file can
be edited with a text editor: Just change the numbers and nothing
else or you will corrupt it! I am using the number of elements
returned from (scanf) to determine corruption in the files: This
can definitely be improved upon!


Now, create a new file called (plaintext), and fill it with
anything you want; use a movie file, or a bunch of (A)'s...

;^)



Then run the following command line:

ffe 1 default_secret_key plaintext ciphertext

that will encrypt plaintext into the file ciphertext.



Okay... Now we are going to decrypt the ciphertext file using the
following command line:

ffe 2 default_secret_key plaintext_compare ciphertext

that will create a new file called (plaintext_compare) that should
be identical to the original (plaintext) file.

You can follow all of the steps above online using the following
awesome site:

http://www.tutorialspoint.com/compile_c99_online.php

Can you compile it?

Do the command lines work for you?

Chris M. Thomasson

unread,
Nov 16, 2015, 5:00:51 PM11/16/15
to
wrote in message
news:4ac0a476-2392-408a...@googlegroups.com...

>>On Saturday, November 14, 2015 at 5:40:58 PM UTC-5, Chris M. Thomasson
>>wrote:
> rsharris wrote:
[...]
>> I am hoping that relying/requiring a standard floating point
>> representation would help. Something
>>like JavaScript:
>> http://www.w3schools.com/js/js_numbers.asp
>> IEEE 754

> Not to be mean-spirited, but just keep on "hoping".

Can you think of a high precision number library that can possibly
help things out a bit?

Perhaps something like https://gmplib.org ?

Humm...

Rich

unread,
Nov 16, 2015, 5:21:15 PM11/16/15
to
That will only reduce the possibility of a rounding error, but never
fully eliminate it.

The reason is simple. It is because not all fractional numbers can be
represented in a finite space.

The easy ones to understand for those of us who normally operate in
base-10 notation are:

represent, exactly, this fraction in decimal digits:

1/3 (one third)

represent, exactly, the value of this constant in decimal digits:

pi


The answer to both is: you can't. The base-10 decimal representation
of both values is an infinte number of digits.

But since your computer has a finite amount of memory, it can not store
an infinite number of digits, and so, eventually, it has to store a
very close approximation, but not the exact value.

You might be able to make use of the rational number portion of GMP to
avoid the issue for everything except the irrational numbers (pi and
friends), which means you are quite unlikely to hit an issue, but the
probability would not be zero, just likely small enough you'd seldom
ever notice it.


Rich

unread,
Nov 16, 2015, 5:26:07 PM11/16/15
to
Chris M. Thomasson <nos...@nospam.nospam> wrote:
> Can you compile it?

I can confirm that using gcc 4.8.2 on Linux, with this command line:

gcc -Wall -std=c99 ffe.c -o ffe -lm

results in an executable, with no compiler warnings output.

That is the sum total of what I can confirm.


Note, you might consider shipping a Makefile along with the c code so
you can include any needed flags for compiling the code, rather than
relying upon "add this flag, an this flag, etc." type instructions.

Ben Bacarisse

unread,
Nov 16, 2015, 5:51:05 PM11/16/15
to
Rich <ri...@example.invalid> writes:

> Chris M. Thomasson <nos...@nospam.nospam> wrote:
>> wrote in message
>> news:4ac0a476-2392-408a...@googlegroups.com...
>
>> >>On Saturday, November 14, 2015 at 5:40:58 PM UTC-5, Chris M. Thomasson
>> >>wrote:
>> > rsharris wrote:
>> [...]
>> >> I am hoping that relying/requiring a standard floating point
>> >> representation would help. Something
>> >>like JavaScript:
>> >> http://www.w3schools.com/js/js_numbers.asp
>> >> IEEE 754
>
>> > Not to be mean-spirited, but just keep on "hoping".
>
>> Can you think of a high precision number library that can possibly
>> help things out a bit?
>
>> Perhaps something like https://gmplib.org ?
>
> That will only reduce the possibility of a rounding error, but never
> fully eliminate it.

<snip>
> You might be able to make use of the rational number portion of GMP to
> avoid the issue for everything except the irrational numbers (pi and
> friends), which means you are quite unlikely to hit an issue, but the
> probability would not be zero, just likely small enough you'd seldom
> ever notice it.

None of the computations require anything but rational numbers (albeit
include an imaginary part) so, space and time permitting, the
computations can be made exact. I don't see any exceptions in the code.

--
Ben.

Richard Heathfield

unread,
Nov 16, 2015, 6:16:50 PM11/16/15
to
On 16/11/15 21:51, Chris M. Thomasson wrote:
>> "wizzofozz" wrote in message news:n1thrn$dq3$1...@dont-email.me...
>
> [...]
>
>> So, if you want people to start tearing the shi% out of anything, you'll
>> need to implement (again) something which can be run from the
>> commandline.
>
> FWIW, here is a new command line version of the program
> that can encrypt/decrypt any file. Something to try to break
> for fun? ;^)
>
> http://pastebin.com/D7N4vBWa

It compiles, albeit with rather a lot of warnings (but then my makefiles
are somewhat fascist in nature).

I encrypted "Now is the time for all good men to come to the party.\n"
(sans quotes), and stored the result. (It decrypted just fine, by the way.)

Then I encrypted "Oow is the time for all good men to come to the
party.\n", which is just one bit different, and compared the bits of the
ciphertext files. Out of 1040 bits, 329 (31+%) had changed. That's not
brilliant, but it's not shabby either, not by any means.

It is true that quite a few of those differences are in the header
information. (I found this surprising, since the key was the same for
each encryption.) But the avalanching does appear to affect the whole
file. Here is my key file for both encryptions:

iters:314
scale:(1.0000000000000, 0.0000000000000)
julia0:(0.3600000000000, 0.0000000000000)
julia1:(-0.7500000000000, 0.1000000000000)
julia2:(0.3500000000000, 0.1000000000000)
axes:(-0.7000000000000, 0.3000000000000, -0.2000000000000, 0.8000000000000)

Encryption 1 ("Now is the time...") ends with 85 0B 64 62
Encryption 2 ("Oow is the time...") ends with 68 FE 47 33

#1: 10001001 00001011 01100100 01100010
#2: 01101000 11111110 01000111 00110011

I see no obvious relationship between the two, which is of course a Good
Thing.

--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

rsharris....@gmail.com

unread,
Nov 17, 2015, 10:16:42 AM11/17/15
to
>>>>> I am hoping that relying/requiring a standard floating point
>>>>> representation would help. Something like JavaScript:
>>>>> http://www.w3schools.com/js/js_numbers.asp
>>>>> IEEE 754
>>>>
>>>> Not to be mean-spirited, but just keep on "hoping".
>>>
>>> Can you think of a high precision number library that can possibly
>>> help things out a bit?
>>
>> That will only reduce the possibility of a rounding error, but never
>> fully eliminate it.
>
> <snip>
> > You might be able to make use of the rational number portion of GMP to
> > avoid the issue <snip>
>
> None of the computations require anything but rational numbers (albeit
> include an imaginary part) so, space and time permitting, the computations
> can be made exact. I don't see any exceptions in the code.

If the number of iterations is large, space could become an issue though.

Thinking this through, the process doesn't need exact results, just reproducible ones. So an implementation in rationals, but which keeps the numerator and denominator within a fixed size, would probably be adequate. That is, whenever the exact result would cause either numerator or denominator to be too large, the number would be reduced to an approximation in which those are not too large. As long as the code to do this is deterministic (there's no reason it wouldn't be), the problem with floating point irreproducibility is avoided.

Whether this has any ill effect on the "quality" of the resulting fractal, as relates to its use as a crypto key, I can't say.

I guess that can be implemented in C++ with a "bounded rational" class that overrides all the arithmetic operators.

Jakob Bohm

unread,
Nov 17, 2015, 11:17:36 AM11/17/15
to
Could old-fashioned fixed point notation do the job (i.e. use ints or
long ints and interpret them as referring to a fixed design time
denominator, e.g. 1/4096 or 1/0x1000000 depending on the numeric range
needed in the algorithm.

Enjoy

Jakob
--
Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com
Transformervej 29, 2860 Søborg, Denmark. Direct +45 31 13 16 10
This public discussion message is non-binding and may contain errors.
WiseMo - Remote Service Management for PCs, Phones and Embedded

wizzofozz

unread,
Nov 17, 2015, 3:30:59 PM11/17/15
to
On 16-11-2015 22:51, Chris M. Thomasson wrote:
>> "wizzofozz" wrote in message news:n1thrn$dq3$1...@dont-email.me...
>
> [...]
>
>> So, if you want people to start tearing the shi% out of anything, you'll
>> need to implement (again) something which can be run from the
>> commandline.
>
> FWIW, here is a new command line version of the program
> that can encrypt/decrypt any file. Something to try to break
> for fun? ;^)
>
> Can you compile it?
>

Yes, that worked. I also encrypted a bunch of zeroes with it. No obvious
patterns yet. I get some patterns, but I'm not sure if those make it
distinguishable from random. I want to look into that myself before
bothering you with it.

> Do the command lines work for you?

More or less.

As it is now, it's ok for playing with different plaintexts. Playing
with the keys is still a bit cumbersome. But, it's better than the GUI ;-)

Ozz

Chris M. Thomasson

unread,
Nov 19, 2015, 3:36:53 PM11/19/15
to
> "Richard Heathfield" wrote in message news:n2do0k$en1$1...@dont-email.me...

> > On 16/11/15 21:51, Chris M. Thomasson wrote:
> >> "wizzofozz" wrote in message news:n1thrn$dq3$1...@dont-email.me...
> >
> > [...]
> >
> >> So, if you want people to start tearing the shi% out of anything,
> >> you'll
> >> need to implement (again) something which can be run from the
> >> commandline.
> >
> > FWIW, here is a new command line version of the program
> > that can encrypt/decrypt any file. Something to try to break
> > for fun? ;^)
> >
> > http://pastebin.com/D7N4vBWa

> It compiles, albeit with rather a lot of warnings (but then my makefiles
> are somewhat fascist in nature).

> I encrypted "Now is the time for all good men to come to the party.\n"
> (sans quotes), and stored the result. (It decrypted just fine, by the
> way.)

> Then I encrypted "Oow is the time for all good men to come to the
> party.\n", which is just one bit different, and compared the bits of the
> ciphertext files. Out of 1040 bits, 329 (31+%) had changed. That's not
> brilliant, but it's not shabby either, not by any means.

Thank you for taking a look at the ciphertext Richard. I am
glad that you are able to compile and actually use the
resulting executable!


> It is true that quite a few of those differences are in the header
> information. (I found this surprising, since the key was the same for each
> encryption.) But the avalanching does appear to affect the whole file.
> Here is my key file for both encryptions:

Yes. The avalanche effect is not brilliant, its rather crude,
but it does seem to change the whole file. It is due to the
nature of a fractal, and the axes into it. Have you tried
encrypting a plaintext P with key A, slightly modifying A and
decrypting P into Px and checking how close P is to Px? That is what
I am very interested in. How "sensitive" the key actually is.

iters, or iteration count, is not going to do much, so trying
modifying the scale, Julia points, and the axes in the secret key.


> iters:314
> scale:(1.0000000000000, 0.0000000000000)
> julia0:(0.3600000000000, 0.0000000000000)
> julia1:(-0.7500000000000, 0.1000000000000)
> julia2:(0.3500000000000, 0.1000000000000)
> axes:(-0.7000000000000, 0.3000000000000, -0.2000000000000,
> 0.8000000000000)

> Encryption 1 ("Now is the time...") ends with 85 0B 64 62
> Encryption 2 ("Oow is the time...") ends with 68 FE 47 33

> #1: 10001001 00001011 01100100 01100010
> #2: 01101000 11111110 01000111 00110011

> I see no obvious relationship between the two, which is of
course a Good Thing.

Thanks again. I hope that you can find some problems with it
and crack the living crap out of it.

I am looking forward to that for sure!

:^)


I do not have time to give a proper response; been fairly busy
lately. Sorry about that.


If you have any questions, or criticisms, please let me know.
I really want to crack this damn thing, and any help I can get
is a good thing indeed.

My C is a little crusty, but at least it can compile, even with
your hardcore Makefile. BTW, can you give me some of the warnings
you get? I want to make the code compile as clean as possible!


Thank you!

Chris M. Thomasson

unread,
Nov 19, 2015, 3:43:03 PM11/19/15
to
> "wizzofozz" wrote in message news:n2g2lk$ak1$1...@dont-email.me...

> > On 16-11-2015 22:51, Chris M. Thomasson wrote:
> >> "wizzofozz" wrote in message news:n1thrn$dq3$1...@dont-email.me...
> >
> > [...]
> >
> >> So, if you want people to start tearing the shi% out of anything,
> >> you'll
> >> need to implement (again) something which can be run from the
> >> commandline.
> >
> > FWIW, here is a new command line version of the program
> > that can encrypt/decrypt any file. Something to try to break
> > for fun? ;^)
> >
> > Can you compile it?

> Yes, that worked. I also encrypted a bunch of zeroes with it. No obvious
> patterns yet. I get some patterns, but I'm not sure if those make it
> distinguishable from random. I want to look into that myself before
> bothering you with it.

Go ahead and tell me about patterns you have found: I want
to hear about them. The default key has the imaginary axes
crossing the real line. It should give “some” patterns. I set
the default axes the way they are for a reason...


> > Do the command lines work for you?

> More or less.

> As it is now, it's ok for playing with different plaintexts. Playing
> with the keys is still a bit cumbersome. But, it's better than the GUI ;-)

:^D

I am glad this is working for you. As for the secret key
file, well, I could do better... indeed!

;^o


Thanks again Wizz.

rsharris....@gmail.com

unread,
Nov 23, 2015, 12:30:19 PM11/23/15
to
On Tuesday, November 17, 2015 at 11:17:36 AM UTC-5, Jakob Bohm wrote:
> Could old-fashioned fixed point notation do the job [snip]

Possibly.

Another possibility would be to include error correction as part of the process, except you'd still have non-zero probability of a decryption being incorrect.

The bigger problem is how to convince the designer the problem is a real concern. And I can't see how to accomplish that. There's not much point in discussing solutions.

Bob H


Chris M. Thomasson

unread,
Nov 23, 2015, 2:52:03 PM11/23/15
to
> wrote in message
> news:028543cf-43fe-4957...@googlegroups.com...
I understand the problem, and its in the name. I used the word
"Funny" Fractal Encryption for a reason. The damn thing can act
funny sometimes wrt the hornets nest of pissed off floating point
issues.

However, I still want to continue developing it, for fun...

;^)

Chris M. Thomasson

unread,
Nov 23, 2015, 3:21:27 PM11/23/15
to
> "Chris M. Thomasson" wrote in message
> news:n2vqou$hko$1...@speranza.aioe.org...

> > wrote in message
> > news:028543cf-43fe-4957...@googlegroups.com...

[...]
> > The bigger problem is how to convince the designer the problem is a real
> > concern. And I can't see how to accomplish that. There's not much
> > point in discussing solutions.

> I understand the problem,

Heck, I even thought of using convergents of continued fractions:

https://groups.google.com/d/msg/sci.crypt/g6CPhD9mh24/L9D7OZK66j4J

as a possible fix wrt the header of ciphertext, the axes. Perhaps I can
require
a certain compiler along with a standard floating point representation.

Anyway, thank you for giving a damn about the "funny" aspect of my "cipher"

:^o

I just do not want to slow this thing down to the point where a snail
hiking up a mountain of salt will beat it to the damn finish line!

Ouch!

rsharris....@gmail.com

unread,
Nov 23, 2015, 4:28:14 PM11/23/15
to
On Monday, November 23, 2015 at 3:21:27 PM UTC-5, Chris M. Thomasson wrote:
> Bob H wrote:
>>> The bigger problem is how to convince the designer the problem is a real
>>> concern. And I can't see how to accomplish that. There's not much
>>> point in discussing solutions.
>
>> I understand the problem,
>
> Heck, I even thought of using convergents of continued fractions:
> https://groups.google.com/d/msg/sci.crypt/g6CPhD9mh24/L9D7OZK66j4J

My mistake. I hadn't seen the earlier thread about this scheme, and the only posts I'd seen from you in this thread made it seem like you didn't think it was a problem or didn't understand why. Again, my mistake.

Bob H

Chris M. Thomasson

unread,
Dec 4, 2015, 4:31:49 PM12/4/15
to
>"Richard Heathfield" wrote in message news:n2do0k$en1$1...@dont-email.me...

>>On 16/11/15 21:51, Chris M. Thomasson wrote:
[,,,]
>> FWIW, here is a new command line version of the program
>> that can encrypt/decrypt any file. Something to try to break
>> for fun? ;^)
>>
>> http://pastebin.com/D7N4vBWa

>It compiles, albeit with rather a lot of warnings (but then my makefiles
>are somewhat fascist in nature).

Can you please give me some of those warnings?

I want this to compile as clean as possible!

Thank you.

Richard Heathfield

unread,
Dec 5, 2015, 4:49:30 PM12/5/15
to
fracrypt.c:32:1: warning: no previous prototype for
‘ffe_cnv_uint_from_buffer’ [-Wmissing-prototypes]
ffe_cnv_uint_from_buffer(
^
fracrypt.c:50:1: warning: no previous prototype for
‘ffe_cnv_double_to_string_to_double’ [-Wmissing-prototypes]
ffe_cnv_double_to_string_to_double(
^
fracrypt.c:72:1: warning: no previous prototype for
‘ffe_util_cantor_packing’ [-Wmissing-prototypes]
ffe_util_cantor_packing(
^
fracrypt.c: In function ‘ffe_util_cantor_packing’:
fracrypt.c:76:37: warning: conversion to ‘double’ from ‘size_t’ may
alter its value [-Wconversion]
size_t ret = (size_t)(0.5 * (n0 + n1) * (n0 + n1 + 1) + n1);
^
fracrypt.c:76:54: warning: conversion to ‘double’ from ‘size_t’ may
alter its value [-Wconversion]
size_t ret = (size_t)(0.5 * (n0 + n1) * (n0 + n1 + 1) + n1);
^
fracrypt.c:76:5: warning: conversion to ‘double’ from ‘size_t’ may alter
its value [-Wconversion]
size_t ret = (size_t)(0.5 * (n0 + n1) * (n0 + n1 + 1) + n1);
^
fracrypt.c: At top level:
fracrypt.c:83:1: warning: no previous prototype for ‘ffe_util_random’
[-Wmissing-prototypes]
ffe_util_random(void)
^
fracrypt.c:90:1: warning: no previous prototype for
‘ffe_util_random_sign’ [-Wmissing-prototypes]
ffe_util_random_sign(double n)
^
fracrypt.c:106:1: warning: no previous prototype for ‘ffe_complex_add’
[-Wmissing-prototypes]
ffe_complex_add(
^
fracrypt.c:115:1: warning: no previous prototype for ‘ffe_complex_mul’
[-Wmissing-prototypes]
ffe_complex_mul(
^
fracrypt.c:150:1: warning: no previous prototype for
‘ffe_secret_key_output_status’ [-Wmissing-prototypes]
ffe_secret_key_output_status(
^
fracrypt.c:181:1: warning: no previous prototype for
‘ffe_secret_key_parse_from_file’ [-Wmissing-prototypes]
ffe_secret_key_parse_from_file(
^
fracrypt.c:212:1: warning: no previous prototype for
‘ffe_secret_key_store_to_file’ [-Wmissing-prototypes]
ffe_secret_key_store_to_file(
^
fracrypt.c:252:1: warning: no previous prototype for
‘ffe_salt_output_status’ [-Wmissing-prototypes]
ffe_salt_output_status(
^
fracrypt.c:274:1: warning: no previous prototype for
‘ffe_salt_parse_from_file’ [-Wmissing-prototypes]
ffe_salt_parse_from_file(
^
fracrypt.c:321:1: warning: no previous prototype for
‘ffe_salt_generate_from_file’ [-Wmissing-prototypes]
ffe_salt_generate_from_file(
^
fracrypt.c: In function ‘ffe_salt_generate_from_file’:
fracrypt.c:355:17: warning: conversion to ‘double’ from ‘size_t’ may
alter its value [-Wconversion]
fmod(pow(pack, RN() * 0.3 + 0.3), 0.3 + RN() * 0.6),
^
fracrypt.c:356:17: warning: conversion to ‘double’ from ‘size_t’ may
alter its value [-Wconversion]
fmod(pow(pack, RN() * 0.3 + 0.3), 0.3 + RN() * 0.6),
^
fracrypt.c:357:17: warning: conversion to ‘double’ from ‘size_t’ may
alter its value [-Wconversion]
fmod(pow(pack, RN() * 0.3 + 0.3), 0.3 + RN() * 0.6),
^
fracrypt.c:358:17: warning: conversion to ‘double’ from ‘size_t’ may
alter its value [-Wconversion]
fmod(pow(pack, RN() * 0.3 + 0.3), 0.3 + RN() * 0.6)
^
fracrypt.c: At top level:
fracrypt.c:379:1: warning: no previous prototype for
‘ffe_salt_store_to_file’ [-Wmissing-prototypes]
ffe_salt_store_to_file(
^
fracrypt.c:429:1: warning: no previous prototype for ‘ffe_create’
[-Wmissing-prototypes]
ffe_create(
^
fracrypt.c:445:1: warning: no previous prototype for ‘ffe_destroy’
[-Wmissing-prototypes]
ffe_destroy(
^
fracrypt.c:452:1: warning: no previous prototype for
‘ffe_cipher_iterate_point’ [-Wmissing-prototypes]
ffe_cipher_iterate_point(
^
fracrypt.c: In function ‘ffe_cipher_iterate_point’:
fracrypt.c:479:32: warning: conversion to ‘unsigned int’ from ‘size_t’
may alter its value [-Wconversion]
mutator->iters = i + 1;
^
fracrypt.c: At top level:
fracrypt.c:495:1: warning: no previous prototype for
‘ffe_cipher_buffer_inplace’ [-Wmissing-prototypes]
ffe_cipher_buffer_inplace(
^
fracrypt.c: In function ‘ffe_cipher_buffer_inplace’:
fracrypt.c:513:30: warning: conversion to ‘unsigned int’ from ‘size_t’
may alter its value [-Wconversion]
unsigned int vpx = n % cipher->dims;
^
fracrypt.c:514:30: warning: conversion to ‘unsigned int’ from ‘size_t’
may alter its value [-Wconversion]
unsigned int vpy = n / cipher->dims;
^
fracrypt.c:539:39: warning: cast from function call of type ‘double’ to
non-matching type ‘long unsigned int’ [-Wbad-function-cast]
unsigned int cmutator_uint = ((size_t)fabs(cmutator_real)) %
FFE_BYTESZ;
^
fracrypt.c:551:36: warning: conversion to ‘int’ from ‘unsigned int’ may
change the sign of the result [-Wsign-conversion]
cmutated_byte = buf[i] - cmutator_uint;
^
fracrypt.c:555:45: warning: conversion to ‘unsigned int’ from ‘int’ may
change the sign of the result [-Wsign-conversion]
cmutated_byte = abs((buf[i] + FFE_BYTESZ) -
cmutator_uint);
^
fracrypt.c:555:59: warning: conversion to ‘int’ from ‘unsigned int’ may
change the sign of the result [-Wsign-conversion]
cmutated_byte = abs((buf[i] + FFE_BYTESZ) -
cmutator_uint);
^
fracrypt.c:559:9: warning: conversion to ‘unsigned char’ from ‘int’ may
alter its value [-Wconversion]
buf[i] = cmutated_byte;
^
fracrypt.c:563:13: warning: conversion to ‘double’ from ‘size_t’ may
alter its value [-Wconversion]
unsigned int per = (unsigned int)ceil((n /
(double)cipher->in_file_size) * 100.0);
^
fracrypt.c:563:32: warning: cast from function call of type ‘double’ to
non-matching type ‘unsigned int’ [-Wbad-function-cast]
unsigned int per = (unsigned int)ceil((n /
(double)cipher->in_file_size) * 100.0);
^
fracrypt.c:569:5: warning: conversion to ‘double’ from ‘size_t’ may
alter its value [-Wconversion]
unsigned int per = (unsigned int)ceil((n /
(double)cipher->in_file_size) * 100.0);
^
fracrypt.c:569:24: warning: cast from function call of type ‘double’ to
non-matching type ‘unsigned int’ [-Wbad-function-cast]
unsigned int per = (unsigned int)ceil((n /
(double)cipher->in_file_size) * 100.0);
^
fracrypt.c:496:23: warning: unused parameter ‘self’ [-Wunused-parameter]
struct ffe* const self,
^
fracrypt.c: At top level:
fracrypt.c:577:1: warning: no previous prototype for ‘ffe_sys_calc_salt’
[-Wmissing-prototypes]
ffe_sys_calc_salt(
^
fracrypt.c: In function ‘ffe_sys_calc_salt’:
fracrypt.c:581:5: warning: conversion to ‘double’ from ‘size_t’ may
alter its value [-Wconversion]
cipher->dims = (size_t)(sqrt(in_file_size) + 1);
^
fracrypt.c:581:20: warning: conversion to ‘unsigned int’ from ‘long
unsigned int’ may alter its value [-Wconversion]
cipher->dims = (size_t)(sqrt(in_file_size) + 1);
^
fracrypt.c: At top level:
fracrypt.c:603:1: warning: no previous prototype for ‘ffe_encrypt’
[-Wmissing-prototypes]
ffe_encrypt(
^
fracrypt.c:664:1: warning: no previous prototype for ‘ffe_decrypt’
[-Wmissing-prototypes]
ffe_decrypt(
^
fracrypt.c:742:1: warning: no previous prototype for
‘ffe_cmdline_app_create’ [-Wmissing-prototypes]
ffe_cmdline_app_create(
^
fracrypt.c:828:1: warning: no previous prototype for
‘ffe_cmdline_sys_create_default_skey’ [-Wmissing-prototypes]
ffe_cmdline_sys_create_default_skey(
^
fracrypt.c:859:1: warning: no previous prototype for
‘ffe_cmdline_sys_encrypt’ [-Wmissing-prototypes]
ffe_cmdline_sys_encrypt(
^
fracrypt.c:884:1: warning: no previous prototype for
‘ffe_cmdline_sys_decrypt’ [-Wmissing-prototypes]
ffe_cmdline_sys_decrypt(
^
fracrypt.c:909:1: warning: no previous prototype for
‘ffe_cmdline_display_help’ [-Wmissing-prototypes]
ffe_cmdline_display_help(
^
fracrypt.c:931:1: warning: no previous prototype for
‘ffe_cmdline_app_run’ [-Wmissing-prototypes]
ffe_cmdline_app_run(
^
fracrypt.c:955:1: warning: no previous prototype for
‘ffe_cmdline_app_destroy’ [-Wmissing-prototypes]
ffe_cmdline_app_destroy(
^

Chris M. Thomasson

unread,
Dec 5, 2015, 5:02:24 PM12/5/15
to
> > "Richard Heathfield" wrote in message
> > news:n3vm0k$fr1$1...@dont-email.me...

> > On 04/12/15 21:31, Chris M. Thomasson wrote:
> >> "Richard Heathfield" wrote in message
> >> news:n2do0k$en1$1...@dont-email.me...
[...]
> >> It compiles, albeit with rather a lot of warnings (but then my
> >> makefiles are somewhat fascist in nature).
> >
> > Can you please give me some of those warnings?
> >
> > I want this to compile as clean as possible!

That’s great!

I can get rid of a lot of them by providing proper prototypes.

However, I need to really examine the casts and make sure they are actually
okay.

Also, I did not notice that unused parameter.

Thank you Richard. I really appreciate it.

[...]

Chris M. Thomasson

unread,
Dec 5, 2015, 5:09:28 PM12/5/15
to
> "Chris M. Thomasson" wrote in message
> news:n212rb$ob6$1...@speranza.aioe.org...
[...]

> The paper is scraping along.

[...]

FWIW, I am describing the algorithm in pseudo-code along the following
guidelines:

http://users.csc.calpoly.edu/~jdalbey/SWE/pdl_std.html

Any thoughts?

0 new messages