Author Topic: Latest works.  (Read 5393 times)

0 Members and 1 Guest are viewing this topic.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Latest works.
« on: April 01, 2009 »


Recently I've taken a break from demo and game coding to work with some lower level data processing.

Currently I have a program that will convert a string into binary(trivial), hex(again trivial) and Morse Code.

I also just finished an encryption program based on my own method. (came to me in a dream of all things)

It might be cool to make a demo that has morse code as the words scroll. I still have to make a function that translates back but that will come with time.


String formatting
Code: [Select]
SuperStrict
Framework brl.retro
' Morse Code/ Binary / Hexidecimal conversion
' Ryan Burnside 2009

'use a case statement

' convert string to morse "dits and dahs" (lossy conversion for non printables)
Function string_to_morse:String(message:String)
' set letter to use for conversion of bytes to ascii
Local return_string:String = ""
message = message.ToLower()
For Local i:Int = 0 To message.Length - 1
' select the value
Select Chr(message[i])
Case "a"
return_string:+".- "
Case "b"
return_string:+"-... "
Case "c"
return_string:+"-.-. "
Case "d"
return_string:+"-.. "
Case "e"
return_string:+". "
Case "f"
return_string:+"..-. "
Case "g"
return_string:+"--. "
Case "h"
return_string:+".... "
Case "i"
return_string:+".. "
Case "j"
return_string:+".--- "
Case "k"
return_string:+"-.- "
Case "l"
return_string:+".-.. "
Case "m"
return_string:+"-- "
Case "n"
return_string:+"-. "
Case "o"
return_string:+"--- "
Case "p"
return_string:+".--. "
Case "q"
return_string:+"--.- "
Case "r"
return_string:+".-. "
Case "s"
return_string:+"... "
Case "t"
return_string:+"- "
Case "u"
return_string:+"..- "
Case "v"
return_string:+"...- "
Case "w"
return_string:+".-- "
Case "x"
return_string:+"-..- "
Case "y"
return_string:+"-.-- "
Case "z"
return_string:+"--.. "
Case "0"
return_string:+"----- "
Case "1"
return_string:+".---- "
Case "2"
return_string:+"..--- "
Case "3"
return_string:+"...-- "
Case "4"
return_string:+"....- "
Case "5"
return_string:+"..... "
Case "6"
return_string:+"-.... "
Case "7"
return_string:+"--... "
Case "8"
return_string:+"---.. "
Case "9"
return_string:+"----. "

End Select
Next
Return return_string
End Function

' convert morse "dits and dahs" to ascii
Function morse_to_string:String()

End Function

' convert string to hex codes (just the last two bits)
Function string_to_hexadecimal:String(message:String)
Local output:String
For Local i:Int = 0 To message.Length - 1
output:+String(Hex(message[i]))[6..]
Next
Return output
End Function

' convert hex to string
Function hexadecimal_to_string:String(message:String)
Local output:String
While message.Length > 0
output:+Chr(Int("$" + message[0..2]))
message = message[2..]
Wend
Return output
End Function

' convert string to binary 8 character sequences.
Function string_to_binary:String(message:String)
Local output:String
For Local i:Int = 0 To message.Length - 1
output:+String(Bin(message[i]))
Next
Return output
End Function

' convert binary to string
Function binary_to_string:String(message:String)
Local output:String
message = message.Replace(" ", "") ' get rid of spaces if present
While message.Length > 0
output:+Chr(Int("%" + message[0..8]))
message = message[8..]
Wend
Return output
End Function

Encryption Program (fairly strong I believe, I have ideas on how to make it stronger)
Code: [Select]
'this is a utility to encrypt files
'compile in console window mode
'encryption process
'1 ask the user for a key
'2 seed the random number generator with the key
'3 for each character add rand(0,255) to it

'decryption process
'1 ask the user for a key
'2 seed the random number generator with the key
'3 subtract rand(0,255) from each character

SuperStrict
Framework brl.StandardIO
Import BRL.Random
Import BRL.System

' ask for key value (not yet implimented we just use 0 for now)
Global key_value:Int = 0 ' this is for now
Print("Encryption Utility By Ryan Burnside (Pixel_Outlaw) 2009")
Print("Please specify an encryption or decryption key between -2147483648 And 2147483647 !")
key_value = Int(Input())
Print("REMEMBER: " + key_value +" this is the value for both encryption and decryption.")

' use the key_value to seed the random number generator for encryption
SeedRnd(key_value)

Print("Encrypt (E) or Decrypt(D)")
Global encrypt_file:String = Input().ToUpper()

