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

Re: Fun/Funny Fractal Encryption...

202 views
Skip to first unread message

Chris M. Thomasson

unread,
Jul 10, 2015, 3:26:02 PM7/10/15
to
> "Chris M. Thomasson" wrote in message
> news:mnhpm5$fh9$1...@speranza.aioe.org... [...]

This is cross-posted with comp.lang.c. I am hoping some of them take a look
at the C
program and perhaps find some bugs for me to fix! :^)

Anyway...
____________________________________________________

I have created a pre-alpha version of a fun little toy
project I call “Funny Fractal Encryption”. It is based
on the idea of generating a stream cypher out of renderings
from fractal formulas. The initial version of the program
is using escape time fractals, Julia set in this case. The
escape iteration counts mutated with color transformation
functions and an orbit trap are then used to build a cypher
of a given location in the fractal. This cypher is then
used to encrypt the cleartext using simple modular arithmetic.
I can get a fairly decent avalanche effect of the resulting
cypertext by using the contents of the cleartext to decide
on what location to go in the Julia set. This location is
used as a public key that can be sent across the wire along
with its associated cypertext. The private key would consist
of a fractal formula, a location in the complex plane and an
iteration count. The resulting cypertext is VERY sensitive
to very small mutations in the fractal settings.

So, the overall scheme for this type of encryption would be
something like:

Bob and Alice want to send/receive encrypted messages to/from
each other.

Bob and Alice decide on a private key K0 consisting of a fractal
formula, location and iteration count that ends up rendering a
beautiful image.

Bob wants to send a message M to Alice, so he uses M to generate
a private key K1 consisting of a location. He then uses K0 and
K1 to generate a new fractal F. Bob then uses F to encrypt M as
EM.

Bob sends EM and K1 across the wire to Alice.

Alice uses the keys K0 and K1 to gain the fractal F.

Alice uses F to decrypt EM back into M.

Alice reads M.


Here is the C code for an embryonic version, pre-alpha indeed!
;^)

http://pastebin.com/fcV5YiJH
(this is the most recent version of the code)

I am VERY interested in any cyrpto analysis that can crack the
formula/key responsible for encrypting several messages with
the same public key/derived-fractal. Keep in mind that the derived
fractal, or public key should be mathematically tied to the original
private fractal.

FWIW, here is a link to the original thread I started over in
comp.lang.c:

https://groups.google.com/d/topic/comp.lang.c/vui6XP-IxRM/discussion
(this link has links to older versions of the program on pastebin)


Well, is this 100% crap, or “perhaps” not all that shi%Ty?

;^o

Chris M. Thomasson

unread,
Jul 10, 2015, 6:10:42 PM7/10/15
to
> > "Chris M. Thomasson" wrote in message
> > news:mnp683$pld$1...@speranza.aioe.org...

> > "Chris M. Thomasson" wrote in message
> > news:mnhpm5$fh9$1...@speranza.aioe.org... [...]

> I am VERY interested in any cyrpto analysis that can crack the
> formula/key responsible for encrypting several messages with
> the same public key/derived-fractal. Keep in mind that the derived
> fractal, or public key should be mathematically tied to the original
> private fractal.

Yikes! I made a typo in there.

The public key is generated from the cleartext and is
tied to the ciphertext via the private key and can be
sent across the wire as is.

So, I would like to see the private key cracked out of
a series of ciphertexts and their associated public keys.

For instance, here are mutations to the phrase "Hello World"
encrypted with the program as-is. Keep in mind that you
know the private key, and the public keys. So, how you
one go about cracking another key that happens to works
for all of the following cipher texts:


public key = 0.068879
original = Hello World
encrypted = d*GCXsUFHG`
decrypted = Hello World


public key = 0.235041
original = hello World
encrypted = FF!]y@prMak
decrypted = hello World


public key = 0.224501
original = Hello Wordl
encrypted = F2MNVaqXhve
decrypted = Hello Wordl


public key = 0.059056
original = Hello World Hello
encrypted = 1zCCZlG?'%e7pAfk7
decrypted = Hello World Hello


public key = 0.107481
original = Hello World hello
encrypted = %')Ln2,(Pf>IA sq5
decrypted = Hello World hello



Is there an obvious pattern I totally missing!

;^/

Richard Heathfield

unread,
Jul 15, 2015, 10:52:33 AM7/15/15
to
[Followups set to sci.crypt]

On 10/07/15 20:25, Chris M. Thomasson wrote:

<snip>

> I am VERY interested in any cyrpto analysis that can crack the
> formula/key responsible for encrypting several messages with
> the same public key/derived-fractal. Keep in mind that the derived
> fractal, or public key should be mathematically tied to the original
> private fractal.

Chris, the first step is to try to crack the algorithm yourself.

That doesn't necessarily mean recovering a plaintext from a ciphertext
(without the key). Here are some ways to illustrate that a cipher is
insecure (not all will necessarily apply to every cipher, but most will
apply to most):

1) A frequency analysis shows that the distribution of ciphertext
characters varies significantly from what you would expect from
randomly-generated data. This is a relatively easy task.
(Transposition-only ciphers are bound to fail this test, which doesn't
necessarily mean they're no use.)

2) A change of a single bit in the plaintext results in a trifling
change in the ciphertext. One would expect, in a strong cipher, that the
alteration of a single bit in the plaintext would result in roughly half
the bits of the ciphertext changing (and these changes would be
distributed apparently at random through the file).

3) The cipher falls to the usual attacks on monoalphabetic or
polyalphabetic substitution ciphers. (Look up "Kasiski" and/or "Index of
Coincidence".)

4) Given a known plaintext (i.e. you have the ciphertext and you know at
least some of the plaintext that generated it), you can recover the key.

Those might be considered the most basic attacks. You need to try these
for yourself. You will never design a first-class (or even second- or
third-class) cipher if you don't acquire some experience in breaking
ciphers. (And it's quite a diverting exercise in its own right.)

When you ask "can anyone break this?", they're much more likely to *try*
if you can say "the ciphertext is indistinguishable from random, the
avalanching is up to snuff, and I tried the foo, bar, and baz attacks,
but couldn't make any headway" - in other words, if you've eliminated
the obvious and also shown that you've made an effort.

--
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,
Jul 16, 2015, 5:32:53 PM7/16/15
to
> "Richard Heathfield" wrote in message news:mo5s0m$um6$1...@dont-email.me...

> [Followups set to sci.crypt]

> > On 10/07/15 20:25, Chris M. Thomasson wrote:

<snip>

> > I am VERY interested in any cyrpto analysis that can crack the
> > formula/key responsible for encrypting several messages with
> > the same public key/derived-fractal. Keep in mind that the derived
> > fractal, or public key should be mathematically tied to the original
> > private fractal.

> Chris, the first step is to try to crack the algorithm yourself.

> That doesn't necessarily mean recovering a plaintext from a ciphertext
> (without the key). Here are some ways to illustrate that a cipher is
> insecure (not all will necessarily apply to every cipher, but most will
> apply to most):

I HOPE cracking this sucker will be not all that “hard” using the
excellent information you so kindly provided me below:



> 1) A frequency analysis shows that the distribution of ciphertext
> characters varies significantly from what you would expect from
> randomly-generated data. This is a relatively easy task.
> (Transposition-only ciphers are bound to fail this test, which doesn't
> necessarily mean they're no use.)

Okay, I will start here first. Now I have a couple of questions,
wrt this specific aspect of cracking the fractal cipher. I am going
to wait for an answer here before I actually start laying down real
code. I also really need to draft a flow chart of different methods
to crack the shi% out out of this fractal toy I finally got the guts
to make public! ;^o


0a: How big of sample cleartext should start off with for “proper”
frequency analysis? Megabytes, or perhaps 5 characters; something
like “CHRIS”? Humm...

0b: How big of a “main alphabet”, akin to a color pallet wrt fractals,
should I use for a pseudo/fake one-time pad, or stream cipher? WRT
the code as-is, it will use a 9x9 fractal pad for a any 5 character
cleartext. FWIW, the size of the pad is governed by a sqrt of the
number of characters in the cleartext plus 1, multiplied by the
`dim_scale' variable in the function “int main() { … }”. This makes
a perfect square pad that can hold more than the character count in
the cleartext.

FWIW, the main alphabet in the code is defined as `CT_MBROT_ABET'.




1: A nice way to interpret the character frequency?

;^o




> 2) A change of a single bit in the plaintext results in a trifling change
> in the ciphertext. One would expect, in a strong cipher, that the
> alteration of a single bit in the plaintext would result in roughly half
> the bits of the ciphertext changing (and these changes would be
> distributed apparently at random through the file).

I hope I am going down a “fairly decent?” path wrt this question Richard;
avalanche effect indeed! :^)

So far I am only using a couple of “aspects” of information derived from
the plain/cleartext to mutate/generate a “new location” of the private
fractal generated on a plain/cleartext basis. That is, one change in the
cleartext sure “seems” to alter the nature of the ciphertext. However,
there is an interesting caveat I mentioned in this thread. The mutation
ends up basically requiring “another key” that is “okay?” to send across
the wire. So, each mutation in the cleartext creates its own, “unique?”,
public key that is derived from the private key, or formula if you will...






> 3) The cipher falls to the usual attacks on monoalphabetic or
> polyalphabetic substitution ciphers. (Look up "Kasiski" and/or "Index of
> Coincidence".)

Check! This is on the “to-do” list, so to speak. Thanks.




> 4) Given a known plaintext (i.e. you have the ciphertext and you know at
> least some of the plaintext that generated it), you can recover the key.

Infinite Checks of beauty; thank you Richard!

IMVVVHO, this “third-party/SELF” crack just might end of being an important
insight into analyzing a deeper nature of fractals. I have to admit Richard,
well, I am not really/totally doing this for a “cipher”, as much as another
way to look at fractals... Keep in mind, fractals, perhaps, “can?” be used
in some fairly “interesting” ways:

http://www.fractenna.com

A single example...

;^)




> Those might be considered the most basic attacks. You need to try these
> for yourself. You will never design a first-class (or even second- or
> third-class) cipher if you don't acquire some experience in breaking
> ciphers. (And it's quite a diverting exercise in its own right.)

thank you: RICHARD HEATHFIELD!




> When you ask "can anyone break this?", they're much more likely to *try*
> if you can say "the ciphertext is indistinguishable from random, the
> avalanching is up to snuff, and I tried the foo, bar, and baz attacks, but
> couldn't make any headway" - in other words, if you've eliminated the
> obvious and also shown that you've made an effort.

Point taken Sir!

Thanks again.




BTW, I am indeed here to LEARN Richard!


DAMN! I feel a bit guilty because I am not PAYING you all for the dense,
free and AWESOME advise:


God bless this group!

:^D

Richard Heathfield

unread,
Jul 16, 2015, 6:34:25 PM7/16/15
to
On 16/07/15 22:24, Chris M. Thomasson wrote:
>> "Richard Heathfield" wrote in message news:mo5s0m$um6$1...@dont-email.me...
>
>> [Tests to try]
>> 1) A frequency analysis shows that the distribution of ciphertext
>> characters varies significantly from what you would expect from
>> randomly-generated data. This is a relatively easy task.
>> (Transposition-only ciphers are bound to fail this test, which doesn't
>> necessarily mean they're no use.)
>
> 0a: How big of sample cleartext should start off with for “proper”
> frequency analysis? Megabytes, or perhaps 5 characters; something
> like “CHRIS”? Humm...

5 bytes won't give you anything like a reasonable assessment of your
cipher's characteristics. Megabytes would be all right, but if you take,
say, the complete text of Julius Caesar or Midsummer Night's Dream, and
encrypt that. Then do the frequency analysis:

1) set up an array 256 elements in size, with every element set to 0 -
e.g. unsigned long freq[256] = {0};
2) read each character of the ciphertext: ch = getc(fp);
3) record it: ++freq[ch];
4) when you're done, calculate the variance and thus the standard deviation:

total = 0.0; /* this should be a double, obviously */
for(i = 0; i < 256; i++)
{
total += freq[i];
}
mean = total / 256.0;
variance = 0.0;
for(i = 0; i < 256; i++)
{
double diff = freq[i] - mean;
variance += diff * diff; /* squaring discards the sign information */
}
stddev = sqrt(variance);

What would you expect the standard deviation to be if the input were a
randomly-generated file of the same size? If your std dev is
significantly greater than this, that's a problem.

> 0b: How big of a “main alphabet”, akin to a color pallet wrt fractals,
> should I use for a pseudo/fake one-time pad, or stream cipher?

If you want to be able to encrypt any file, you should be able to deal
with any byte value in the range 0-255.

<snip>

Chris M. Thomasson

unread,
Jul 19, 2015, 4:24:31 PM7/19/15
to
> "Richard Heathfield" wrote in message news:mo9bem$urf$1...@dont-email.me...

> > On 16/07/15 22:24, Chris M. Thomasson wrote:
[...]
> > 0a: How big of sample cleartext should start off with for “proper”
> > frequency analysis? Megabytes, or perhaps 5 characters; something
> > like “CHRIS”? Humm...

> 5 bytes won't give you anything like a reasonable assessment of your
> cipher's characteristics. Megabytes would be all right, but if you take,
> say, the complete text of Julius Caesar or Midsummer Night's Dream, and
> encrypt that. Then do the frequency analysis:

[...]

I am almost finished with a prototype. However, the nature of
the program raises some other questions about C wrt sending
floating point across the wire. So far, I am just sending the
fractional numbers as cleartext (e.g., “-0.5 0.5”, ect...) and
using `atof()' to convert them on the receiving end. Humm.

Also, I am breaking the algorithm apart into several individual
programs. I am working on `ffe_encrypt' now. This takes an input
file for cleartext, and two output files; one for a public key
and its associated ciphertext, a 2d point, and a location in the
complex plane:


inf = input file (read-only)
outf = output file (write-only)

ffe_encrypt <inf_cleartext> <outf_publickey> <outf_ciphertext>
<px> <py> <pxmin> <pxmax> <pymin> <pymax>


Example command-line:

ffe_encrypt clear.file publickey.file cipher.file -0.7 0.3 -0.5
0.5 -0.5 0.5



I am planning a ffe_decrypt program as well:

ffe_decrypt <inf_ciphertext> <inf_publickey> <outf_cleartext>
<px> <py> <pxmin> <pxmax> <pymin> <pymax>



I wish I could devote some more time to this toy!

;^o



Chris M. Thomasson

unread,
Jul 19, 2015, 4:37:51 PM7/19/15
to
> "Chris M. Thomasson" wrote in message
> news:moh11p$a4f$1...@speranza.aioe.org...
[...]
> I am almost finished with a prototype.

FWIW: so far, the private key is limited to a location with
a formula hard coded as a squared Julia set. I need to add a
function parser, and a complex number library. I want fractional
powers in the sense of sqrt = pow(n, 0.5), well, I want a user
private key to be able to support pow(n, 0.618).

Richard Heathfield

unread,
Jul 19, 2015, 4:49:29 PM7/19/15
to
On 19/07/15 21:24, Chris M. Thomasson wrote:

<snip>

> I am almost finished with a prototype. However, the nature of
> the program raises some other questions about C wrt sending
> floating point across the wire. So far, I am just sending the
> fractional numbers as cleartext (e.g., “-0.5 0.5”, ect...) and
> using `atof()' to convert them on the receiving end. Humm.

That may well come back to bite you. Can you be certain that Alice will
be able to convey over the wire *exactly* the text interpretation of the
floating point number that will allow Bob to reconstruct the correct
floating point number from that text interpretation? For any Bob? (i.e.
for any floating point library, for any computer, for any OS).

Cryptographers are not above using floating point on occasion, but
generally avoid it for actual message processing, because the
possibilities for screwing it up are just too vast.

Chris M. Thomasson

unread,
Jul 20, 2015, 4:08:43 AM7/20/15
to
> "Richard Heathfield" wrote in message news:moh2dt$pun$1...@dont-email.me...

> > On 19/07/15 21:24, Chris M. Thomasson wrote:

<snip>

> > I am almost finished with a prototype. However, the nature of
> > the program raises some other questions about C wrt sending
> > floating point across the wire. So far, I am just sending the
> > fractional numbers as cleartext (e.g., “-0.5 0.5”, ect...) and
> > using `atof()' to convert them on the receiving end. Humm.

> That may well come back to bite you. Can you be certain that Alice will be
> able to convey over the wire *exactly* the text interpretation of the
> floating point number that will allow Bob to reconstruct the correct
> floating point number from that text interpretation? For any Bob? (i.e.
> for any floating point library, for any computer, for any OS).

IMVHO, this aspect of mutations wrt floating point from string
can possibly produce some fairly interesting errors. IMO, that
is basically show stopping for general use as-is, but is still
interesting to me. The resolution of the private key is proportional
to the size of the ceartext; a bigger text produces a fractal with
a higher resolution. FWIW, I tried moving the a public key around
its associated private key location by very small orbits and
started getting parts of smaller cleartexts (10-20 chars) around,
IIRC, 0.00000001 moments in either the real or imaginary axes. So,
if Bobs floating point is off by at least that amount, well, he
might get back some, a lot of, or total gibberish. Also, all of
this is at a particular, hard coded escape time iteration count
for now...


> Cryptographers are not above using floating point on occasion, but
> generally avoid it for actual message processing, because the
> possibilities for screwing it up are just too vast.

Yup. It sounds like juggling several running chainsaws. I wonder
if simply relying on a standard view of floating point ops (e.g.,
IEEE) might help out a bit? Then, say the program does not work
unless it has reliable access to the standard view of floating points
ops it depends on. Iterations of a fractal within a single standard,
should be okay.

Humm... I think I should post this over in comp.lang.c under a new
topic, “C Floating Fractal's”; what do you think?


Also, I am not going to give up on this shi% just because of the
nest of NASTY floating point issues. I will say use with EXTREME
caution, because the damn thing can decide to randomly bite/mutilate
decrypted ciphertext! Bob cannot make heads or tails out of what
Alice wrote. Yikes!

;^/



Say to use for a fun “academic” experience only?

;^o

Gordon Burditt

unread,
Jul 20, 2015, 5:03:03 AM7/20/15
to
> Yup. It sounds like juggling several running chainsaws. I wonder
> if simply relying on a standard view of floating point ops (e.g.,
> IEEE) might help out a bit? Then, say the program does not work
> unless it has reliable access to the standard view of floating points
> ops it depends on. Iterations of a fractal within a single standard,
> should be okay.

More recent versions of the C standard include printf/sprintf %a
conversion, which dumps double floating-point numbers in hex. By
default, you get enough precision to exactly represent the number.
sscanf has the reverse %a operation to get back the original value.

For example: -1.0/3.0 comes out as -0x1.5555555555555p-2 .

This should remove problems related to roundoff problems when the
number has an infinite decimal representation. If you also stick
to IEEE formats, you should get back the same bits. It might even
work between IEEE and non-IEEE if the number of mantissa bits is
the same and both formats have adequate exponent range.

%a is not intended to represent NaNs (there are potentially millions
of types, and I seem to get "nan" for all of them), and I'm not so
sure about denormals. I don't think this matters to your code,
though.

There can be multiple representations of the same number, for
example, 0x1.92p+1, 0x3.24p+0, 0x6.48p-1 and 0xc.9p-2 are equivalent.
(FreeBSD 8.0 and later document that the number before the hexadecimal
point is always 1, except for true zeroes).

Chris M. Thomasson

unread,
Jul 20, 2015, 4:09:52 PM7/20/15
to
>"Gordon Burditt" wrote in message
>news:dYOdnTh3M7LYJDHInZ2dnUU7->I2d...@posted.internetamerica...
[...]
>>(Chris M. Thomasson wrote...)
>> Yup. It sounds like juggling several running chainsaws. I wonder
>> if simply relying on a standard view of floating point ops (e.g.,
>> IEEE) might help out a bit? Then, say the program does not work
>> unless it has reliable access to the standard view of floating points
>> ops it depends on. Iterations of a fractal within a single standard,
>> should be okay.
[...]

> More recent versions of the C standard include printf/sprintf %a
> conversion, which dumps double floating-point numbers in hex. By
> default, you get enough precision to exactly represent the number.
> sscanf has the reverse %a operation to get back the original value.

> For example: -1.0/3.0 comes out as -0x1.5555555555555p-2 .

This should work. I happen to get:

“0x1.9e377ap+0” for
_________________________________________
{
double t = (1.0 + sqrt(5)) / 2.0;

printf("%f\r\n", t);
printf("%a\r\n", t);
}
_________________________________________


> This should remove problems related to roundoff problems when the
> number has an infinite decimal representation. If you also stick
> to IEEE formats, you should get back the same bits. It might even
> work between IEEE and non-IEEE if the number of mantissa bits is
> the same and both formats have adequate exponent range.

Sounds okay so far Gordon! :^)



> %a is not intended to represent NaNs (there are potentially millions
> of types, and I seem to get "nan" for all of them), and I'm not so
> sure about denormals. I don't think this matters to your code,
> though.

Humm... In fact, if the private key location and/or formula ends
up generating a bunch of NaNs, well, that would be a poor key to
use. IMHO, this should be detected before allowing a user to encrypt
any text at all!

;^o


> There can be multiple representations of the same number, for
> example, 0x1.92p+1, 0x3.24p+0, 0x6.48p-1 and 0xc.9p-2 are equivalent.
> (FreeBSD 8.0 and later document that the number before the hexadecimal
> point is always 1, except for true zeroes).

Thank you for the heads up about `%a'! It should work. Also, adhering
to a std representation of floating point ops should help as well.

I feel much better about this. :^)

Bruce Stephens

unread,
Jul 20, 2015, 5:10:31 PM7/20/15
to
On 20/07/2015 21:09, Chris M. Thomasson wrote:

> Thank you for the heads up about `%a'! It should work. Also, adhering
> to a std representation of floating point ops should help as well.

Presuming you're sending between two equivalent computers (x86_64, say),
just sending the bytes of the double ought to be fine (though
non-trivial to get right given modern C aliasing rules). Or just give up
and use some serialisation library such as Google's protocol buffers.
(Or everyone's favourite, ASN.1 with some encoding rules.)

>
> I feel much better about this. :^)

That's not a safe feeling when dealing with floating point, even when
everything's using IEEE (which it presumably is).

Chris M. Thomasson

unread,
Jul 20, 2015, 6:13:52 PM7/20/15
to
> > "Bruce Stephens" wrote in message > >
> > news:ZdydnRthc71Z_jDI...@brightview.co.uk...

> On 20/07/2015 21:09, Chris M. Thomasson wrote:

> Thank you for the heads up about `%a'! It should work. Also, adhering
> to a std representation of floating point ops should help as well.

> > Presuming you're sending between two equivalent computers (x86_64, say),
> > just sending the bytes of the double ought to be fine (though
> > non-trivial to get right given modern C aliasing rules). Or just give up
> > and use some serialisation library such as Google's protocol buffers.
> > (Or everyone's favourite, ASN.1 with some encoding rules.)

I think this should work. FWIW, for now, I want to investigate `%a'
and adhering to a std_float before I use third party libs.



> I feel much better about this. :^)

> > That's not a safe feeling when dealing with floating point, even when
> > everything's using IEEE (which it presumably is).

Yikes! :^o

I would sure hope that a std floating point package handles the `%a'
conversion in a "sane" manner! Also, the fractal iterations themselves
across different archs/os! ;^o

Bruce Stephens

unread,
Jul 20, 2015, 6:35:57 PM7/20/15
to
On 20/07/2015 23:13, Chris M. Thomasson wrote:
>> > "Bruce Stephens" wrote in message > > >

>> > That's not a safe feeling when dealing with floating point, even when
>> > everything's using IEEE (which it presumably is).
>
> Yikes! :^o
>
> I would sure hope that a std floating point package handles the `%a'
> conversion in a "sane" manner! Also, the fractal iterations themselves
> across different archs/os! ;^o

Sure. My concern (which may not apply) is that floating point is subtle.
Intermediate values in a calculation may have higher precision, for
example. You can rely on the results conforming to the relevant
standards, but that's about it. OTOH, IEEE 754 has made stuff much
saner and more consistent; things used to be much weirder.

Chris M. Thomasson

unread,
Jul 20, 2015, 10:39:54 PM7/20/15
to
>>"Chris M. Thomasson" wrote in message
>>news:mojrqs$gq3$1...@speranza.aioe.org...

>> > "Bruce Stephens" wrote in message > >
>> > news:ZdydnRthc71Z_jDI...@brightview.co.uk...

>> On 20/07/2015 21:09, Chris M. Thomasson wrote:

>> Thank you for the heads up about `%a'! It should work. Also, adhering
>> to a std representation of floating point ops should help as well.

>I think this should work.

[...]

I am having trouble getting `%a' to work with `sscanf'! DAMN!.

Richard Heathfield

unread,
Jul 21, 2015, 3:15:19 AM7/21/15
to
On 21/07/15 03:39, Chris M. Thomasson wrote:

<snip>

> I am having trouble getting `%a' to work with `sscanf'! DAMN!.


Surely that's a question for a group dealing with your compiler, not a
cryptography group?

Chris M. Thomasson

unread,
Jul 21, 2015, 3:21:23 AM7/21/15
to


> "Richard Heathfield" wrote in message news:mokrfb$tpc$1...@dont-email.me...

> > On 21/07/15 03:39, Chris M. Thomasson wrote:

<snip>

> > I am having trouble getting `%a' to work with `sscanf'! DAMN!.


> Surely that's a question for a group dealing with your compiler, not a
> cryptography group?


Yes it is. FWIW, I think there might be a way to send integer pairs that get
close enough to a given floating point...

Something like:
___________________________________
Here is a funny way to just send some integer pairs across:

sqrt(2) ~= 66922 / 47321
sqrt(3) ~= 70226 / 40545
sqrt(4) ~= 2 / 1
sqrt(5) ~= 51841 / 23184
sqrt(6) ~= 116412 / 47525
sqrt(7) ~= 149858 / 56641
pi ~= 208341 / 66317
gratio ~= 196418 / 121393 (golden ratio)
[...]
___________________________________


LOL!

;^)

Chris M. Thomasson

unread,
Jul 21, 2015, 4:25:50 AM7/21/15
to
> "Chris M. Thomasson" wrote in message
> news:mokrte$8c7$1...@speranza.aioe.org... [...]
___________________________________
>Here is a funny way to just send some integer pairs across:
>[...]
>pi ~= 208341 / 66317
>gratio ~= 196418 / 121393 (golden ratio)
>[...]
> ___________________________________

Here are a couple of more to add to the list:

sqrt(42) ~= 227137 / 35048
e ~= 271801 / 99990

lol ;^D

Chris M. Thomasson

unread,
Jul 21, 2015, 3:41:46 PM7/21/15
to
> "Chris M. Thomasson" wrote in message
> news:mokrte$8c7$1...@speranza.aioe.org...
[...]

Another pair of integers for PI:

PI ~= 312689 / 99532

real PI: 3.1415926535897932384626433832795

guess: 3.1415926536189366233975003014106

I should post the tries at mimicking a given fractional number with a pair
of
integers and a division op over at sci.math.

Now, that group seems to have the most kooks!

;^o

Paul Rubin

unread,
Jul 21, 2015, 6:56:35 PM7/21/15
to
"Chris M. Thomasson" <nos...@nospam.nospam> writes:
> Another pair of integers for PI:
> PI ~= 312689 / 99532
> I should post the tries at mimicking a given fractional number with a
> pair of integers and a division op over at sci.math.

Usually you do that by taking successive continued fraction
approximations to the number, and converting them to regular fractions.

Gordon Burditt

unread,
Jul 22, 2015, 2:33:43 AM7/22/15
to
>> More recent versions of the C standard include printf/sprintf %a
>> conversion, which dumps double floating-point numbers in hex. By
>> default, you get enough precision to exactly represent the number.
>> sscanf has the reverse %a operation to get back the original value.
>
>> For example: -1.0/3.0 comes out as -0x1.5555555555555p-2 .
>
> This should work. I happen to get:
>
> “0x1.9e377ap+0” for

I get:
0x1.9e3779b97f4a8p+0 vs. your
0x1.9e377ap+0

> _________________________________________
> {
> double t = (1.0 + sqrt(5)) / 2.0;
>
> printf("%f\r\n", t);
> printf("%a\r\n", t);
> }
> _________________________________________

WHOOPS! My statement about the default precision of %a is apparently
not correct (or someone implemented it wrong, which is just as bad
- the assumption about the precision doesn't work). Your implementation
is putting out 6 digits after the decimal point, rather than 13
which is appropriate for an IEEE double.

Maybe the portable format for an IEEE double is "%.13a" rather than
"%a".

My value with 13 digits after the decimal point rounded to 6 digits
after the decimal point matches yours. However, that might be
enough to mess up the decryption.

Ben Bacarisse

unread,
Jul 22, 2015, 5:54:01 AM7/22/15
to
"Chris M. Thomasson" <nos...@nospam.nospam> writes:
<snip>
> [...] I happen to get:
>
> “0x1.9e377ap+0” for
> _________________________________________
> {
> double t = (1.0 + sqrt(5)) / 2.0;
>
> printf("%f\r\n", t);
> printf("%a\r\n", t);
> }

That output is wrong. When no precision is specified, and the floating
point radix is a power of 2, %a should print enough digits to represent
the number exactly. When the radix is not a power of 2, %a should print
enough digits to distinguish between any two (non-NaN) floating point
numbers. What is this faulty C library? Maybe a bug report has been
filed against it.

The fact that your implementation is not doing the right thing means
that you can't rely on the default precision, but you could calculate a
precision (to use with %.*a), or you could decree that your program
needs IEEE 64-bit floating point and write out the bits in some
address-agnostic format or your own.

(BTW, there is no need for the \r in your output string.)

<snip>
--
Ben.

Richard Heathfield

unread,
Jul 22, 2015, 6:12:14 AM7/22/15
to
On 22/07/15 10:53, Ben Bacarisse wrote:
> "Chris M. Thomasson" <nos...@nospam.nospam> writes:
<snip>
>>
>> printf("%f\r\n", t);
>> printf("%a\r\n", t);
>> }
>
<snip>

>
> (BTW, there is no need for the \r in your output string.)

There could be such a need. For example, he could be writing a CGI
script on a *nix system. The HTTP protocol (IIRC) requires each line to
be terminated by a carriage return and a linefeed, which *nix I/O will
not provide by default.

Ben Bacarisse

unread,
Jul 22, 2015, 6:30:10 AM7/22/15
to
Richard Heathfield <r...@cpax.org.uk> writes:

> On 22/07/15 10:53, Ben Bacarisse wrote:
>> "Chris M. Thomasson" <nos...@nospam.nospam> writes:
> <snip>
>>>
>>> printf("%f\r\n", t);
>>> printf("%a\r\n", t);
>>> }
>>
> <snip>
>
>>
>> (BTW, there is no need for the \r in your output string.)
>
> There could be such a need. For example, he could be writing a CGI
> script on a *nix system. The HTTP protocol (IIRC) requires each line
> to be terminated by a carriage return and a linefeed, which *nix I/O
> will not provide by default.

Yes, of course. I meant that it's needed in this case, not that there
is never any need for it.

--
Ben.

Richard Heathfield

unread,
Jul 22, 2015, 6:38:07 AM7/22/15
to
On 22/07/15 11:30, Ben Bacarisse wrote:
> Richard Heathfield <r...@cpax.org.uk> writes:
>
>> On 22/07/15 10:53, Ben Bacarisse wrote:
>>> "Chris M. Thomasson" <nos...@nospam.nospam> writes:
>> <snip>
>>>>
>>>> printf("%f\r\n", t);
>>>> printf("%a\r\n", t);
>>>> }
>>>
>> <snip>
>>
>>>
>>> (BTW, there is no need for the \r in your output string.)
>>
>> There could be such a need. For example, he could be writing a CGI
>> script on a *nix system. The HTTP protocol (IIRC) requires each line
>> to be terminated by a carriage return and a linefeed, which *nix I/O
>> will not provide by default.
>
> Yes, of course. I meant that it's [not?] needed in this case, not that there
> is never any need for it.

Ah, I didn't realise he'd made that clear. It wasn't clear from where I
was standing.

Chris M. Thomasson

unread,
Jul 22, 2015, 3:49:01 PM7/22/15
to
> "Ben Bacarisse" wrote in message news:87lhe85...@bsb.me.uk...

> > "Chris M. Thomasson" <nos...@nospam.nospam> writes:
<snip>
> > [...] I happen to get:
> >
> > “0x1.9e377ap+0” for
> > _________________________________________
> > {
> > double t = (1.0 + sqrt(5)) / 2.0;
> >
> > printf("%f\r\n", t);
> > printf("%a\r\n", t);
> > }

> When the radix is not a power of 2, %a should print
> enough digits to distinguish between any two (non-NaN) floating point
> numbers. What is this faulty C library? Maybe a bug report has been
> filed against it.

This is for MSVC 12. Yikes!

Ben Bacarisse

unread,
Jul 22, 2015, 4:57:56 PM7/22/15
to
"Chris M. Thomasson" <nos...@nospam.nospam> writes:

>> "Ben Bacarisse" wrote in message news:87lhe85...@bsb.me.uk...
>
>> > "Chris M. Thomasson" <nos...@nospam.nospam> writes:
> <snip>
>> > [...] I happen to get:
>> >
>> > “0x1.9e377ap+0” for
>> > _________________________________________
>> > {
>> > double t = (1.0 + sqrt(5)) / 2.0;
>> >
>> > printf("%f\r\n", t);
>> > printf("%a\r\n", t);
>> > }
>
>> When the radix is not a power of 2, %a should print
>> enough digits to distinguish between any two (non-NaN) floating point
>> numbers.

[You snipped the part that most likely applies here: when no precision is
specified, and the floating point radix is a power of 2, %a should print
enough digits to represent the number exactly.]

>> What is this faulty C library? Maybe a bug report has been
>> filed against it.
>
> This is for MSVC 12. Yikes!

Ah. The online documentation for MSVC 2015 states that the default
precision for %a is 6 digits (which is what you are getting). It looks
like they do not follow the C99 (or C11) standard here.

--
Ben.

Chris M. Thomasson

unread,
Jul 22, 2015, 5:46:24 PM7/22/15
to
> "Paul Rubin" wrote in message
> news:87r3o1u...@jester.gateway.sonic.net...
This works like a charm, and is totally compatible wrt the way public keys
can
be represented in my toy cipher scheme.

I just might use integer pairs as "mock" floating point approximations. This
works
because the fractal cipher pad can be built using said approximations.

Why send floating point across the wire, when you can send integers?

Humm...

Chris M. Thomasson

unread,
Jul 31, 2015, 4:40:20 PM7/31/15
to
FWIW, here is the latest version that can encrypt any file:

http://pastebin.com/rQRXU5Mb

The command line for encryption is:

<flag> = 0 means encrypt
<flag> = 1 means decrypt

<program> <cleartext.file[in]> <ciphertext.file[out]> <flag:0> <xmin> <xmax>
<ymin> <ymax>


The command like for decryption is:

<program> <ciphertext.file[in]> <cleartext.file[out]> <flag:1> <xmin> <xmax>
<ymin> <ymax>


Running the program in encrypt mode gives a command line that
can decrypt the generated ciphertext. Here is output I get for
the same file I posted the freqency distributions for in the
ShuttlePads thread:
____________________________________________________________________
xmin = -0.50000000000
xmax = 0.50000000000
ymin = -0.50000000000
ymax = 0.50000000000
Opened the cleartext [in]! <C:\Users\Chris\Desktop\cleartext.txt>
Opened the ciphertext [out]! <C:\Users\Chris\Desktop\ciphertext.txt>
ffe_encrypt_first_pass processed: 703149 bytes

lost precision: 0.0000000000006
lost precision: 0.0000000000035
lost precision: 0.0000000000039
lost precision: 0.0000000000050
pub_xmin_scale = -0.39747846419
pub_xmax_scale = 1.22504427779
pub_ymin_scale = -0.37951654765
pub_ymax_scale = 0.67335246548

file size: 703149
fractal dims: 840 x 840

Passed at 703149 bytes!



Decrypt Command Line:

C:\Users\Chris\Desktop\ciphertext.txt
C:\Users\Chris\Desktop\cleartext.txt_dc 1
-0.39747846419 1.22504427779 -0.37951654765 0.67335246548


No Errors Reported!

Closed the ciphertext [out]! <C:\Users\Chris\Desktop\ciphertext.txt>
Closed the cleartext [in]! <C:\Users\Chris\Desktop\cleartext.txt>

Complete!


The decrypt command line is:

C:\Users\Chris\Desktop\ciphertext.txt
C:\Users\Chris\Desktop\cleartext.txt_dc 1 -0.39747846419
1.22504427779 -0.37951654765 0.67335246548


This code is in a fairly sad state. Its in flux. I need to check
sscanf for errors damn it!

But, at least you can see how this works and can make your own
analysis of the ciphertexts for any file.


Also, keep in mind that the private key is hard coded into the
program as:

{ -0.7, 0.25 }

So, every ciphertext will be based off a location into this
paticiular Julia set. I need to make the program able to allow
a user to provide their own actual formula and locations, iteration
counts, color monitors, ect... Lot of work to do!

Yikes!

;^o

Chris M. Thomasson

unread,
Jul 31, 2015, 4:43:44 PM7/31/15
to
> "Chris M. Thomasson" wrote in message
> news:mpgmfd$q02$1...@speranza.aioe.org...

> FWIW, here is the latest version that can encrypt any file:

> http://pastebin.com/rQRXU5Mb

Ummmm.... There is a damn getchar that I forgot to remove! So, the program
completes and hits a damn getchar. Well, you need to hit a key. Anyway,
I forgot to remove this. Sorry!!!!

;^o


Here is the code just in case PasteBin does not work for some reason:

(this one has the getchar commented out)
__________________________________________________________________
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <math.h>



/*-------------------------*/
#define CT_LB "\r\n"
#define CT_PREC "%.11lf"
#define CT_PREC_EPS "%.13lf"
#define CT_EPS 0.00000000001
#define CT_MIN(mp_0, mp_1) ((mp_0) < (mp_1) ? (mp_0) : (mp_1))

struct main_args
{
int argc;
char** argv;
};





/*-------------------------*/
double
double_to_string_to_double(
double n
){
double nn = 0.0;
double ndif = 0.0;

char nbuf[UCHAR_MAX + 1] = { '\0' };

sprintf(nbuf, CT_PREC, n);

sscanf(nbuf, "%lf", &nn);

ndif = fabs(n - nn);

/* `nn' has lost precision of `n'.*/
printf("lost precision: " CT_PREC_EPS CT_LB, ndif);

return nn;
}


double
string_to_double(
char const* nbuf
){
double n = 0.0;

sscanf(nbuf, "%lf", &n);

return n;
}


unsigned int
string_to_uint(
char const* nbuf
){
unsigned int n = 0;

sscanf(nbuf, "%u", &n);

return n;
}





/*-------------------------*/
#define SQ(mp_0) ((mp_0)*(mp_0))


struct complexn
{
double x;
double y;
};


#define COMPLEXN_SINIT() { 0.0, 0.0 }


struct complexn
complexn_add(
struct complexn self,
struct complexn n
){
struct complexn p = {
self.x + n.x,
self.y + n.y
};

return p;
}


struct complexn
complexn_mul(
struct complexn self,
struct complexn n
){
struct complexn p = {
self.x * n.x - self.y * n.y,
self.x * n.y + self.y * n.x
};

return p;
}




/*--------------------------*/
unsigned long
cantor_packing(
unsigned int n0,
unsigned int n1
){
unsigned long ret = 0.5 * (n0 + n1) * (n0 + n1 + 1) + n1;

return ret;
}





/*-------------------------*/
#define FFE_MARGS_NMIN 7
#define FFE_BUF_NMAX (1024 * 756)
#define FFE_ABETN (UCHAR_MAX + 1U)


struct ffe_buf
{
unsigned char buf[FFE_BUF_NMAX];
size_t bufsz;
};


struct ffe_abet
{
unsigned int abet[UCHAR_MAX + 1];
};


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

unsigned int
ffe_cplane_iterate(
struct complexn c,
struct complexn j,
unsigned int imax
){
unsigned int i = 0;
unsigned int imod = 0;

double dmin = 999999999999.0;

struct complexn z = c;
c = j; /* Julia Mode */

for (i = 0; i < imax; ++i)
{
double zd = 0.0;

z = complexn_mul(z, z);
z = complexn_add(z, c);

zd = SQ(z.x) + SQ(z.y);

dmin = CT_MIN(dmin, zd);

if (zd > 4.0)
{
imod = (unsigned int)((20371 + i) *
fabs(cos(i * i * dmin * 252307))) % FFE_ABETN;

return imod;
}
}

imod = (unsigned int)(40377 *
fabs(sin(dmin * 152307))) % FFE_ABETN;

return imod;
}




size_t
ffe_buf_read(
struct ffe_buf* const self,
FILE* const file
){
self->bufsz = fread(self->buf, 1, FFE_BUF_NMAX, file);

if (self->bufsz == FFE_BUF_NMAX)
{
return self->bufsz;
}

if (! ferror(file))
{
if (feof(file))
{
return self->bufsz;
}
}

printf("fread error!" CT_LB);

return 0;
}


size_t
ffe_buf_write(
struct ffe_buf const* const self,
FILE* const file
){
size_t bufsz = fwrite(self->buf, 1, self->bufsz, file);

if (bufsz == FFE_BUF_NMAX)
{
return bufsz;
}

if (! ferror(file))
{
return bufsz;
}

printf("fwrite error!" CT_LB);

return 0;
}





/*-------------------------*/

struct ffe_encrypt
{
struct ffe_cplane cplane; /* private key: plane */
struct complexn jplane; /* private key: Julia */
struct ffe_cplane pub_cplane; /* public key: plane */

struct ffe_buf* ebuf;
unsigned int flags;
size_t uwidth;
size_t fbytes;

FILE* fctext; /* clear text file */
FILE* fcipher; /* cipher text file */
};


int
ffe_encrypt_main_args_fctext_parse(
struct ffe_encrypt* const self,
struct main_args* const margs
){
if (margs->argc == FFE_MARGS_NMIN + 1)
{
unsigned int base = 1;

/* Try to open the cleartext [in] */
self->fctext = fopen(margs->argv[base], "rb");

if (self->fctext)
{
printf("Opened the cleartext [in]! <%s>" CT_LB, margs->argv[1]);

/* Try to open the ciphertext [out] */
self->fcipher = fopen(margs->argv[base + 1], "wb");

if (self->fcipher)
{
printf("Opened the ciphertext [out]! <%s>" CT_LB,
margs->argv[base + 1]);

return 1;
}

else
{
printf("Cannot open the ciphertext [out]! <%s>" CT_LB,
margs->argv[base + 1]);
}

fclose(self->fctext); /* check for errors!?!? */
}

printf("Cannot open the cleartext [int]! <%s>" CT_LB,
margs->argv[base]);
}

return 0;
}


int
ffe_encrypt_main_args_cplane_parse(
struct ffe_encrypt* const self,
struct main_args* const margs
){
if (margs->argc == FFE_MARGS_NMIN + 1)
{
/* Parse the complex plane dimensions (2d for now) */
unsigned int const icpbase = 3;

self->flags = string_to_uint(margs->argv[icpbase + 0]);

self->cplane.xmin = string_to_double(margs->argv[icpbase + 1]);
self->cplane.xmax = string_to_double(margs->argv[icpbase + 2]);

self->cplane.ymin = string_to_double(margs->argv[icpbase + 3]);
self->cplane.ymax = string_to_double(margs->argv[icpbase + 4]);

return 1;
}

return 0;
}


int
ffe_encrypt_parse(
struct ffe_encrypt* const self,
struct main_args* const margs
){
if (ffe_encrypt_main_args_cplane_parse(self, margs))
{
printf(
"xmin = " CT_PREC CT_LB "xmax = " CT_PREC CT_LB
"ymin = " CT_PREC CT_LB "ymax = " CT_PREC CT_LB,
self->cplane.xmin, self->cplane.xmax,
self->cplane.ymin, self->cplane.ymax
);

if (ffe_encrypt_main_args_fctext_parse(self, margs))
{
return 1;
}
}

return 0;
}


void
ffe_encrypt_first_pass(
struct ffe_encrypt* const self,
struct main_args const* const margs
){
self->fbytes = 0;
double cmean_sum = 0.0;
size_t cpack_msum = 0;
size_t cxor = 0;

for (;;)
{
size_t rbytes = ffe_buf_read(self->ebuf, self->fctext);

if (rbytes != 0)
{
size_t i = 0;

for (i = 0; i < rbytes; i += 2)
{
double cavg_0 = self->ebuf->buf[i] / ((double)UCHAR_MAX);
double cavg_1 = self->ebuf->buf[i + 1] /
((double)UCHAR_MAX);

cmean_sum = cmean_sum + cavg_0 + cavg_1;

cpack_msum =
(cpack_msum + cantor_packing(
self->ebuf->buf[i], self->ebuf->buf[i + 1])) %
1073741823;

cxor = cxor ^ self->ebuf->buf[i];
cxor = cxor ^ self->ebuf->buf[i + 1];
cxor = cxor ^ cpack_msum;

cmean_sum += ((cxor) % (UCHAR_MAX)) / ((double)UCHAR_MAX);
}

printf("ffe_encrypt_first_pass processed: %lu bytes" CT_LB,
(unsigned long)rbytes);

self->fbytes = self->fbytes + rbytes;

continue;
}

break;
}

printf(CT_LB);

{
/* build new location/offset (Public Key) into (Private Key) */
double cavg = cmean_sum / ((double)self->fbytes);
double cfmod = ((cavg + (cpack_msum / cxor)) * cxor) / ((cxor +
cpack_msum) % 1237);
cfmod = fmod(cfmod, 1.0);

/* try to avoid divide-by-zero conditions */
if (! cxor) cxor = 1;
if (! cpack_msum) cpack_msum = 1;

{
/* Generate Public Key Scale */
unsigned int sum_mod = 5;
double fmod_scale = ((1.0 + sqrt(5.0)) / 2.0) / 2.0;
double pub_xmin_scale = fmod(cavg * cfmod + (cxor /
(double)cpack_msum), fmod_scale);
double pub_xmax_scale = fmod((cavg * cfmod) * cxor + (cxor /
(double)cpack_msum), fmod_scale);
double pub_ymin_scale = fmod(cavg + cfmod + (cxor /
(double)cpack_msum), fmod_scale);
double pub_ymax_scale = fmod((cavg + cfmod) * cxor + (cxor /
(double)cpack_msum), fmod_scale);

pub_xmin_scale = pub_xmin_scale / ((cxor % 7) + 3);
pub_xmax_scale = pub_xmax_scale / (((cxor + cpack_msum) % 7) +
1);
pub_ymin_scale = pub_ymin_scale / (((cxor * cpack_msum) % 7) +
1);
pub_ymax_scale = pub_ymax_scale / (((((cxor * 3 + cpack_msum) +
7)) % 7) + 1);

pub_xmin_scale = (fmod(pub_xmin_scale + (cavg / 7), fmod_scale))
+ self->cplane.xmin;
pub_xmax_scale = (fmod(pub_xmax_scale + (cavg / 7), fmod_scale))
+ self->cplane.xmax;
pub_ymin_scale = (fmod(pub_ymin_scale + (cavg / 7), fmod_scale))
+ self->cplane.ymin;
pub_ymax_scale = (fmod(pub_ymax_scale + (cavg / 7), fmod_scale))
+ self->cplane.ymax;

cavg = fmod(cavg, fmod_scale);
cfmod = fmod(cfmod, fmod_scale);
cavg = 1.0 - fmod(cavg + cfmod, fmod_scale);

cpack_msum = cpack_msum * cavg + (cpack_msum % sum_mod) + 1;
cxor = cxor + (cxor % sum_mod) + 1;


self->pub_cplane.xmin =
double_to_string_to_double(pub_xmin_scale);
self->pub_cplane.xmax =
double_to_string_to_double(pub_xmax_scale);
self->pub_cplane.ymin =
double_to_string_to_double(pub_ymin_scale);
self->pub_cplane.ymax =
double_to_string_to_double(pub_ymax_scale);


/* decrypt setting 0 */
if (self->flags == 1)
{
self->pub_cplane = self->cplane;
}


printf("pub_xmin_scale = " CT_PREC CT_LB,
self->pub_cplane.xmin);
printf("pub_xmax_scale = " CT_PREC CT_LB,
self->pub_cplane.xmax);
printf("pub_ymin_scale = " CT_PREC CT_LB,
self->pub_cplane.ymin);
printf("pub_ymax_scale = " CT_PREC CT_LB,
self->pub_cplane.ymax);
}
}
}


int
ffe_encrypt_second_pass(
struct ffe_encrypt* const self,
struct main_args const* const margs
){
double xwidth = self->pub_cplane.xmax - self->pub_cplane.xmin;
double xheight = self->pub_cplane.ymax - self->pub_cplane.ymin;

double xstep = xwidth / self->uwidth;
double ystep = xheight / self->uwidth;

struct complexn c = COMPLEXN_SINIT();

{
size_t i = 0;

rewind(self->fctext);

printf(CT_LB);

for (i = 0; i < self->fbytes;)
{
size_t rbytes = ffe_buf_read(self->ebuf, self->fctext);

if (rbytes != 0)
{
size_t ic = 0;

for (ic = 0; ic < rbytes; ++ic, ++i)
{
/* Apply the cipher */
unsigned int imod = 0;
unsigned int cmod = self->ebuf->buf[ic];

unsigned int yi = i / self->uwidth;
unsigned int xi = i - yi * self->uwidth;

c.x = self->pub_cplane.xmin + xi * xstep;
c.y = self->pub_cplane.ymin + yi * ystep;

imod = ffe_cplane_iterate(c, self->jplane, 503);



/* encrypt/decrypt */
if (self->flags == 0)
{
imod = (imod + cmod) % FFE_ABETN;
}

else
{
int ec = cmod - imod;

if (ec < 0)
{
ec = cmod + FFE_ABETN;
imod = abs(imod - ec);
}

else
{
imod = ec;
}
}

/* commit cipher char to buffer */
self->ebuf->buf[ic] = imod;

if (! (i % 1000))
{
printf("i = %lu\r", (unsigned long)i);
}
}

/* write buffer to cipher file */
{
size_t wbytes = ffe_buf_write(self->ebuf,
self->fcipher);

if (wbytes < rbytes)
{
/* need to loop until the buffer is commited! */
printf("SINGLE WRITE IS FUC%%ED!" CT_LB);
getchar();
}
}

continue;
}

break;
}

if (i == self->fbytes)
{
printf("Passed at %lu bytes!" CT_LB CT_LB, (unsigned long)i);

return 1;
}
}

return 0;
}




/*-------------------------*/
int
main(
int argc,
char* argv[]
){
struct main_args self = { argc, argv };

{
struct ffe_buf ebuf = { { '\0' } };

struct ffe_encrypt fenc = {
{ -2.0, 2.0, -2.0, 2.0, }, /* private key: plane */

/* need to put this in the cmd line damn it! */
{ -0.7, 0.25 }, /* private key: Julia */

{ 0.0, 0.0, 0.0, 0.0, }, /* public key */
&ebuf,
0,
0,
0,
NULL,
NULL
};

if (ffe_encrypt_parse(&fenc, &self))
{
ffe_encrypt_first_pass(&fenc, &self);

printf(CT_LB);
printf("file size: %lu" CT_LB, (unsigned long)fenc.fbytes);

/* gain dims of fractal pad */
fenc.uwidth = (sqrt(fenc.fbytes) + 1.681) * 1.0;

printf("fractal dims: %lu x %lu" CT_LB,
(unsigned long)fenc.uwidth,
(unsigned long)fenc.uwidth
);

if (ffe_encrypt_second_pass(&fenc, &self))
{
if (fenc.flags == 0)
{
unsigned int base = 1;

printf(CT_LB CT_LB "Decrypt Command Line:" CT_LB CT_LB);
printf("%s %s_dc 1 " CT_PREC " " CT_PREC " " CT_PREC " "
CT_PREC CT_LB CT_LB,
self.argv[base + 1],
self.argv[base],
fenc.pub_cplane.xmin,
fenc.pub_cplane.xmax,
fenc.pub_cplane.ymin,
fenc.pub_cplane.ymax);
}

printf(CT_LB "No Errors Reported!" CT_LB CT_LB);
}

/* Check for ERRORS! */
fclose(fenc.fcipher);
printf("Closed the ciphertext [out]! <%s>" CT_LB, self.argv[2]);

fclose(fenc.fctext);
printf("Closed the cleartext [in]! <%s>" CT_LB, self.argv[1]);
}

else
{
printf("failed to parse!" CT_LB);
}
}

puts(CT_LB "Complete!" CT_LB);
/* getchar(); */

return 0;
}
__________________________________________________________________


Chris M. Thomasson

unread,
Jul 31, 2015, 4:46:52 PM7/31/15
to
One more thing... I am creating a single buffer on the stack the size of
`FFE_BUF_NMAX':
_________________________________________________
#define FFE_MARGS_NMIN 7
#define FFE_BUF_NMAX (1024 * 756)
#define FFE_ABETN (UCHAR_MAX + 1U)
_________________________________________________


This might be too much for your stack. So, if you get a stack overflow,
well, make
`FFE_BUF_NMAX'' smaller!


:^O

Chris M. Thomasson

unread,
Aug 16, 2015, 3:10:53 PM8/16/15
to
> "Chris M. Thomasson" wrote in message
> news:mnp683$pld$1...@speranza.aioe.org...

> > "Chris M. Thomasson" wrote in message
> > news:mnhpm5$fh9$1...@speranza.aioe.org... [...]

> This is cross-posted with comp.lang.c. I am hoping some of them take a
> look at the C program and perhaps find some bugs for me to fix! :^)

I am going to code my cryptoalgorithm in Javascript and put it up on a
website.

Then one will not have to compile the C code in order to play around with
the toy!

;^)

Chris M. Thomasson

unread,
Aug 19, 2015, 11:57:21 PM8/19/15
to
Humm... I am now thinking of a “fun/funny” way to try and crack
the fractal cipher. So, assume that Eve does not know the private
key/formula that Bob and Alice finally agreed to use. However,
she did mange to intercept all encrypted communications between
Bob and Alice. Eve has saved a copy of a fairly large amount of
ciphertext and all of the public keys/formulas that describe each
individual plaintext message. Eve then decides to write a suite of
GLSL shader programs that generate a bunch of fractal bitmaps using
the public keys as locations. Perhaps something like:

http://webpages.charter.net/appcore/fractal/webglx/ct_complex_field.html

She then uses the generated bitmaps to try and decipher the ciphertext.
Lets say that some bits and pieces of english words start to magically
appear. Well, then Eve just might be getting close to the formula, or
private key. Of course Eve would have to check different private keys/
formulas. Luckily for Eve, a lot of fractal fromulas are comprised of
embarrassingly parallel computations, so GPU's can crank em out pretty
darn fast. Unfortunately, the pre-alpha code as-is has a hard coded
private key as a power of 2 Julia set with a location of { -0.7, 0.25 }.
I am going to change this massive security hole in the next version.
Actually, I am thinking about using a fractal explorer program to generate
the private keys. Bob and Alice can explore some awesome renderings,
and pick a key for a cipher at the same time! Lol... ;^)

Anyway, once Eve starts to notice some engligh words appearing, well,
she can start to orbit the locations that produce them, perhaps in a
spiral formation. If she gets lucky, well, the orbits will notice more
and more words, and finally, crack it once she gets close enough to the
actual private key.. That that happens, Eve has a drink, and starts
reading Bob and Alice's correspondence!

;^o

Humm. It seems like once I allow the user to pass in a custom private
key, well, this method of cracking it might become more and more tedious.
Eve has to check god knows how many fractal formulas with god knows how
many custom locations, iteration counts, ect in order to get an orbit that
produces some actual plaintext. I was thinking, what if Bob and Alice
decided on a private key, and printed the rendering and hung it on a wall.
Imagine if Eve saw the rendering and recognized what fractal formula might
of created it. So, she tries it, and, well, time for another drink...

The interesting part is if Eve found a private key that works. However,
the private key is based on a completely different formula that happens
to work with each public key...

That would be very interesting indeed!

:^)

Chris M. Thomasson

unread,
Aug 20, 2015, 12:05:02 AM8/20/15
to
> "Chris M. Thomasson" wrote in message
> news:mr3j6o$9r9$1...@speranza.aioe.org...

[...]

> http://webpages.charter.net/appcore/fractal/webglx/ct_complex_field.html
[...]

FWIW, the link above is a little fractal explorer I wrote a while back in
Javascript and GLSL.

You can click on a part of the image, and it should zoom in.

;^)

Chris M. Thomasson

unread,
Aug 21, 2015, 3:53:30 PM8/21/15
to
> "Chris M. Thomasson" wrote in message
> news:mr3j6o$9r9$1...@speranza.aioe.org...

> Humm... I am now thinking of a “fun/funny” way to try and crack
> the fractal cipher.

[...]

Humm... Another thought:

I am wondering if cracking this thing can be way easier if
I heavily restrict the alphabet down to say 26 lowercase
characters. If one can crack it at 26 chars, then they might
be about to crack it at 30 chars. Well, if you can do 30,
then why not 40? There has to be a way to learn how to crack
this by restriction of the alphabet?

Any thoughts?

Chris M. Thomasson

unread,
Aug 21, 2015, 5:46:26 PM8/21/15
to
> "Chris M. Thomasson" wrote in message
> news:mpgmfd$q02$1...@speranza.aioe.org...

> FWIW, here is the latest version that can encrypt any file:

> http://pastebin.com/rQRXU5Mb

Quick question: Has anybody tried to compile this?

If so, how did it go?

:^o

MM

unread,
Aug 21, 2015, 5:58:42 PM8/21/15
to
It compiled.

When I ran it, I got "failed to parse", and there was no documentation
nearby that I could find (comments, CL options etc), so Ieft it.

M
--

Chris M. Thomasson

unread,
Aug 21, 2015, 6:07:08 PM8/21/15
to


> "MM" wrote in message
> news:241bde1c-cb26-4836...@googlegroups.com...

> > On Friday, 21 August 2015 22:46:26 UTC+1, Chris M. Thomasson wrote:
> > > "Chris M. Thomasson" wrote in message
> > > news:mpgmfd$q02$1...@speranza.aioe.org...
> >
> > > FWIW, here is the latest version that can encrypt any file:
> >
> > > http://pastebin.com/rQRXU5Mb
> >
> > Quick question: Has anybody tried to compile this?
> >
> > If so, how did it go?

> It compiled.

Great!


> When I ran it, I got "failed to parse", and there was no documentation
> nearby that I could find (comments, CL options etc), so Ieft it.

DAMN!

Okay. I am very sorry for the sorry state of the code. The command line arg
format for this is:

___________________________________________________________
The command line for encryption is:

<flag> = 0 means encrypt
<flag> = 1 means decrypt

<program> <cleartext.file[in]> <ciphertext.file[out]> <flag:0> <xmin> <xmax>
<ymin> <ymax>


The command like for decryption is:

<program> <ciphertext.file[in]> <cleartext.file[out]> <flag:1> <xmin> <xmax>
<ymin> <ymax>


Running the program in encrypt mode gives a command line that
can decrypt the generated ciphertext.
___________________________________________________________


I will include detailed instruction screen in the program wrt the next
release.
This should be within 1 or 2 days.

:^)


BTW, can you get it working on text files wrt the hyper crude instructions I
provided?

Sorry about all of this non-sense!


;^(

Chris M. Thomasson

unread,
Aug 21, 2015, 6:10:15 PM8/21/15
to
> "MM" wrote in message
> news:241bde1c-cb26-4836...@googlegroups.com...
[...]
> It compiled.
[...]


> ___________________________________________________________
> The command line for encryption is:

> <flag> = 0 means encrypt
> <flag> = 1 means decrypt

> <program> <cleartext.file[in]> <ciphertext.file[out]> <flag:0> <xmin>
> <xmax>
> <ymin> <ymax>

Example:

ffe C:\plaintext.txt C:\ciphertext.dat 0 -0.5 0.5 -0.5 0.5

Does something like that work? FWIW, here is the command line I am using in
my
test environment over on Windows 7:


ffe C:\Users\Chris\Desktop\ffe_dat\cleartext.txt
C:\Users\Chris\Desktop\ffe_dat\ciphertext.txt 0 -0.5 0.5 -0.5 0.5


I hope it starts working for you!

Ben Bacarisse

unread,
Aug 21, 2015, 8:29:31 PM8/21/15
to
"Chris M. Thomasson" <nos...@nospam.nospam> writes:

>> "Chris M. Thomasson" wrote in message
>> news:mpgmfd$q02$1...@speranza.aioe.org...
>
>> FWIW, here is the latest version that can encrypt any file:
>
>> http://pastebin.com/rQRXU5Mb
>
> Quick question: Has anybody tried to compile this?

No, but I did just now since you asked...

> If so, how did it go?

Not bad. A lot of conversion warnings (I use -Wconversion on all new
code just to get the lie of the land) but they may well be fine.

A warning about unused parameter (margs) and one about a missing
initialiser for bufsz in struct ffe_buf. Only that last one worried me.

Running the result says

failed to parse!

Complete!

which indicates something is wrong. Do I need some hardware-specific
flags? This is gcc version 4.9.2 on an i7-3520M CPU.

You are avoiding C's complex type but using some other C99 features.
That's not wrong, but a little odd.

--
Ben.

Chris M. Thomasson

unread,
Aug 21, 2015, 11:03:52 PM8/21/15
to
> "Ben Bacarisse" wrote in message news:8737zc8...@bsb.me.uk...

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

> >> "Chris M. Thomasson" wrote in message
> >> news:mpgmfd$q02$1...@speranza.aioe.org...
> >
> >> FWIW, here is the latest version that can encrypt any file:
> >
> >> http://pastebin.com/rQRXU5Mb
>
> > > Quick question: Has anybody tried to compile this?

> No, but I did just now since you asked...

> > If so, how did it go?

> Not bad. A lot of conversion warnings (I use -Wconversion on all new
> code just to get the lie of the land) but they may well be fine.

I think they are okay.


> A warning about unused parameter (margs) and one about a missing
> initialiser for bufsz in struct ffe_buf. Only that last one worried me.

I am not seeing those warnings. The unused parameter (margs)
almost has to be in the (ffe_encrypt_first_pass) and
(ffe_encrypt_second_pass) functions. As for the last one, well
could you please provide me with a line number? I am compiling
this with with Mingw 4.9.2 and the most recent MSVC. Unfortunately,
none of them give these warnings Ben!

Damn.



> Running the result says

> failed to parse!

> Complete!

> which indicates something is wrong. Do I need some hardware-specific
> flags? This is gcc version 4.9.2 on an i7-3520M CPU.

It will output “Complete!” regardless of how it exits, and this is
a flaw. The failed to parse error means that it did not get enough
command line arguments; it requires 7 of them. The command line syntax
for this is:



<flag> = 0 means encrypt

<flag> = 1 means decrypt



<program> <cleartext.file[in]> <ciphertext.file[out]> <flag:0>
<xmin> <xmax>
<ymin> <ymax>





The command like for decryption is:



<program> <ciphertext.file[in]> <cleartext.file[out]> <flag:1>
<xmin> <xmax>
<ymin> <ymax>




Running the program in encrypt mode gives a command line that
can decrypt the generated ciphertext.




Example for encryption:



ffe C:\plaintext.txt C:\ciphertext.dat 0 -0.5 0.5 -0.5 0.5



Does something like that work? FWIW, here is the command line
I am using in my test environment over on Windows 7:




ffe C:\Users\Chris\Desktop\ffe_dat\cleartext.txt
C:\Users\Chris\Desktop\ffe_dat\ciphertext.txt 0 -0.5 0.5 -0.5 0.5


The <xmin> <xmax> <ymin> <ymax> arguments define the 2d plane/
location in which the fractal will be processed.



> You are avoiding C's complex type but using some other C99 features.
> That's not wrong, but a little odd.

Yeah, I just could not get the standard built in complex type to
work for me for some reason.

Damn again.

;^o



Can you try creating a simple text file, called plaintext.txt,
and running the program with:

ffe <path_to_plaintext.txt> <path_to_ciphertext.dat> 0
-0.5 0.5 -0.5 0.5

something like:

ffe plaintext.txt ciphertext.dat 0 -0.5 0.5 -0.5 0.5

This will read the plaintext.txt file and create a new file
called ciphertext.dat. The program will the output a command
line that can be used to decrypt the ciphertext.dat.

Again, I am sorry for the sorry state of the crude, embryonic
version of the code!

;^o

Ben Bacarisse

unread,
Aug 22, 2015, 8:02:53 AM8/22/15
to
"Chris M. Thomasson" <nos...@nospam.nospam> writes:

>> "Ben Bacarisse" wrote in message news:8737zc8...@bsb.me.uk...
>
>>> "Chris M. Thomasson" <nos...@nospam.nospam> writes:
>
>> >> "Chris M. Thomasson" wrote in message
>> >> news:mpgmfd$q02$1...@speranza.aioe.org...
>> >
>> >> FWIW, here is the latest version that can encrypt any file:
>> >
>> >> http://pastebin.com/rQRXU5Mb
>>
>> > > Quick question: Has anybody tried to compile this?
>
>> No, but I did just now since you asked...
>
>> > If so, how did it go?
>
>> Not bad. A lot of conversion warnings (I use -Wconversion on all new
>> code just to get the lie of the land) but they may well be fine.
>
> I think they are okay.
>
>
>> A warning about unused parameter (margs) and one about a missing
>> initialiser for bufsz in struct ffe_buf. Only that last one worried me.
>
> I am not seeing those warnings. The unused parameter (margs)
> almost has to be in the (ffe_encrypt_first_pass) and
> (ffe_encrypt_second_pass) functions. As for the last one, well
> could you please provide me with a line number?

Line 588. I'd add a 0 just to clear it up:

struct ffe_buf ebuf = { { '\0' }, 0 };

In fact, I might write it

struct ffe_buf ebuf = { "", 0 };

but that's hardly important.

<snip>
>> Running the result says
>
>> failed to parse!
>
>> Complete!
>
>> which indicates something is wrong. Do I need some hardware-specific
>> flags? This is gcc version 4.9.2 on an i7-3520M CPU.
>
> It will output “Complete!” regardless of how it exits, and this is
> a flaw. The failed to parse error means that it did not get enough
> command line arguments; it requires 7 of them.
<snip>

> Example for encryption:
>
> ffe C:\plaintext.txt C:\ciphertext.dat 0 -0.5 0.5 -0.5 0.5
>
> Does something like that work?

Yes. I can do an encrypt/decrypt cycle fine.

The program's a bit wordy but that's probably a Windows/Unix culture
clash.

<snip>
> Again, I am sorry for the sorry state of the crude, embryonic
> version of the code!

It's fine, but a one-line "usage" message would have enabled me to test
it right away.

--
Ben.

MM

unread,
Aug 22, 2015, 8:19:11 AM8/22/15
to
On Saturday, 22 August 2015 13:02:53 UTC+1, Ben Bacarisse wrote:
> It's fine, but a one-line "usage" message would have enabled me to test
> it right away.

Please also put a link to some documentation explaining (using the maths!)
its theory of operation.

M
--

Ben Bacarisse

unread,
Aug 22, 2015, 9:29:09 AM8/22/15
to
You probably intended that to a reply to the cipher's author! I can't
comply!

--
Ben.

MM

unread,
Aug 22, 2015, 9:32:59 AM8/22/15
to
Er, yes, that was to the OP, sorry!

M
--

Chris M. Thomasson

unread,
Aug 22, 2015, 3:09:18 PM8/22/15
to
> "MM" wrote in message
> news:9a78c279-287b-4a8d...@googlegroups.com...
I have a lot of work to do! The math wrt fractals are luckily, fairly well
established:

http://www.fractal.org/Bewustzijns-Besturings-Model/Fractals-Useful-Beauty.htm

but I still need to explain them. However, I need to really
explain how I am using Cantor pairing in order to get an
"avalanche" effect:

https://en.wikipedia.org/wiki/Pairing_function#Cantor_pairing_function

Chris M. Thomasson

unread,
Aug 22, 2015, 9:15:43 PM8/22/15
to
> "Ben Bacarisse" wrote in message news:87wpwn7...@bsb.me.uk...
[...]
> > "Chris M. Thomasson" <nos...@nospam.nospam> writes:
[...]
> >> "Ben Bacarisse" wrote in message news:8737zc8...@bsb.me.uk...
[...]
> >> A warning about unused parameter (margs) and one about a missing
> >> initialiser for bufsz in struct ffe_buf. Only that last one worried
> >> me.
> >
> > I am not seeing those warnings. The unused parameter (margs)
> > almost has to be in the (ffe_encrypt_first_pass) and
> > (ffe_encrypt_second_pass) functions. As for the last one, well
> > could you please provide me with a line number?

> Line 588. I'd add a 0 just to clear it up:

> struct ffe_buf ebuf = { { '\0' }, 0 };

> In fact, I might write it

> struct ffe_buf ebuf = { "", 0 };

> but that's hardly important.


Thank you for helping me spot this. Also, I am very happy that
the pre-alpha code seems to be working for you.

Thanks again Ben.

:^D

Karl-Uwe Frank

unread,
Aug 23, 2015, 7:09:42 AM8/23/15
to
May I ask, if the generate keystream output of a cipher has very good
random quality, a frequency analysis on an encrypted text should not be
able to find any pattern, right?

Therefore if we test the keystream output of a given cipher algorithm on
huge amounts of data, like 2**33 bit and even more, with statistical
test like the book stack test and there are no significant spikes,
doesn't that imply at least that the cipher might be resistant against
bias finding and distinguishing attacks?

If so, should we still run frequency analysis on some encrypted texts?



On 17.07.15 00:34, Richard Heathfield wrote:
> 5 bytes won't give you anything like a reasonable assessment of your
> cipher's characteristics. Megabytes would be all right, but if you take,
> say, the complete text of Julius Caesar or Midsummer Night's Dream, and
> encrypt that. Then do the frequency analysis:
>
> 1) set up an array 256 elements in size, with every element set to 0 -
> e.g. unsigned long freq[256] = {0};
> 2) read each character of the ciphertext: ch = getc(fp);
> 3) record it: ++freq[ch];
> 4) when you're done, calculate the variance and thus the standard
> deviation:
>
> total = 0.0; /* this should be a double, obviously */
> for(i = 0; i < 256; i++)
> {
> total += freq[i];
> }
> mean = total / 256.0;
> variance = 0.0;
> for(i = 0; i < 256; i++)
> {
> double diff = freq[i] - mean;
> variance += diff * diff; /* squaring discards the sign information */
> }
> stddev = sqrt(variance);
>
> What would you expect the standard deviation to be if the input were a
> randomly-generated file of the same size? If your std dev is
> significantly greater than this, that's a problem.
>
>> 0b: How big of a “main alphabet”, akin to a color pallet wrt fractals,
>> should I use for a pseudo/fake one-time pad, or stream cipher?
>
> If you want to be able to encrypt any file, you should be able to deal
> with any byte value in the range 0-255.
>
> <snip>
>


--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---
0 new messages