Crypting text.

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
E.K.Virtanen
Posts: 785
Joined: May 28, 2005 9:19
Location: Finland

Crypting text.

Post by E.K.Virtanen »

Dont have FB in this machine, but it should work. Anyway, the idea is clear. If you can program, you can uncrypt this with keyword :)

Code: Select all

rem Kristian Virtanen, 2011, krisu.virtanen@gmail.com

dim as string cryptMe, keyCode, temp, c
dim as integer i, ii

cryptMe = "Kristian Virtanen, 2011, krisu.virtanen@gmail.com"

rem keycode can be any lenght practically, makes this one nearly impossible to uncrypt without keycode.
keyCode = "Hello World"

i = 1
for ii = 1 to len(cryptMe)
	c = mid(cryptMe, ii, 1)
	temp = temp + str(asc(c) * asc(mid(keyCode, i, 1)))
	if ii < len(cryptMe) then temp = temp + "," : end if
	i = i + 1
	if i > len(keyCode) then
		i = 1
	endif
next ii

print "Crypted: ", temp
end
Output: (tested with yabasic which i have in this machine)
Crypted: 5400,11514,11340,12420,12876,3360,8439,12210,3648,9288,10500,
8208,11716,10476,11880,11211,3520,3828,3552,5700,5184,4900,3528,4444,
3456,11556,12654,3360,10005,12987,5244,12744,10500,8208,11716,10476,
11880,11211,3520,5568,11433,12426,10476,10500,7776,4646,10692,11988,12099
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Post by Richard »

E.K.Virtanen wrote:keycode can be any lenght practically, makes this one nearly impossible to uncrypt without keycode.
This is not a strong cipher. It generates double the volume of data bits than the plain text input so there is duplicated information that must always correlate. The fundamental problem with this cipher is that the factors of each letter in the key repeat with a fixed period in the enciphered output.

You do not need to first know the key used as it can easily be extracted from the voluminous enciphered code.

By performing a Kasiski analysis of the minimum prime factors sets in the cipher output you can extract the key length, then the probable key, and then generate a probable text. If this first probable solution is not perfect then the key can be very easily refined to fix the incorrect key letters.
E.K.Virtanen
Posts: 785
Joined: May 28, 2005 9:19
Location: Finland

Post by E.K.Virtanen »

So in other words; make it better? :)
fxm
Moderator
Posts: 12110
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Post by fxm »

E.K.Virtanen wrote:So in other words; make it better? :)
You can easily encrypt a bit more complicated, even by simplifying your program!

Code: Select all

rem Kristian Virtanen, 2011, krisu.virtanen@gmail.com

dim as string cryptMe, keyCode, temp, c
dim as integer ii

cryptMe = "Kristian Virtanen, 2011, krisu.virtanen@gmail.com"

rem keycode can be any lenght practically, makes this one nearly impossible to uncrypt without keycode.
keyCode = "Hello World"

for ii = 1 to len(cryptMe)
        c = mid(cryptMe, ii, 1)
        temp = temp + str(asc(c) * asc(mid(keyCode, int(rnd * len(keycode)) + 1, 1)))
        if ii < len(cryptMe) then temp = temp + "," : end if
next ii

print "Crypted: ", temp
end
 
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Post by Richard »

Unfortunately stepwise refinement just makes it a little harder each time, it simply takes longer messages or more traffic before the crack occurs. The fundamentals of this type of technique are weak in the presence of computers. Aim for a cipher that generates enciphered code the same length in bits as the message using a key of 64 to 256 independent bits.

The following demonstration cracker gets remarkably close to the correct key for such a short example message. Double the length of the message and it will find the 11 character key almost every time.

Code: Select all

'===================================================================
' Richard's demonstration key cracker for the EKV cipher
'===================================================================
Dim As String placode   ' plain text
Dim As String keyCode   ' key string
placode = "Kristian Virtanen, 2011, krisu.virtanen@gmail.coms"
keyCode = "Hello World"
'===================================================================
' Example Crypted Output: (tested with yabasic which i have in this machine)
'  5400, 11514, 11340, 12420, 12876,  3360,  8439, 12210,  3648,  9288
' 10500,  8208, 11716, 10476, 11880, 11211,  3520,  3828,  3552,  5700
'  5184,  4900,  3528,  4444,  3456, 11556, 12654,  3360, 10005, 12987
'  5244, 12744, 10500,  8208, 11716, 10476, 11880, 11211,  3520,  5568
' 11433, 12426, 10476, 10500,  7776,  4646, 10692, 11988, 12099
'===================================================================

Dim As Integer pcn = Len(placode)       ' length of message
Dim Shared As Integer encicode(Len(placode))   ' encrypted text

Print
Print "length of plain text is ="; pcn
Print "length of  key  text is ="; Len(keycode)
Print

Dim As Integer ti       ' plain text index
Dim As Integer ki = 0   ' key index

For ti = 0 To pcn - 1
    encicode(ti) = placode[ti] * keycode[ki]
    ki = ki + 1
    If ki = Len(keyCode) Then ki = 0
Next ti

For ti = 0 To pcn-1
    Print encicode(ti);
Next ti
Print : Print

'===================================================================
' demonstration of a crude key cracker
'===================================================================
' first the primes less than 256 are needed to factor the encicode
Const As Integer nprimes = 54
Dim Shared As Integer p, prime(1 To nprimes) =_
{   2,   3,   5,   7,  11,  13,  17,  19,  23,  29 _
,  31,  37,  41,  43,  47,  53,  59,  61,  67,  71 _ 
,  73,  79,  83,  89,  97, 101, 103, 113, 107, 109 _
, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173 _
, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229 _
, 233, 239, 241, 251}

'-------------------------------------------------------------------
' characters in the key with prime ascii codes are insecure
Print "Prime characters in the key are weak  ";
For p = 12 To 30
    Print Chr(prime(p), 32);
Next p
Print
Print

'-------------------------------------------------------------------
' factorize and save the encicode
Dim Shared As Integer factors(pcn, 1 To nprimes)
For ti = 0 To pcn-1
    Dim As Integer p = 1, i = encicode(ti)
    Do
        If (i Mod prime(p)) = 0 Then    ' divisible by a prime
            factors(ti, p) += 1     ' update record
            i = i \ prime(p)        ' try same again
        Else
            p = p + 1   ' advance to next bigger prime
        End If
    Loop Until (p > nprimes) Or (i = 1) ' done factorization
Next ti

'-------------------------------------------------------------------
' report the factorization for initial checking
For ti = 0 To pcn-1
    Print Using "###### = "; encicode(ti);
    For p = 1 To nprimes
        If factors(ti, p) <> 0 Then
            If factors(ti, p) = 1 Then
                Print Using "###   "; prime(p);
            Else
                Print Using "###^# "; prime(p); factors(ti, p);
            End If
        End If
    Next p
    Print
Next ti
Print

'-------------------------------------------------------------------
' do the keylength search
Dim As Integer minimum(1 To nprimes)
Dim As Integer keylength, i, j, k
Print "Length", "possible keys"
For keylength = 1 To pcn \ 2
    Print keylength,
    For i = 0 To keylength - 1  ' the first character of key
        For p = 1 To nprimes
            minimum(p) = 1000   ' initial guaranteed overestimate
        Next p
        For j = i To pcn - 1 Step keylength
            For p = 1 To nprimes
                If minimum(p) > factors(j, p) Then minimum(p) = factors(j, p)
            Next p 
        Next j
        ' now we have another possible key character for this length key
        j = 1
        For p = 1 To nprimes
            If minimum(p) > 0 Then j *= ( prime(p) ^ minimum(p) )
        Next p
        If (j < 32) Or (j > 126) Then j = 250 ' mask unprintables
        Print Chr(j);
    Next i
    Print
Next keylength

'-------------------------------------------------------------------
Sleep   ' end of crude cracker demo
'-------------------------------------------------------------------
For relatively long keys I would use a different technique based on the short random repetitions of characters in the plain text message.
E.K.Virtanen
Posts: 785
Joined: May 28, 2005 9:19
Location: Finland

Post by E.K.Virtanen »

hmm...Richard, you are guru ;)
E.K.Virtanen
Posts: 785
Joined: May 28, 2005 9:19
Location: Finland

Post by E.K.Virtanen »

How about this. Still dont have FB in this machine (having my wife laptop for now) but should work.

Code: Select all

rem Kristian Virtanen, 2011, krisu.virtanen@gmail.com
rem Code fixed after "first release"
declare function invert(text as string) as string
dim as string cryptMe, keyCode, temp, c
dim as integer i, ii

cryptMe = "Kristian Virtanen, 2011, krisu.virtanen@gmail.com"

rem keycode can be any lenght practically, makes this one nearly impossible to uncrypt without keycode.
keyCode = "Hello World"

i = 1
for ii = 1 to len(cryptMe)
        c = mid(cryptMe, ii, 1)
        temp = temp + str(asc(c) * asc(mid(keyCode, i, 1)))
        if ii < len(cryptMe) then temp = temp + "," : end if
        i = i + 1
        if i > len(keyCode) then
                i = 1
        endif
                if instr(keyCode, c) > 0 then
                        temp = invert(temp)
                end if
next ii

if mid(temp, 1, 1) <> "," then temp = "," + temp
if mid(temp, len(temp), 1) <> "," then temp = temp + ","
       
print "Crypted: ", temp
end
 

function invert(text as string) as string
        dim as integer i
        dim as string c

        for i = 1 to len(text)
                c = mid(text, i, 1) + c
        next i

        return c
end function
Last edited by E.K.Virtanen on May 29, 2011 21:15, edited 2 times in total.
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Post by Richard »

@ E.K.Virtanen.
When you design a cipher, make sure it compiles in FB before you post it. You must also write the decipherment code and test it thoroughly on several sample files. If every time you complicate your cipher algorithm I must prove it is still weak, then I will be wasting my time and you will never learn.

The best way to design a strong cipher is to read everything you can about the history of encryption and then at least try to break every cipher you can find. I started in 1978 by reading “The Codebreakers” by David Kahn. (Get a second hand copy for $2 + postage via the web.) If you do not know the history and understand the techniques of cryptanalysis, you will never learn from others past mistakes. Cryptanalysis is both good fun and a real challenge, but only if you approach it from a solid rational and analytic direction.
E.K.Virtanen
Posts: 785
Joined: May 28, 2005 9:19
Location: Finland

Post by E.K.Virtanen »

You dont have to prove anything. This is a programming-, not a code breaking forum. Codes presented in this topic are good enough to store high scores, map datas and such.

[edit]
I fixed code at my previous post. Sorry for not checking it first.
kiyotewolf
Posts: 1009
Joined: Oct 11, 2008 7:42
Location: ABQ, NM
Contact:

Post by kiyotewolf »

My crypt method is to BASE64, swap letters, then BASE64 back to the old container again.



:M

Gotta maintain upper & lowercase of letters you swap though.
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Post by Richard »

@ E.K.Virtanen. Thanks for editing your latest encryption.
I am not sure yet of the best way to decrypt it, even if the key is know.
Can you post a routine that regenerates the “cryptMe” string from your output “temp” string.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Post by dodicat »

deleted
Last edited by dodicat on Jun 11, 2011 22:35, edited 1 time in total.
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Post by Richard »

@ E.K.Virtanen. Your reversal cipher was excellent at hiding data. Even knowing the key made recovery quite uncertain as it needed a Viterbi algorithm to produce all probable plain texts.

Anyhow, moving the reversal from the end of the encryption loop to the beginning makes recovery certain as demonstrated in the following code.

Code: Select all

'===================================================================
' different functionality to original reversal, but now recoverable. 
'===================================================================
' reverses order of characters in a string
Function reverse(Byref temp As String) As String
    Dim As Integer i
    Dim As String s
    For i = 1 To Len(temp)
        s = Mid(temp, i, 1) + s
    Next i
    Return s
End Function

'===================================================================
Dim As String cryptMe, keyCode, temp, c
Dim As Integer i, ii

cryptMe = "Kristian Virtanen, 2011, krisu.virtanen@gmail.com"
keyCode = "Hello World"

temp = ","
i = 1
For ii = 1 To Len(cryptMe)
    c = Mid(cryptMe, ii, 1)
    ' conditional reverse() if latest character in text is also in key
    If Instr(keyCode, c) > 0 Then temp = reverse(temp)
    temp = temp + Str(Asc(c) * Asc(Mid(keyCode, i, 1))) + ","
    i = i + 1
    If i > Len(keyCode) Then i = 1
Next ii
Print
Print "Encrypted: ", temp
Print

'===================================================================
' given the keycode and temp(), recover the plain text
'===================================================================
' first find the number of elements in the text
Dim As Integer j, k, nmax = -1 ' -1 since comma at both ends of line
Dim As Integer comma = Asc(",")
For i = 0 To Len(temp) - 1
    If temp[i]= comma Then nmax += 1
Next i
Dim As String a(1 To nmax)  ' this will hold the number codes as strings
i = 0
Do  ' extract the strings into a()
    If temp[i] = comma Then
        j += 1
    Else
        a(j) += Chr(temp[i])
    End If
    i += 1
Loop While i < (Len(temp) - 1)

'-------------------------------------------------------------------
' show the strings
Print "Regurgitated  ,";
For i = 1 To nmax
    Print a(i); ",";
Next i
Print

'-------------------------------------------------------------------
dim as integer direction = +1, fwd = nmax, rev = 1
dim as string plain = ""

i = (nmax mod Len(keycode)) - 1   ' point at the last key character used
do
    if direction = 1 then 
        c = a(fwd)
        fwd -= 1
    else
        c = reverse( a(rev) )
        rev += 1
    end if
    c = chr( val(c) \ keycode[i] )
    plain = c + plain
    i -= 1  ' count backwards down through the keycode
    if i < 0 then i = len(keycode)-1
    if instr(keycode, c) > 0 Then direction = - direction
loop until fwd < rev

print
print " original = "; cryptMe
print
print "recovered = "; plain
print

'===================================================================
Sleep
'===================================================================
Post Reply