While encrypt_file <> "E" And encrypt_file <> "D"
encrypt_file:String = Input().ToUpper()
Wend

Global directory:String = RequestFile("Please select a file..")
Global selected_file:TStream = ReadStream(directory)
Print("Please choose a new DIFFERENT name for the output file.")
Global directory_output:String = RequestFile("Please select a file..", "", True, directory.Replace(".", "_copy."))
Print("Conversion started. This may take some time. DO NOT EXIT.")

' ensure the files are valid
If directory = Null Or directory_output = Null
End
EndIf

Global output:TStream = WriteStream(directory_output)

'encrypt file
Function encrypt()
While Not Eof(selected_file)
output.WriteByte(selected_file.ReadByte() + Rand(0, 255))
Wend
selected_file.Close()
output.Close()
End Function

'decrypt file
Function decrypt()
While Not Eof(selected_file)
output.WriteByte(selected_file.ReadByte() - Rand(0, 255))
Wend
selected_file.Close()
output.Close()
End Function


Local t:Int=MilliSecs()
' select the proper option
If encrypt_file = "E"
encrypt()
EndIf

If encrypt_file = "D"
decrypt()
End If
Local f:Int=MilliSecs()-t
Print("Done.")
Notify("Conversion took: "+String(MilliSecs()-t) +" Milliseconds")


Yes my coding is sloppy but these are rapid prototyping secessions.


Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Latest works.
« Reply #1 on: April 02, 2009 »
Thanks for posting your code!

Some things to think about for your encryption algorithm:
The absolute maximum number of possible encryptions you can do is 2^32 or about 4billion because you 'only' have 32 bits of seed.  That might sound like a lot but consider that modern ciphers will use 1024 or more bits of key, each bit doubling the size of the problem.

The rng in blitzmax is probably not that good and wastes bits of your key - for instance if it uses the standard C runtime rng as described in the C Standard, then there are only 32768 possible keys.  With your decryption program I could generate all the possible decryptions of your file in just a few milliseconds!  If I had any idea what was in there, I could easily then write a program to find the ones I'm interested in, eg. those with plain text or those with jpg headers in them.

Also, if the rng uses a poor algorithm, then I can encrypt a lot of pre-known text (something like 'the quick brown fox' a hundred times, or a million zeroes) with your algorithm using different keys and do some statistical analysis on the resultant files and from that work out the fact that many rngs have very short repeating loops in the cycle of numbers that they generate.  From that it's reasonably easy to deduce the algorithm.

Another problem is each time you call the rng, you discard all but the bottom 8 bits (0-255) of the result.  Again if the rng algorithm is poor you might find those 8 bits are not that random.

A whole field of the research in cryptography is to build rngs with bigger spatial qualities and keys so they can't be analysed in this way.

Please don't take this as criticism, take it as food for thought to give you some ideas how even with the tools at hand you can quickly improve your program.  It's already easily good enough to deter any casual hackers!

:)

Nick, can you remember Parabellum's Blitz encryption code?

Jim
« Last Edit: April 02, 2009 by Jim »
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: Latest works.
« Reply #2 on: April 02, 2009 »
Thanks Jim. :)

I just needed something better than matching the old decoder ring style encryption. I'll take a look but the notion is just to make a file appear broken for my uses.

Is the method poor or is the number generator just weak? Or Both?
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Latest works.
« Reply #3 on: April 02, 2009 »
A lot of people put a lot of thought into cryptography for a couple of decades; just have a look at Wikipedia.
As Jim already pointed out, if someone has an idea what the deciphered data looks like, 2^32 possible combinations don't impede a modern machine for more than a few seconds.
But you could simply feed your algorithm from a couple of random-generators to increase the bit-count.
I suggest to create the key from an alphanumeric password; it's difficult to remember decimal numbers in the range of 2^1024 :)
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: Latest works.
« Reply #4 on: April 02, 2009 »
I had thought about using a alpha numeric key but the problem was still seeding the random number generator with it. Out of ignorance I didn't realize that the random number generator looped at some point.

Can anyone suggest a better generator? You both seem to be saying I need to get a better one. :)

Also, what is a good way to seed the generator with the password type hellfire mentioned?
Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: Latest works.
« Reply #5 on: April 02, 2009 »
I found this alternative rnd() function on the Bmax forum. It might be useful, not sure though:

http://blitzmax.com/codearcs/codearcs.php?code=1782

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Latest works.
« Reply #6 on: April 02, 2009 »
Quote
I didn't realize that the random number generator looped at some point.
It doesn't (at least not very soon) due to prime factors and overflow (see linear congruential generator).
Especially note:
Quote
If a linear congruential generator is seeded with a character and then iterated once, the result is a simple classical cipher called an affine cipher;
this cipher is easily broken by standard frequency analysis.
(you're essentially adding white noise to your data)

Quote
Can anyone suggest a better generator?
You don't need a "better" random generator.
The generator produces the same "random" sequence for the same initial seed value.
The problem is that this seed value is an integer, so there can only be 2^32 different random sequences and it's easy to simply try all of these in a brute-force-attempt and see if the decrypted data makes any sense.
This  of course assumes that the decryption-algorithm is know, but that's usually just a matter of setting some breakpoints in your favourite debugger.
Instead you want to use seed values which are as big as your key.
For performance reasons most implementations use native (32 bit) datatypes, though.

To create a numeric key from some alphanumeric password you can simply assume that each character represents an ascii-code (0..255). This isn't quite optimal since the characters below 33 and above 127 will be rarely used (and depend on language-specific codepages, too), so at least one bit of your key gets lost here.


« Last Edit: April 02, 2009 by hellfire »
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: Latest works.
« Reply #7 on: April 03, 2009 »
I understand the limitations of the int variable limit the number of possible keys. I thought of this when I wrote the limits in the prompt for a key.


It would be nice to have a generator that could take a seed value of any size. I think this would have to be something based on strings since strings have no size limitations for digits. I know that one can fake huge number calculations by custom writing string arithmetic functions.

A key between some absurd bounds like (-1,000,000,000,000,000,000,000 and -1,000,000,000,000,000,000,000) might be great. Could a random number generator be written to take huge string 'numbers' as parameters?

I just intended a tool to fool users into thinking the files were corrupt not necessarily encoded. So the tool has done its job, but now I'm interested in further discussion/modification.
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Latest works.
« Reply #8 on: April 03, 2009 »
Quote
Could a random number generator be written to take huge string 'numbers' as parameters?
Sure. You just have to implement functions for addition, multiplication and division (for modulus) on these strings and use the lcg from above.
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Latest works.
« Reply #9 on: April 03, 2009 »
1 billion trillion is not that absurd these days, what with public hand-outs to corporations. :P
It's around 70 bits.  2^1024 (common key size) = 10^308.  ie. 1 with over 300 zeroes after it!!
:D

Jim
« Last Edit: April 03, 2009 by Jim »
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Latest works.
« Reply #10 on: April 03, 2009 »
Quote
Nick, can you remember Parabellum's Blitz encryption code?

Bits of it Jim, that actually came about as a result of someone on the old blitzcoder forum trying to make an encryption program and Parabellum decided to crack it, he went about it pretty much in the way you said.

He used the program to encrypt some text and it was fairly easy to find the encryption ckey (this was a 32 bit key).

Parabellum then went on to make a much better 128 bit program of his own, it's used in the no 3d program I've just had another look at it and it is a bastard to crack, it is do-able but I guess it will take time and I am no cracker.

Something else that P_O might want to consider when making a key is to get a more random seed by analyzing his mouse movements over a period of time to generate a really strong key.

This is the way that programs like secway generate thier encryption keys.

Shockwave ^ Codigos
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: Latest works.
« Reply #11 on: April 05, 2009 »
Well finished the Morse code conversion.

Now to use your capslock light as a blinker and a sound to put out some Morse Code...

Code: [Select]

SuperStrict
Framework brl.retro
' Morse Code/ Binary / Hexidecimal conversion
' Ryan Burnside 2009
' convert string to morse "dits and dahs" (lossy conversion for non printables)
Function string_to_morse:String(message:String)
' set letter to use for conversion of bytes to ascii
Local return_string:String = ""
message = message.ToLower()

For Local i:Int = 0 To message.Length - 1
' select the value
Select Chr(message[i])
Case "a"
return_string:+".- "
Case "b"
return_string:+"-... "
Case "c"
return_string:+"-.-. "
Case "d"
return_string:+"-.. "
Case "e"
return_string:+". "
Case "f"
return_string:+"..-. "
Case "g"
return_string:+"--. "
Case "h"
return_string:+".... "
Case "i"
return_string:+".. "
Case "j"
return_string:+".--- "
Case "k"
return_string:+"-.- "
Case "l"
return_string:+".-.. "
Case "m"
return_string:+"-- "
Case "n"
return_string:+"-. "
Case "o"
return_string:+"--- "
Case "p"
return_string:+".--. "
Case "q"
return_string:+"--.- "
Case "r"
return_string:+".-. "
Case "s"
return_string:+"... "
Case "t"
return_string:+"- "
Case "u"
return_string:+"..- "
Case "v"
return_string:+"...- "
Case "w"
return_string:+".-- "
Case "x"
return_string:+"-..- "
Case "y"
return_string:+"-.-- "
Case "z"
return_string:+"--.. "
Case "0"
return_string:+"----- "
Case "1"
return_string:+".---- "
Case "2"
return_string:+"..--- "
Case "3"
return_string:+"...-- "
Case "4"
return_string:+"....- "
Case "5"
return_string:+"..... "
Case "6"
return_string:+"-.... "
Case "7"
return_string:+"--... "
Case "8"
return_string:+"---.. "
Case "9"
return_string:+"----. "

End Select
Next
Return return_string
End Function

' convert morse "dits and dahs" to ascii
Function morse_to_string:String(message:String)
Local return_string:String
Local word:String
Local last_char:Int = 0

While message.Contains(" ")

'trim out a Morse letter
last_char = message.Find(" ")
word = message[0..last_char + 1]
message = message[last_char + 1..]

Select word
Case ".- "
return_string:+"a"
Case "-... "
return_string:+"b"
Case "-.-. "
return_string:+"c"
Case "-.. "
return_string:+"d"
Case ". "
return_string:+"e"
Case "..-. "
return_string:+"f"
Case "--. "
return_string:+"g"
Case ".... "
return_string:+"h"
Case ".. "
return_string:+"i"
Case ".--- "
return_string:+"j"
Case "-.- "
return_string:+"k"
Case ".-.. "
return_string:+"l"
Case "-- "
return_string:+"m"
Case "-. "
return_string:+"n"
Case "--- "
return_string:+"o"
Case ".--. "
return_string:+"p"
Case "--.- "
return_string:+"q"
Case ".-. "
return_string:+"r"
Case "... "
return_string:+"s"
Case "- "
return_string:+"t"
Case "..- "
return_string:+"u"
Case "...- "
return_string:+"v"
Case ".-- "
return_string:+"w"
Case "-..- "
return_string:+"x"
Case "-.-- "
return_string:+"y"
Case "--.. "
return_string:+"z"
Case "----- "
return_string:+"0"
Case ".---- "
return_string:+"1"
Case "..--- "
return_string:+"2"
Case "...-- "
return_string:+"3"
Case "....- "
return_string:+"4"
Case "..... "
return_string:+"5"
Case "-.... "
return_string:+"6"
Case "--... "
return_string:+"7"
Case "---.. "
return_string:+"8"
Case "----. "
return_string:+"9"

End Select
Wend

Return return_string

End Function


' convert string to hex codes (just the last two bits)
Function string_to_hexadecimal:String(message:String)
Local output:String
For Local i:Int = 0 To message.Length - 1
output:+String(Hex(message[i]))[6..]
Next
Return output
End Function

' convert hex to string
Function hexadecimal_to_string:String(message:String)
Local output:String
While message.Length > 0
output:+Chr(Int("$" + message[0..2]))
message = message[2..]
Wend
Return output
End Function

' convert string to binary 8 character sequences.
Function string_to_binary:String(message:String)
Local output:String
For Local i:Int = 0 To message.Length - 1
output:+String(Bin(message[i]))
Next
Return output
End Function

' convert binary to string
Function binary_to_string:String(message:String)
Local output:String
message = message.Replace(" ", "") ' get rid of spaces if present
While message.Length > 0
output:+Chr(Int("%" + message[0..8]))
message = message[8..]
Wend
Return output
End Function
« Last Edit: April 05, 2009 by Pixel_Outlaw »
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Latest works.
« Reply #12 on: April 14, 2009 »
Thanks!

For fun, let's say this was moon-landing critical code  :kewl:  Every byte and every cycle counts.
How might you massively increase the speed of turning ascii characters into morse code?
(hint:  every ascii character has a unique code between 0 and 256, and that would make a very small lookup table).

http://thedailywtf.com/Articles/That-Kind-of-Security.aspx
I love The Daily WTF web site.  The host is a burke, but they get some great WTF coding things.  There's nothing wrong with this kind of security, despite the posts in this thread and the TDWTF posting.  The idea is to deter the average sticky beak.  The problem only comes when it's used to protect something that everyone wants to attack, like personal information, bank accounts, credit cards...OMG.

Jim
Challenge Trophies Won: