JEA1 Encryption (something I made yeah)

Share your advanced PureBasic knowledge/code with the community.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

JEA1 Encryption (something I made yeah)

Post by Joakim Christiansen »

Okay, so I spent the night making an improved (over my previous one) encryption algorithm.
I think this one should be very secure, at least I will challenge anyone here to make an algorithm to retrieve keys from encrypted files, good luck! :wink:

Code: Select all

;Joakim's Encryption Algorithm v1 (JEA1)
;
;I am no encryption expert but I tried to make an algorithm
;which is simple and will make fetching the key impossible.

EnableExplicit

Structure JEA1_state ;a structure to keep the current state
  encrypt.l ;wheter to encrypt or decrypt
  key.l ;pointer to key
  keyLen.l ;length of key
  randomSeed.l ;status of seed
  keyPos.l ;status of key pos
EndStructure
Procedure.l JEA1_random(seed.l) ;used for random number generation
  Protected rnd_w.l, rnd_z.l
  rnd_w = seed: rnd_z = seed+1 ;this can be experimented with
  rnd_z = 36969 * (rnd_z & 65535) + (rnd_z >> 16)
  rnd_w = 18000 * (rnd_w & 65535) + (rnd_w >> 16)
  ProcedureReturn (rnd_z << 16) + rnd_w;  /* 32-bit result */
EndProcedure
Procedure JEA1_start(*key,keyLen,encrypt,*state.JEA1_state) ;reset encryption state
  Protected keyPos
  *state\key = *key
  *state\keyLen = keyLen
  *state\encrypt = encrypt
  *state\randomSeed = 0
  For keyPos=0 To keyLen
    *state\randomSeed + JEA1_random(*state\randomSeed+PeekB(*key+keyPos)+1)
  Next
  *state\keyPos = 0
EndProcedure
Procedure JEA1_crypt(*mem,memLen.i,*state.JEA1_state) ;process memory block
  Protected memPos.i, randomByte.b, byteRead.b
  For memPos=0 To memLen-1
    byteRead   = PeekB(*mem+memPos)
    randomByte = JEA1_random(*state\randomSeed) >> 16
    PokeB(*mem+memPos,byteRead!randomByte)
    If *state\encrypt
      *state\randomSeed + JEA1_random(*state\randomSeed+PeekB(*state\key+*state\keyPos)+byteRead)
    Else
      *state\randomSeed + JEA1_random(*state\randomSeed+PeekB(*state\key+*state\keyPos)+byteRead!randomByte)
    EndIf
    *state\keyPos + 1
    If *state\keyPos > *state\keyLen: *state\keyPos = 0: EndIf
  Next
EndProcedure
Procedure JEA1_cryptFile(*key,keyLen,file$,encrypt=1,fileBufferSize=4096)
  Protected result=#True,file,filePos.q,fileLen.q,*fileBuffer,bytesRead,state.JEA1_state
  file = OpenFile(#PB_Any,file$)
  If file
    fileLen = Lof(file)
    If fileBufferSize > fileLen: fileBufferSize = fileLen: EndIf
    FileBuffersSize(file,0) ;we use our own buffer
    *fileBuffer = AllocateMemory(fileBufferSize)
    JEA1_start(*key,keyLen,encrypt,@state)
    Repeat
      bytesRead = ReadData(file,*fileBuffer,fileBufferSize) ;at end bytesRead <= fileBufferSize
      If bytesRead
        JEA1_crypt(*fileBuffer,bytesRead,@state)
        FileSeek(file,filePos) ;seek back
        WriteData(file,*fileBuffer,bytesRead)
        filePos + bytesRead
      Else
        result = #False: Break
      EndIf
    Until filePos = fileLen
    FreeMemory(*fileBuffer)
    CloseFile(file)
  Else
    result = #False
  EndIf
  ProcedureReturn result
EndProcedure

Code: Select all

;Example of use
Procedure JEA1_cryptMemory(password$,*memory,size,encrypt) ;here we use a string as key
  Protected state.JEA1_state
  JEA1_start(@password$,Len(password$),encrypt,@state)
  JEA1_crypt(*memory,size,@state)
EndProcedure
Procedure.s memoryToHex(address,length) ;returns a string containing the hex representation of a memory area
  Protected result$, i
  For i=0 To length-1
    result$ + RSet(Hex(PeekB(address+i),#PB_Byte),2,"0");+" "
  Next
  ProcedureReturn RTrim(result$)
EndProcedure

Define string1$ = "hello encryption world!"
Define string1Length = Len(string1$)
Define string2$ = "Hello encryption world!" ;notice the small difference?
Define string2Length = Len(string2$)

JEA1_cryptMemory("password",@string1$,string1Length,1)
Debug memoryToHex(@string1$,string1Length)+" / "+string1$

JEA1_cryptMemory("password",@string2$,string2Length,1)
Debug memoryToHex(@string2$,string2Length)+" / "+string2$ ;notice the big difference?

JEA1_cryptMemory("password",@string1$,string1Length,0)
Debug string1$

JEA1_cryptMemory("password",@string2$,string2Length,0)
Debug string2$

;Now something funny
JEA1_cryptMemory("password",@string1$,string1Length,0) ;See what I did?
Debug memoryToHex(@string1$,string1Length)+" / "+string1$

JEA1_cryptMemory("password",@string1$,string1Length,1) ;A hint: this was 0 before
Debug string2$

End

JEA1_cryptFile(@"hello world",11,OpenFileRequester("","","",0),1)
I like logic, hence I dislike humans but love computers.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: JEA1 Encryption (something I made yeah)

Post by Kwai chang caine »

Thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Re: JEA1 Encryption (something I made yeah)

Post by Rook Zimbabwe »

I can't see

OpenCryptRandom()

in the code... did I miss it? :mrgreen:

I am proficient in encryption and this is a nice idea!
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Re: JEA1 Encryption (something I made yeah)

Post by Joakim Christiansen »

Rook Zimbabwe wrote:I can't see

OpenCryptRandom()

in the code... did I miss it? :mrgreen:
Oh, didn't think about that one! (maybe you can implement it in your code)
But actually I like that it doesn't depend on any PureBasic command, this way it is very easy to port to any language! And with the random value being affected by both file content and key content I hope it is good enough.
EDIT: Actually CryptRandom() can not be used since we can not define a starting seed.
Rook Zimbabwe wrote:I am proficient in encryption and this is a nice idea!
Thanks :)
Last edited by Joakim Christiansen on Thu Mar 10, 2011 3:32 pm, edited 1 time in total.
I like logic, hence I dislike humans but love computers.
User avatar
dobro
Enthusiast
Enthusiast
Posts: 766
Joined: Sun Oct 31, 2004 10:54 am
Location: France
Contact:

Re: JEA1 Encryption (something I made yeah)

Post by dobro »

coding based on randomSeed + position in the text
I did it Aug. 26, 2007 ;) ...

look here :
http://www.purebasic.fr/french/viewtopi ... e&start=15

Code: Select all


;/ code par Dobro, modifié par Chris
;/ sur une base de AR-S
;/ algorythme de crypage axé sur le random !!


Enumeration
     #ARS
     #BT_Coder
     #BT_Decoder
     #Affiche
     #BT_Copie
     #Text_4
     #Message
     #Texte1
     #BT_Help
     #Titre
     #Font_Titre
     #spinGadget
     #BT_Ouvrir
     #BT_Sauver
EndEnumeration

Enumeration
     #PopUp
EndEnumeration

#CRLF = Chr (13)+ Chr (10)

Global Ex$

Declare ChargeFichier()
Declare CopyToClipboard()
Declare Decode()
Declare Encode()
Declare OpenWindow_ARS()
Declare SauveFichier()
Declare.s ReplaceFirst(String$, StringToFind$, StringToReplace$)

Procedure OpenWindow_ARS()
    hauteur_fenetre=600
    largeur_fenetre=600
     If OpenWindow ( #ARS , 150, 10, largeur_fenetre, hauteur_fenetre, "Dobro Crypt" , #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_TitleBar )
        
         If CreatePopupMenu ( #PopUp )
             MenuItem (0, "Copier" + Chr (9) + "Ctrl+C" )
             MenuItem (1, "Coller" + Chr (9) + "Ctrl+V" )
         EndIf
        
         If CreateGadgetList ( WindowID ( #ARS ))
             TextGadget ( #Titre , 5, 5, 360, 45, "Dobro Crypt" , #PB_Text_Border|#PB_Text_Center )
             TextGadget ( #Texte1 , 5, 55, 140, 15, "Message à coder / décoder" )
             EditorGadget ( #Message , 3, 68, largeur_fenetre-10, hauteur_fenetre-200)
             ButtonGadget ( #BT_Coder , 7, hauteur_fenetre-100, 90, 25, "Coder" )
             ButtonGadget ( #BT_Decoder , 102, hauteur_fenetre-100, 90, 25, "Decoder" )
             ButtonGadget ( #BT_Ouvrir , 400, hauteur_fenetre-100, 70, 20, "Ouvrir" )
             ButtonGadget ( #BT_Sauver , 500, hauteur_fenetre-100, 70, 20, "Sauver" )
             ButtonGadget ( #BT_Help , 400, 10, 15, 40, "?" )
             SpinGadget ( #spinGadget ,200,hauteur_fenetre-100,30, 25, 0, 9, #PB_Spin_ReadOnly|#PB_Spin_Numeric )
             SetGadgetText ( #spinGadget , "0" )
            
             ButtonGadget ( #BT_Copie , 6, hauteur_fenetre-50, 355, 20, "Copier le résultat dans le presse papier" )
             SetGadgetText ( #Message , "" )
            
             SetGadgetFont ( #Titre , LoadFont ( #Font_Titre , "Arial Black" , 22, 0))
         EndIf
        
        DC_Msg = GetDC_ ( GadgetID ( #Message ))
         SendMessage_ ( GadgetID ( #Message ), #EM_SETTARGETDEVICE , DC_Msg, GadgetWidth ( #Message )*14)
         ReleaseDC_ ( GadgetID ( #Message ), DC_Msg)
     EndIf
    
     ProcedureReturn WindowID ( #ARS )
EndProcedure

Procedure Encode()
     ClearClipboard ()
    de = GetGadgetState ( #spinGadget )
     RandomSeed (de)
    phrase$ = GetGadgetText ( #Message )
    chaine_codee$= ""
    
     For position_caractere = 1 To Len (phrase$)
        Caractere$ = Mid (phrase$, position_caractere, 1)
        rd = Random (5) + position_caractere
         For cc = 0 To 254
             If Caractere$ = Chr (cc)
                chaine_codee$ + Str (rd+cc) + Chr (255)
                Break 1
             EndIf
         Next cc
     Next position_caractere
     ClearGadgetItemList ( #Message )
     SetGadgetText ( #Message , chaine_codee$ + Str (de))
EndProcedure

Procedure Decode()
     ClearClipboard ()
    phrase$ = GetGadgetText ( #Message )
    de = Val ( Right (phrase$, 1)) ; attention ne lit que le dernier caractere !! : D donc une valeur entre 0 et 9
     RandomSeed (de)
    
    phrase$ = Left (phrase$, Len (phrase$) -1)
     For t = 1 To Len (phrase$)
        code = Val ( StringField (phrase$, t, Chr (255)))
        rd = Random (5) + t
        decode = code - rd
         If decode > 0
            phrase$ = ReplaceFirst(phrase$, Str (code), Chr (decode))
         EndIf
     Next t
    phrase$ = RemoveString (phrase$, Chr (255))
     ClearGadgetItemList ( #Message )
     SetGadgetText ( #Message , phrase$)
    
EndProcedure

Procedure.s ReplaceFirst(String$, StringToFind$, StringToReplace$)
     ; de Dri
    index = FindString (String$, StringToFind$, 1)
    length = Len (String$) - Len (StringToFind$) - index
    
     If index
        String$ = Left (String$, index-1) + StringToReplace$ + Right (String$, length+1)
     EndIf
    
     ProcedureReturn String$
EndProcedure

Procedure SauveFichier()
    T$ = SaveFileRequester ( "Sauver un fichier" , "" , "Fichiers supportés|*.crypt;*.txt|Fichiers cryptés|*.crypt|Fichiers texte|*.txt" , 0)
     If T$ : Fichier$ = T$ : T$ = "" : EndIf
    
     If GetExtensionPart (Fichier$) = ""
        Fichier$ + Ex$
     EndIf
    
     Debug Fichier$
    
    Contenu$ = GetGadgetText ( #Message ) : Size = Len (Contenu$)
    *Buffer = AllocateMemory (Size)
     PokeS (*Buffer, Contenu$)
    
     If CreateFile (0, Fichier$)
         WriteData (0, *Buffer, Size)
         CloseFile (0)
     EndIf
     FreeMemory (*Buffer)
EndProcedure

Procedure ChargeFichier()
    T$ = OpenFileRequester ( "Ouvrir un fichier" , "" , "Fichiers supportés|*.crypt;*.txt|Fichiers cryptés|*.crypt|Fichiers texte|*.txt" , 0)
     If T$ : Fichier$ = T$ : T$ = "" : EndIf
    
     If Fichier$
         If ReadFile (0, Fichier$)
            Size = Lof (0)
            *Buffer = AllocateMemory (Size +1)
             If *Buffer
                 ReadData (0, *Buffer, Size)
             EndIf
             CloseFile (0)
             SetGadgetText ( #Message , PeekS (*Buffer))
            
             FreeMemory (*Buffer)
            
         EndIf
     EndIf
EndProcedure

Procedure CopyToClipboard()
     If GetGadgetText ( #Message ) <> ""
         SetClipboardText ( GetGadgetText ( #Message ))
     EndIf
EndProcedure

If OpenWindow_ARS() = 0 : End : EndIf

Repeat
     Select WaitWindowEvent ()
         Case #WM_RBUTTONDOWN ;{
            x = WindowMouseX ( #ARS ) : Y = WindowMouseY ( #ARS )
            
             If x >= GadgetX ( #Message ) And x <= GadgetX ( #Message )+ GadgetWidth ( #Message )
                 If Y >= GadgetY ( #Message ) And Y <= GadgetY ( #Message )+ GadgetHeight ( #Message )
                     DisplayPopupMenu ( #PopUp , WindowID ( #ARS ))
                 EndIf
            EndIf ;}
            
         Case #PB_Event_Menu ;{
             Select EventMenu ()
                 Case 0 ; Copier
                     If GetGadgetText ( #Message ) <> ""
                         ClearClipboard () : SetClipboardText ( GetGadgetText ( #Message ))
                     EndIf
                    
                 Case 1 ; Coller
                     SetGadgetText ( #Message , "" ): SetGadgetText ( #Message , GetClipboardText ())
            EndSelect ;}
            
         Case #PB_Event_Gadget
             Select EventGadget ()
                 Case #BT_Coder
                    Ex$ = ".crypt"
                    Encode()
                    
                 Case #BT_Decoder
                    Ex$ = ".txt"
                    Decode()
                    
                 Case #BT_Ouvrir
                    ChargeFichier()
                    
                 Case #BT_Sauver
                    SauveFichier()
                    
                 Case #BT_Copie
                    CopyToClipboard()
                    
                 Case #BT_Help
                     MessageRequester ( "A propos" , "----------- Dobro Crypt v1 -----------" + Chr (10) + "" + Chr (10) + " Codé par Dobro." + Chr (10) + " Modifié par Chris." + Chr (10) + "" + Chr (10) + "" , #MB_OK )
             EndSelect
            
         Case #PB_Event_CloseWindow
            Quit = #True
     EndSelect
Until Quit

End 
Image
Windows 98/7/10 - PB 5.42
■ sites : http://michel.dobro.free.fr/
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Re: JEA1 Encryption (something I made yeah)

Post by Joakim Christiansen »

dobro wrote:coding based on randomSeed + position in the text
I did it Aug. 26, 2007 ;) ...

look here :
http://www.purebasic.fr/french/viewtopi ... e&start=15
Your code is valued too!
But your key is a single number (4 bytes) while my key can be data of any length so I am unsure why you used the blinking smiley face. :P
I like logic, hence I dislike humans but love computers.
User avatar
dobro
Enthusiast
Enthusiast
Posts: 766
Joined: Sun Oct 31, 2004 10:54 am
Location: France
Contact:

Re: JEA1 Encryption (something I made yeah)

Post by dobro »

Joakim Christiansen wrote:so I am unsure why you used the blinking smiley face. :P
just to say that the idea of using randomSeed () to encode a text came to me in 2007 :)

Your code is good :)

my key exchange, it would consider the position of the character in the text .. in addition to random ;)

the Reversing is almost impossible if we do not know this
you can not find after percentage of frequency of characters either :)
Image
Windows 98/7/10 - PB 5.42
■ sites : http://michel.dobro.free.fr/
freak
PureBasic Team
PureBasic Team
Posts: 5941
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: JEA1 Encryption (something I made yeah)

Post by freak »

Sorry, but such ciphers are not new, and they are generally considered not very secure.

This algorithm for example is vulnerable to a known-plaintext-attack:

Lets say the attacker knows this:
- the message in plain text
- the ciphertext of the message

Using the plain and cipher text, the attacker can recover the sequence of 'randomByte' values used in JEA1_crypt().

Lets further assume that the attacker knows the initial randomseed as calculated by JEA1_start(). In each iteration of the algorithm, the value of the next seed, and therefore the next 'randomByte' value depends on:
- the current seed
- the current plain text byte
- the current byte of the key

Since everything else is know, the key byte can be recovered from that. Multiple possibilities may need to be tried because several key values can produce the same next random byte. Step by step, the whole key can be recovered.

Of course, the initial seed depends on the key and is therefore not known to the attacker. But it is just a 32bit value. Testing all possibilities there is no problem with today's computers.
quidquid Latine dictum sit altum videtur
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Re: JEA1 Encryption (something I made yeah)

Post by Joakim Christiansen »

Yeah, if you know the content of the file and the algorithm I guess key extraction could be possible. :/
Thanks for the insight! (but still safe in cases where this is not a possibility)

Now I will make such an attack (cheating by knowing the initial seed) and see if I can somehow make that super hard! :D
I like logic, hence I dislike humans but love computers.
Post Reply