Advanced AES Crypter > Files &Strings &Termination Handling

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Advanced AES Crypter > Files &Strings &Termination Handling

Post by walbus »

Advanced universal AES256 OFB mode crypter for solving many problems and complicate things

With features you have never seen before on PB ! :shock:

A very big problem is ever the string termination with encrypted strings
To time i have never seen before a working solution for this problem !


This coder has a answer and can encrypt any strings without termination problems !

You can simple encrypt with this little coder :
Files, Data, Ascii and Unicode Strings

No enlargement for encrypted data, all has ever exactely the same length, before and after encryption
No separately encoder and decoder needed, only one coder for encrypting and decrypting
No Base64 or HEX converting needed for string encryption

The coder can encrypt all things also in it self, without changed length or unwanted terminations
Or, as sample, you can encrypt ascii strings in a unicode application

No padding necessary
All Data lengths available from one byte upwards
Counter for blockwise crypting
Encrypted data looking alike CBC mode encrypted data
Dual OFB mode AES256 encryption
Key as simple string available
Absolutely simple to use, good nature, no crashes, no malfunctions
Very little.

Hints :
Further down you find a more enhanced code for blockwise encryption with counter and progressbar
Also a special addon for file crypting with this coder, with automaticaly file integrity check and more

On my websites you found a complete suite with DLL/SO and RSA part

http://www.nachtoptik.de
http://www.quick-aes-256.de

A alterable bare SHA3 512 bit based special crypter you found here
http://www.purebasic.fr/english/viewtop ... 27&t=68742

Code: Select all

DeclareModule QAES_smart_universal_coder
  Declare QAES_smart_universal_coder(mode, *buffer_in.word, *buffer_out.word, bytes.q, key$, counter_key.q=0, counter_aes.q=0)
  UseSHA3Fingerprint()
EndDeclareModule

Module QAES_smart_universal_coder
  EnableExplicit  
  
  ; QAES AES256 OFB mode one or two stage special coder for all things - binarys - strings - text files
  ; This coder can handle automatic string termination for PB strings in compiler mode ASCII and UNICODE
  ; The coder works with all data lengths 
  ; With mode ASCII you can encrypt mixed data, string and binary - This ignore the encryption from zero bytes
  ; The coder go ever forward, a extra decoder is unnecessary !
  ; You cipher a file blockwise, set ever the current block number (consecutive) with a counter - Important !
  ; Author Werner Albus - www.nachtoptik.de - www.quick-aes-256.de
  ; No warranty whatsoever - Use at your own risk
  
  ; counter_key.q   : You cipher a file blockwise, set ever the current block number with this counter (consecutive numbering)
  ; counter_aes.q   : This counter chance same the counter_key the encryption absolutely
  ;                 : The counter_aes you can use as sample for setting a randomized startpoint for using with the file coder addon protection function
  ;                 : With used counters and salt you can personalize the coder, nobody can brute force a password from a unknown personalized coder
  ;                 : You can set the counter as quad, positive and negative
  ; key$            : You can use any strings as key
  ; *buffer_in      : Set the adress to the source data
  ; *buffer_out     : Set the adress to the destination data - Hint : It can also are the same place as the plain data
  ; mode            : Set mode=0 for binary files - Set mode=1 for ASCII strings - Set mode=2 for UNICODE strings 
  
  Procedure QAES_smart_universal_coder(mode, *buffer_in.word, *buffer_out.word, bytes.q, key$, counter_key.q=0, counter_aes.q=0)
    If Not bytes.q Or key$="" : ProcedureReturn 0  : EndIf
    
    #Salt$="t8690352cj2p1ch7fgw34u&=)?=)/%&§/&)=?(otmq09745$%()=)&%" ; Salt, you can change
    Protected.q i, swap_, rounds.q=bytes>>4
    Protected ii, iii, bytes_minus_x, stepp=SizeOf(character)<<1
    Protected *register_asc.ascii, *register.word, *buffer_in_quad.quad, *buffer_out_quad.quad
    Protected rest=bytes%16, bytes_minus_1=bytes-1
    Protected *buffer_in_asc.ascii, *buffer_out_asc.ascii
    Protected hash$=#Salt$+key$+Str(counter_key)+ReverseString(#Salt$)
    Static fixed_key_string${64}
    Static Dim register.q(3)
    
    fixed_key_string$=Fingerprint(@hash$, StringByteLength(hash$), #PB_Cipher_SHA3, 256) ; Create a key
    For ii = 0 To 31 : PokeA(@register(0)+ii, Val("$"+PeekS(@fixed_key_string$+iii, 2))) : iii+stepp : Next
    
    register(1)+counter_aes
    
    Macro go_1 ; One stage
      register(0)+1
      If Not AESEncoder(@register(0), @register(0), 32, @register(0), 256, 0, #PB_Cipher_ECB) : ProcedureReturn 0 : EndIf
      swap_=register(0) : register(0)=register(3) : register(3)=swap_ ; Never use here
      swap_=register(1) : register(1)=register(2) : register(2)=swap_ ; the PB swap function !
      
      ; register(2)+1 ; Activate for two stage crypting
      ; If Not AESEncoder(@register(0), @register(0), 32, @register(0), 256, 0, #PB_Cipher_ECB) : ProcedureReturn 0 : EndIf
    EndMacro
    
    If Not mode ; Binary mode
      *buffer_in_quad.quad=*buffer_in.word : *buffer_out_quad.quad=*buffer_out.word
      If bytes<16 ; Less 16 bytes
        *buffer_out_asc=*buffer_out_quad : *buffer_in_asc=*buffer_in_quad : *register_asc=@register(0)
        go_1
        For ii=0 To bytes_minus_1
          *buffer_out_asc\a=*buffer_in_asc\a ! *register_asc\a : *buffer_in_asc+1 : *buffer_out_asc+1 : *register_asc+1
        Next
        ProcedureReturn 1
      EndIf
      While i<rounds ; =>16 bytes
        go_1
        *buffer_out_quad\q=*buffer_in_quad\q ! register(0) : *buffer_in_quad+8 : *buffer_out_quad+8
        *buffer_out_quad\q=*buffer_in_quad\q ! register(1) : *buffer_in_quad+8 : *buffer_out_quad+8 : i+1
      Wend
      If rest
        *buffer_out_asc=*buffer_out_quad : *buffer_in_asc=*buffer_in_quad : *register_asc=@register(0)
        go_1
        For ii=0 To rest-1
          *buffer_out_asc\a=*buffer_in_asc\a ! *register_asc\a : *buffer_in_asc+1 : *buffer_out_asc+1 : *register_asc+1
        Next
      EndIf
    ElseIf mode=1
      bytes_minus_x=bytes-2
      *buffer_in_asc=*buffer_in : *buffer_out_asc=*buffer_out
      Repeat
        go_1 : *register_asc=@register(0)
        For ii=0 To 15
          If *buffer_in_asc\a And *buffer_in_asc\a ! *register_asc\a
            *buffer_out_asc\a=*buffer_in_asc\a ! *register_asc\a
          Else
            *buffer_out_asc\a=*buffer_in_asc\a
          EndIf
          If i>bytes_minus_x : Break 2 : EndIf
          *buffer_in_asc+1 : *buffer_out_asc+1 : *register_asc+1 : i+1
        Next ii
      ForEver
    Else ; mode=2
      bytes_minus_x=bytes-3
      Repeat
        go_1 : *register.word=@register(0)
        For ii=0 To 15 Step 2
          If *buffer_in\w And *buffer_in\w ! *register\w
            *buffer_out\w=*buffer_in\w ! *register\w
          Else
            *buffer_out\w=*buffer_in\w
          EndIf
          If i>bytes_minus_x : Break 2 : EndIf
          *buffer_in+2 : *buffer_out+2 : *register+2 : i+2
        Next ii
      ForEver
    EndIf
    ProcedureReturn 1
  EndProcedure
  
EndModule
UseModule QAES_smart_universal_coder

; ============== AES256 OFB mode special coder - For files, binarys, text and strings =================

;; counter_key.q   : You cipher a file blockwise, set ever the current block number (consecutive numbering) - This is important !
;;                 : You can set the counter as quad, positive and negative
;; key$            : You can use any strings as key
;; @string$        : Set the adress to the source data
;; @string_result$ : Set the adress to the destination data - Hint : It can also are the same place as the plain data
;; mode            : Set mode=0 for binary files - Set mode=1 for ASCII strings - Set mode=2 for UNICODE strings 
; 
; ; A sample : QAES_smart_universal_coder(mode_ascii_or_unicode, *source_data, *destination_data, length_of_data, key$, counter)
; 
; counter_key=123456
; string$="The quick brown fox jumps over the lazy dog"
; string$="A"+RSet("Z", 50, "x") ; Demo text string to encryption - For unicode, the length from 1 char = 2 bytes !
; key$="This is a simple key"
; ; mode=2 ; UNICODE
; mode=SizeOf(character)
; 
; ; Encoding
; QAES_smart_universal_coder(mode, @string$, @string$, StringByteLength(string$), key$, counter)
; Debug "QAES smart universal coder : Encoded : "+string$
; ShowMemoryViewer(@string$,StringByteLength(string$))
; Debug ""
; ; Decoding
; QAES_smart_universal_coder(mode, @string$, @string$, StringByteLength(string$), key$, counter)
; Debug "QAES smart text coder : Decoded : "+string$

;-----------------------------------
mode=SizeOf(character)

path$ = OpenFileRequester("Select a file to encrypting or decrypting !", "", "*.*", 0)
file=OpenFile(#PB_Any, path$)
If file
  *buffer=AllocateMemory(Lof(file))
  ReadData(file, *buffer, MemorySize(*buffer))
  QAES_smart_universal_coder(mode, *buffer, *buffer, MemorySize(*buffer), "Your key")
  FileSeek(file, 0) : WriteData(file, *buffer, MemorySize(*buffer)) : CloseFile(file)
EndIf

Last edited by walbus on Sat Jul 08, 2017 6:20 pm, edited 67 times in total.
WilliamL
Addict
Addict
Posts: 1215
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: Advanced AES coder -for binarys -strings -text -with sou

Post by WilliamL »

Tried your code and get this error:
Line 51: Modules can not be nested.
MacBook Pro-M1 (2021), Sonoma 14.3.1 (CLT 15.3), PB 6.10b7 M1
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Advanced AES coder -for binarys -strings -text -with sou

Post by walbus »

@WilliamL

Many thanks for your hint
Missmatch by creating and renaming the module for the forum

Please try now again :wink:

Regards Werner
WilliamL
Addict
Addict
Posts: 1215
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: Advanced AES coder -for binarys -strings -text -with sou

Post by WilliamL »

Works great! :D Encoding/decoding is automatic and it worked fine with a 50k text file.
MacBook Pro-M1 (2021), Sonoma 14.3.1 (CLT 15.3), PB 6.10b7 M1
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Advanced AES coder -for binarys -strings -text -with sou

Post by walbus »

@WilliamL

Nice to hear you are happy herewith :D
WilliamL
Addict
Addict
Posts: 1215
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: Advanced AES coder -for binarys -strings -text -with sou

Post by WilliamL »

Code: Select all

Protected hash$=key$+Str(counter)+"t8690352cj2p1ch7fgw34uotmq09745$%()=)&%" ; + Salt, you can change
Does this have to be of any minimum length or excluding any characters?
"Your key"
This must be where I put in my password.

All I need to do is write a little code to ask for the password then use the open file requester. If it's ciphered it will uncipher and if not it will cipher.
MacBook Pro-M1 (2021), Sonoma 14.3.1 (CLT 15.3), PB 6.10b7 M1
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Advanced AES coder -for binarys -strings -text -with sou

Post by walbus »

Hi,
the salt above you can make how ever you want
All characters are available
Change you only one character, the encryption changes absolutely
The lengt of the salt make not to short, mostly i use >30 characters, more is ever better

Also changing the counter, make the same
The counter change ever when you encrypt blockwise a file
Set the Blocknumbers as counter, this is important

"Your Key" is a sample password, you can use what ever you want, each length :wink:
WilliamL
Addict
Addict
Posts: 1215
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: Advanced AES coder -for binarys -strings -text -with sou

Post by WilliamL »

Set the Blocknumbers as counter, this is important
I don't understand what you mean. It appears that the counter just adds to the hash. I guess I will leave it at the default of zero and hope that doesn't cause problems.
MacBook Pro-M1 (2021), Sonoma 14.3.1 (CLT 15.3), PB 6.10b7 M1
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Advanced AES coder -for binarys -strings -text -with sou

Post by walbus »

Yep,
the counter works primary same a additional password

You must mostly not use the counter

The counter works with blockwise file copy (ever 4096 bytes , or other) , alike a IV
The counter prevent different blocks with the same content looking same encrypted
Last edited by walbus on Mon May 08, 2017 8:05 pm, edited 1 time in total.
User avatar
Blue
Addict
Addict
Posts: 864
Joined: Fri Oct 06, 2006 4:41 am
Location: Canada

Re: Advanced AES coder -for binarys -strings -text -with sou

Post by Blue »

Hello walbus
I hope you're still available to answer questions regarding this wonderful code.

First of all, let me express my total admiration for the code you shared here.
It's very efficient, impressively fast, and extremely solid and reliable.
Truly impressive.

My question to you :
is there a way to quickly identify, before crypting/decrypting a file, whether it's already encrypted or not ?
I have looked carefully at your code in the coding/decoding procedure, but I haven't been able to determine a point at which I'd know for sure the state of the file being worked on.
Last edited by Blue on Mon May 08, 2017 8:29 pm, edited 1 time in total.
"That's not a bug..." said the programmer. "it's a feature! "
"Oh! I see..." replied the blind man.
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Advanced AES coder -for binarys -strings -text -with sou

Post by walbus »

Hi Blue
Many thanks for your friendly words !

Yep, primary this is simple available for many situations, but not for all.

Firstly a little basics for this problem..

For strings you can add simple a row spaces to the strings end
As sample so : "This is my teststring"+Space(12)
Or so : "This is my teststring"+"cryptmagic58"
Now you can simple test, exist this on the end of your string, or not
Exist it, the string is decrypted
Exist it not, it is a encrypted string or a uncnown string

On files you can use this similar
Firstly encrypt the file
Define a little "magic" content, as sample a string or a defined quad
Encrypt now this little content separately
Merge this little defined content to the end of the encrypted file

For trying decrypting you can now ever read firstly this little content from the files end
Try decrypting this little content
Can you decrypt this, truncate it from the file and decrypt then the main file

A encrypted file has never a row same bytes

A very nice and strongly recommended way is :
Create a SHA3 hash from the encrypted binary or the string
Merge this hash as "magic" to your string or binarys end

Now go the same way for decrypting
Get firstly the hash
Create now again a hash from the main content
Compare now, is your created main content hash the same as the magic hash from the string or files end
On this way you become a unbreakable automatic file or string authentication
Nobody can now unnoticed change only one bit

The simplest way is add and removing automatically a hint in the file name
As sample so : test.txt [encrypted]

Regards Werner
Last edited by walbus on Thu Jun 01, 2017 10:33 am, edited 13 times in total.
User avatar
Blue
Addict
Addict
Posts: 864
Joined: Fri Oct 06, 2006 4:41 am
Location: Canada

Re: Advanced AES coder -for binarys -strings -text -with sou

Post by Blue »

Thank you for your quick reply.

Although i find it a bit hard decrypting your very personalized English :shock: (no offense intended :wink: ), I think i understand what you're suggesting. Simply put, tack some recognizable element to the end of the file being encrypted. Then, it becomes a simple matter of checking for the presence of that element to determine whether the file is encrypted or not. Yes, effective. very good thinking.

I was, of course, looking for some kind of signature element introduced by the encrypting process. I now realize, of course, that this is impossible, since it would defeat one of the beauties of your coder/decoder : its end product is always the same size, whether encrypted or not.

I'll get busy implementing your proposed solution.
Again, thank you.
"That's not a bug..." said the programmer. "it's a feature! "
"Oh! I see..." replied the blind man.
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Advanced AES Coder for Files &Strings &Termination Handl

Post by walbus »

d31 m05 y2017
New demo for blockwise crypting added

Codes updated, important speed up for binary mode

Blockwise crypting

Code: Select all

DeclareModule QAES_smart_universal_coder
  Declare QAES_smart_universal_coder(mode, *buffer_in.word, *buffer_out.word, bytes.q, key$, counter_key.q=0, counter_aes.q=0)
  UseSHA3Fingerprint()
EndDeclareModule

Module QAES_smart_universal_coder
  EnableExplicit  
  
  ; QAES AES256 OFB mode one or two stage special coder for all things - binarys - strings - text files
  ; This coder can handle automatic string termination for PB strings in compiler mode ASCII and UNICODE
  ; The coder works with all data lengths 
  ; With mode ASCII you can encrypt mixed data, string and binary - This ignore the encryption from zero bytes
  ; The coder go ever forward, a extra decoder is unnecessary !
  ; You cipher a file blockwise, set ever the current block number (consecutive) with a counter - Important !
  ; Author Werner Albus - www.nachtoptik.de - www.quick-aes-256.de
  ; No warranty whatsoever - Use at your own risk
  
  ; counter_key.q   : You cipher a file blockwise, set ever the current block number with this counter (consecutive numbering)
  ; counter_aes.q   : This counter chance same the counter_key the encryption absolutely
  ;                 : The counter_aes you can use as sample for setting a randomized startpoint for using with the file coder addon protection function
  ;                 : With used counters and salt you can personalize the coder, nobody can brute force a password from a unknown personalized coder
  ;                 : You can set the counter as quad, positive and negative
  ; key$            : You can use any strings as key
  ; *buffer_in      : Set the adress to the source data
  ; *buffer_out     : Set the adress to the destination data - Hint : It can also are the same place as the plain data
  ; mode            : Set mode=0 for binary files - Set mode=1 for ASCII strings - Set mode=2 for UNICODE strings 
  
  Procedure QAES_smart_universal_coder(mode, *buffer_in.word, *buffer_out.word, bytes.q, key$, counter_key.q=0, counter_aes.q=0)
    If Not bytes.q Or key$="" : ProcedureReturn 0  : EndIf
    
    #Salt$="t8690352cj2p1ch7fgw34u&=)?=)/%&§/&)=?(otmq09745$%()=)&%" ; Salt, you can change
    Protected.q i, swap_, rounds.q=bytes>>4
    Protected ii, iii, bytes_minus_x, stepp=SizeOf(character)<<1
    Protected *register_asc.ascii, *register.word, *buffer_in_quad.quad, *buffer_out_quad.quad
    Protected rest=bytes%16, bytes_minus_1=bytes-1
    Protected *buffer_in_asc.ascii, *buffer_out_asc.ascii
    Protected hash$=#Salt$+key$+Str(counter_key)+ReverseString(#Salt$)
    Static fixed_key_string${64}
    Static Dim register.q(3)
    
    fixed_key_string$=Fingerprint(@hash$, StringByteLength(hash$), #PB_Cipher_SHA3, 256) ; Create a key
    For ii = 0 To 31 : PokeA(@register(0)+ii, Val("$"+PeekS(@fixed_key_string$+iii, 2))) : iii+stepp : Next
    
    register(1)+counter_aes
    
    Macro go_1 ; One stage
      register(0)+1
      If Not AESEncoder(@register(0), @register(0), 32, @register(0), 256, 0, #PB_Cipher_ECB) : ProcedureReturn 0 : EndIf
      swap_=register(0) : register(0)=register(3) : register(3)=swap_ ; Never use here
      swap_=register(1) : register(1)=register(2) : register(2)=swap_ ; the PB swap function !
      
      ; register(2)+1 ; Activate for two stage crypting
      ; If Not AESEncoder(@register(0), @register(0), 32, @register(0), 256, 0, #PB_Cipher_ECB) : ProcedureReturn 0 : EndIf
    EndMacro
    
    If Not mode ; Binary mode
      *buffer_in_quad.quad=*buffer_in.word : *buffer_out_quad.quad=*buffer_out.word
      If bytes<16 ; Less 16 bytes
        *buffer_out_asc=*buffer_out_quad : *buffer_in_asc=*buffer_in_quad : *register_asc=@register(0)
        go_1
        For ii=0 To bytes_minus_1
          *buffer_out_asc\a=*buffer_in_asc\a ! *register_asc\a : *buffer_in_asc+1 : *buffer_out_asc+1 : *register_asc+1
        Next
        ProcedureReturn 1
      EndIf
      While i<rounds ; =>16 bytes
        go_1
        *buffer_out_quad\q=*buffer_in_quad\q ! register(0) : *buffer_in_quad+8 : *buffer_out_quad+8
        *buffer_out_quad\q=*buffer_in_quad\q ! register(1) : *buffer_in_quad+8 : *buffer_out_quad+8 : i+1
      Wend
      If rest
        *buffer_out_asc=*buffer_out_quad : *buffer_in_asc=*buffer_in_quad : *register_asc=@register(0)
        go_1
        For ii=0 To rest-1
          *buffer_out_asc\a=*buffer_in_asc\a ! *register_asc\a : *buffer_in_asc+1 : *buffer_out_asc+1 : *register_asc+1
        Next
      EndIf
    ElseIf mode=1
      bytes_minus_x=bytes-2
      *buffer_in_asc=*buffer_in : *buffer_out_asc=*buffer_out
      Repeat
        go_1 : *register_asc=@register(0)
        For ii=0 To 15
          If *buffer_in_asc\a And *buffer_in_asc\a ! *register_asc\a
            *buffer_out_asc\a=*buffer_in_asc\a ! *register_asc\a
          Else
            *buffer_out_asc\a=*buffer_in_asc\a
          EndIf
          If i>bytes_minus_x : Break 2 : EndIf
          *buffer_in_asc+1 : *buffer_out_asc+1 : *register_asc+1 : i+1
        Next ii
      ForEver
    Else ; mode=2
      bytes_minus_x=bytes-3
      Repeat
        go_1 : *register.word=@register(0)
        For ii=0 To 15 Step 2
          If *buffer_in\w And *buffer_in\w ! *register\w
            *buffer_out\w=*buffer_in\w ! *register\w
          Else
            *buffer_out\w=*buffer_in\w
          EndIf
          If i>bytes_minus_x : Break 2 : EndIf
          *buffer_in+2 : *buffer_out+2 : *register+2 : i+2
        Next ii
      ForEver
    EndIf
    ProcedureReturn 1
  EndProcedure
  
EndModule
UseModule QAES_smart_universal_coder

EnableExplicit

;CompilerIf #PB_Compiler_Debugger : MessageRequester("Debugger", "Please deactivate firstly the debugger !") : End : CompilerEndIf

;- Crypt a file blockwise in it self ----------------------------------
Define file, file_size, readed, writen, block_size, window_event, *buffer

Define mode=0    ; Binary mode
Define counter_key=0 ; You can set a counter how ever you want, also negative

Define path$=OpenFileRequester("Select a file to encrypting or decrypting !", "", "*.*", 0)
If path$="" : End : EndIf
OpenWindow(1, 0, 0, 300, 50, "QAES crypter works - please wait", #PB_Window_ScreenCentered)
AddWindowTimer(1, 1, 300)
ProgressBarGadget(1, 10, 10, 280, 30, 0, 100, #PB_ProgressBar_Smooth)
file=OpenFile(#PB_Any, path$)

If file
  file_size=Lof(file) : block_size=4096*4 : FileBuffersSize(file, block_size ) : *buffer=AllocateMemory(block_size)
  Repeat
    readed=ReadData(file, *buffer, block_size)
    QAES_smart_universal_coder(mode, *buffer, *buffer, block_size, "Your key", counter_key) ; QAES crypter - Binary mode
    FileSeek(file, -readed, #PB_Relative) : writen+WriteData(file, *buffer, readed)
    window_event=WaitWindowEvent(1)
    If window_event=#PB_Event_Timer And EventTimer()=1
      SetGadgetState(1, 100*writen/file_size)
    EndIf
    counter_key+1
  Until Not readed
  CloseFile(file) : FreeMemory(*buffer)
  If writen<>file_size : MessageRequester("ERROR", "Writen fails"+#LFCR$+#LFCR$+"Coded Bytes : "+Str(writen)) : EndIf
  #crypt_extender$=" [encrypted]"
  If Right(path$, Len(#crypt_extender$))=#crypt_extender$
    RenameFile(path$, Left(path$, Len(path$)-Len(#crypt_extender$)))
  Else
    RenameFile(path$, path$+#crypt_extender$)
  EndIf
EndIf

Last edited by walbus on Wed Jun 21, 2017 7:23 pm, edited 14 times in total.
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Advanced AES Coder for Files &Strings &Termination Handl

Post by walbus »

This is a advanced file crypter addon-module for the QAES_smart_universal_coder

This is a complete solution for simplest file crypting all over :wink:

With full automatic and unbreakable file integrity check
Various files with the same content are encrypted ever completely differently

Author Werner Albus - http://www.nachtoptik.de - http://www.quick-aes-256.de
No warranty whatsoever - Use at your own risk


Hints:
The QAES_smart_universal_coder is so small that I have added it above the file crypter addon-module
So this code here is directly executable !

For encryption with nearly endless features use QUICK-AES-256, thread here :
http://www.purebasic.fr/english/viewtop ... 27&t=60507

Code with special file crypter addon

Code: Select all

DeclareModule QAES_smart_universal_coder
  Declare QAES_smart_universal_coder(mode, *buffer_in.word, *buffer_out.word, bytes.q, key$, counter_key.q=0, counter_aes.q=0)
  UseSHA3Fingerprint()
EndDeclareModule

Module QAES_smart_universal_coder
  EnableExplicit  
  
  ; QAES AES256 OFB mode one or two stage special coder for all things - binarys - strings - text files
  ; This coder can handle automatic string termination for PB strings in compiler mode ASCII and UNICODE
  ; The coder works with all data lengths 
  ; With mode ASCII you can encrypt mixed data, string and binary - This ignore the encryption from zero bytes
  ; The coder go ever forward, a extra decoder is unnecessary !
  ; You cipher a file blockwise, set ever the current block number (consecutive) with a counter - Important !
  ; Author Werner Albus - www.nachtoptik.de - www.quick-aes-256.de
  ; No warranty whatsoever - Use at your own risk
  
  ; counter_key.q   : You cipher a file blockwise, set ever the current block number with this counter (consecutive numbering)
  ; counter_aes.q   : This counter chance same the counter_key the encryption absolutely
  ;                 : The counter_aes you can use as sample for setting a randomized startpoint for using with the file coder addon protection function
  ;                 : With used counters and salt you can personalize the coder, nobody can brute force a password from a unknown personalized coder
  ;                 : You can set the counter as quad, positive and negative
  ; key$            : You can use any strings as key
  ; *buffer_in      : Set the adress to the source data
  ; *buffer_out     : Set the adress to the destination data - Hint : It can also are the same place as the plain data
  ; mode            : Set mode=0 for binary files - Set mode=1 for ASCII strings - Set mode=2 for UNICODE strings 
  
  Procedure QAES_smart_universal_coder(mode, *buffer_in.word, *buffer_out.word, bytes.q, key$, counter_key.q=0, counter_aes.q=0)
    If Not bytes.q Or key$="" : ProcedureReturn 0  : EndIf
    
    #Salt$="t8690352cj2p1ch7fgw34u&=)?=)/%&§/&)=?(otmq09745$%()=)&%" ; Salt, you can change
    Protected.q i, swap_, rounds.q=bytes>>4
    Protected ii, iii, bytes_minus_x, stepp=SizeOf(character)<<1
    Protected *register_asc.ascii, *register.word, *buffer_in_quad.quad, *buffer_out_quad.quad
    Protected rest=bytes%16, bytes_minus_1=bytes-1
    Protected *buffer_in_asc.ascii, *buffer_out_asc.ascii
    Protected hash$=#Salt$+key$+Str(counter_key)+ReverseString(#Salt$)
    Static fixed_key_string${64}
    Static Dim register.q(3)
    
    fixed_key_string$=Fingerprint(@hash$, StringByteLength(hash$), #PB_Cipher_SHA3, 256) ; Create a key
    For ii = 0 To 31 : PokeA(@register(0)+ii, Val("$"+PeekS(@fixed_key_string$+iii, 2))) : iii+stepp : Next
    
    register(1)+counter_aes
    
    Macro go_1 ; One stage
      register(0)+1
      If Not AESEncoder(@register(0), @register(0), 32, @register(0), 256, 0, #PB_Cipher_ECB) : ProcedureReturn 0 : EndIf
      swap_=register(0) : register(0)=register(3) : register(3)=swap_ ; Never use here
      swap_=register(1) : register(1)=register(2) : register(2)=swap_ ; the PB swap function !
      
      ; register(2)+1 ; Activate for two stage crypting
      ; If Not AESEncoder(@register(0), @register(0), 32, @register(0), 256, 0, #PB_Cipher_ECB) : ProcedureReturn 0 : EndIf
    EndMacro
    
    If Not mode ; Binary mode
      *buffer_in_quad.quad=*buffer_in.word : *buffer_out_quad.quad=*buffer_out.word
      If bytes<16 ; Less 16 bytes
        *buffer_out_asc=*buffer_out_quad : *buffer_in_asc=*buffer_in_quad : *register_asc=@register(0)
        go_1
        For ii=0 To bytes_minus_1
          *buffer_out_asc\a=*buffer_in_asc\a ! *register_asc\a : *buffer_in_asc+1 : *buffer_out_asc+1 : *register_asc+1
        Next
        ProcedureReturn 1
      EndIf
      While i<rounds ; =>16 bytes
        go_1
        *buffer_out_quad\q=*buffer_in_quad\q ! register(0) : *buffer_in_quad+8 : *buffer_out_quad+8
        *buffer_out_quad\q=*buffer_in_quad\q ! register(1) : *buffer_in_quad+8 : *buffer_out_quad+8 : i+1
      Wend
      If rest
        *buffer_out_asc=*buffer_out_quad : *buffer_in_asc=*buffer_in_quad : *register_asc=@register(0)
        go_1
        For ii=0 To rest-1
          *buffer_out_asc\a=*buffer_in_asc\a ! *register_asc\a : *buffer_in_asc+1 : *buffer_out_asc+1 : *register_asc+1
        Next
      EndIf
    ElseIf mode=1
      bytes_minus_x=bytes-2
      *buffer_in_asc=*buffer_in : *buffer_out_asc=*buffer_out
      Repeat
        go_1 : *register_asc=@register(0)
        For ii=0 To 15
          If *buffer_in_asc\a And *buffer_in_asc\a ! *register_asc\a
            *buffer_out_asc\a=*buffer_in_asc\a ! *register_asc\a
          Else
            *buffer_out_asc\a=*buffer_in_asc\a
          EndIf
          If i>bytes_minus_x : Break 2 : EndIf
          *buffer_in_asc+1 : *buffer_out_asc+1 : *register_asc+1 : i+1
        Next ii
      ForEver
    Else ; mode=2
      bytes_minus_x=bytes-3
      Repeat
        go_1 : *register.word=@register(0)
        For ii=0 To 15 Step 2
          If *buffer_in\w And *buffer_in\w ! *register\w
            *buffer_out\w=*buffer_in\w ! *register\w
          Else
            *buffer_out\w=*buffer_in\w
          EndIf
          If i>bytes_minus_x : Break 2 : EndIf
          *buffer_in+2 : *buffer_out+2 : *register+2 : i+2
        Next ii
      ForEver
    EndIf
    ProcedureReturn 1
  EndProcedure
  
EndModule
UseModule QAES_smart_universal_coder

; ===== File coder addon for the universal AES256 based QAES_smart_universal_coder =====

DeclareModule QAES_smart_file_coder
  UseModule QAES_smart_universal_coder
  Declare.s QAES_smart_file_coder(mode, window_ID, progressbar_ID, path_1$, key_1$, file_extender$="", set_counter_protection_mode.q=0)
  Declare QAES_get_cryptextender_length()
  CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    Declare FixWriteData(file, *adress, length) ; Workaround for Linux PB 560
  CompilerEndIf
EndDeclareModule

Module QAES_smart_file_coder
  ; Smart file crypting addon or the QAES_smart_universal_coder
  ; Its nice you set a hint in your software for using QAES contents
  
  ; This addon can protect or encrypt and decrypt files using the QAES_smart_universal_coder module
  ; The encrypted files do not have visible headers or extenders
  ; Works with all file lengths
  ; No separate decrypter necessary
  ; With integrated full automatic working crypt randomized counter
  ; With full automatic file integrity check
  ; Can full automatic check whether a file is encrypted
  ; Various files with the same content are encrypted ever completely differently
  ; Author Werner Albus - www.nachtoptik.de - www.quick-aes-256.de
  ; No warranty whatsoever - Use at your own risk
  
  EnableExplicit
  
  Global cryptextender_length
  
  Procedure QAES_get_cryptextender_length()
    ProcedureReturn cryptextender_length
  EndProcedure
  
  CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    Procedure FixWriteData(file, *adress, length) ; Workaround for Linux PB560
      Protected write_data_pointer=Loc(file)
      Protected writen_data=WriteData(file, *adress, length)
      FileSeek(file, write_data_pointer+writen_data)
      ProcedureReturn writen_data
    EndProcedure
    Macro WriteData(File, Buffer, Size)
      FixWriteData(File, Buffer, Size)
    EndMacro
  CompilerEndIf
  
  Procedure.s QAES_smart_file_coder(mode, window_ID, progressbar_ID, path_1$, key_1$, file_extender$="", set_counter_protection_mode.q=0)
    
    ; mode=0 - Full automatic mode with file selectors
    ; mode=1 - Encrypt or add a file protection
    ; mode=2 - Decrypt or remove a file protection
    ; mode=3 - Check the file integrity
    ; mode=4 - Check if a file is already encrypted or protected
    
    ; set_counter_protection_mode <> 0 - activate the file protection mode
    ; This protect a file, but dont encrypt the file
    ; Mostly files you can normaly use protected
    ; Set on this variable your defined counter_aes from the universal crypter 
    
    ; If not window_ID or not progressbar_ID, you become not a progressbar
    ; A empty key (Password) open automatically a string selector
    
    ; CompilerIf #PB_Compiler_Debugger : MessageRequester("Debugger", "Please deactivate firstly the debugger !") : ProcedureReturn "" : CompilerEndIf
    
    #HashLength=256 ; (224, 256, 384, 512) You can use all available hash lengths divisible by 2 and also different hashes
    
    #Salt$="59#ö#3:_,.45ß$/($(/=)?=JjB$§/(&=$?=)((/&)%WE/()T&%z#'" ; Salt - You can change
    
    cryptextender_length=8+8+#HashLength>>3
    
    restart:
    Protected path$="", hash$, key$, message$, method_0$, method__0$, method___0$
    Protected method_1$, method__1$, method___1$, hash_1$="", key_2$, hash_2$=""
    Protected file, readed, writen=0, check_integrity=0, file_broken=0, block_size, window_event, result
    Protected progressbar_state, encrypted_file_found=0, hash_bytes, i, key_presetted, blocks, rest, block_counter=0
    Protected file_size.q, get_counter.q, get_magic.q, counter.q, counter_0.q, magic.q
    Protected counter_1.q=345645758512426756724 ; Preset startpoint counter 1 - You can change
    Protected Dim hash.q(#HashLength>>3-1)
    Protected *buffer
    
    If set_counter_protection_mode
      counter=set_counter_protection_mode
      magic.q=275390641757985374251 ; Preset protected marker - You can change
      method_0$=" protected " : method__0$=" protect "
      method_1$=" unprotected " : method__1$=" unprotect "
    Else
      If OpenCryptRandom() : CryptRandomData(@counter, 8) : Else : RandomData(@counter, 8) : EndIf
      If Not counter
        If Not mode
          MessageRequester("ERROR", "Can not create counter")
        Else
          ProcedureReturn "ERROR ##01QF - Can not create counter !"
        EndIf
        ProcedureReturn ""
      EndIf
      magic.q=415628580943792148170 ; Preset crypt marker - You can change
      method_0$=" encrypted " : method__0$=" encrypt " : : method___0$=" crypting "
      method_1$=" decrypted " : : method__1$=" decrypt "
    EndIf
    
    If *buffer : FreeMemory(*buffer) : *buffer=0 : EndIf
    
    If mode Or path_1$<>"" : path$=path_1$ : path_1$="" : EndIf
    
    If IsWindow(window_ID) : progressbar_state=1 : EndIf
    If IsGadget(progressbar_ID) : SetGadgetState(progressbar_ID, 0) : progressbar_state+1 : EndIf
    
    If Len(Fingerprint(@magic, 8, #PB_Cipher_SHA3, #HashLength))<>#HashLength>>2 ; Test Fingerprint
      If Not mode
        MessageRequester("ERROR", "Fingerprint fails")
      Else
        ProcedureReturn "ERROR ##02QF - Fingerprint fails !"
      EndIf
      ProcedureReturn ""
    EndIf
    
    If key_1$=""
      key_1$=InputRequester("", "Set firstly a password !", "")
      If key_1$="" : ProcedureReturn "" : EndIf
    Else
      key_presetted=1
    EndIf
    
    key$=ReverseString(#Salt$)+key_1$+#Salt$+ReverseString(key_1$) : key_2$=key_1$ : key_1$=""
    
    QAES_smart_universal_coder(0, @magic, @magic, 8, #Salt$+ReverseString(key$)+Str(magic)+key$)
    
    If Not mode And path$=""
      path$=OpenFileRequester("Select a file to"+method___0$, "", "*.*", 0)
      If path$="" : ProcedureReturn "" : EndIf
    EndIf
    
    file_size=FileSize(path$)
    If file_size<0
      If Not mode
        MessageRequester("ERROR", "File not found")
        Goto restart
      Else
        ProcedureReturn "ERROR ##03QF - File not found !"
      EndIf
    ElseIf Not file_size
      If Not mode
        MessageRequester("ERROR", "This is a zero length file"+#CRLF$+#CRLF$+"Can not"+method__0$+"files without a content")
        Goto restart
      Else
        ProcedureReturn "ERROR ##04QF - This is a zero length file - Can not"+method__0$+"files without a content !"
      EndIf
    EndIf
    
    file=OpenFile(#PB_Any, path$)
    If file
      block_size=4096<<2 : FileBuffersSize(file, block_size ) : *buffer=AllocateMemory(block_size) 
      If file_size<cryptextender_length+1
        If mode>1
          CloseFile(file)
          ProcedureReturn "ERROR ##05QF - This is not a"+method_0$+" file !"
        Else
          Goto encrypt_1
        EndIf
      EndIf
      FileSeek(file, file_size-cryptextender_length)
      ReadData(file, @get_counter, 8)
      ReadData(file, @get_magic, 8)
      ReadData(file, @hash(0), #HashLength>>3)
      FileSeek(file, 0)
      QAES_smart_universal_coder(0, @get_counter, @get_counter, 8, ReverseString(key$)+key$+#salt$)            ; QAES crypter - Try decrypt counter
      QAES_smart_universal_coder(0, @hash(0), @hash(0), #HashLength>>3, key$+ReverseString(key$), get_counter) ; QAES crypter - Try decrypt hash
      QAES_smart_universal_coder(0, @get_magic, @get_magic, 8, ReverseString(key$)+key$, get_counter)          ; QAES crypter - Try decrypt magic
      
      If get_magic=magic
        If mode=1
          CloseFile(file)
          ProcedureReturn "HINT ##06QF - This is a valid"+method_0$+"file !"
        ElseIf mode=3
          check_integrity=1
        ElseIf mode=4
          CloseFile(file)
          ProcedureReturn "ALLok ##07QF - File checked - This is a valid"+method_0$+"file !"
        ElseIf Not mode
          result=MessageRequester("HINT", "This is a valid"+method_0$+"file !"+#CRLF$+#CRLF$+
                                          "Want to"+method__1$+"the file now ? - Select Yes"+#CRLF$+#CRLF$+
                                          "Just want to check the integrity of the file ? - Select Cancel"+#CRLF$+#CRLF$+
                                          "Want to select another file ? - Select No", #PB_MessageRequester_YesNoCancel)
          If result=#PB_MessageRequester_Cancel
            key_1$=key_2$
            check_integrity=1
          ElseIf result=#PB_MessageRequester_No
            key_1$=key_2$
            CloseFile(file)
            Goto restart
          EndIf
        EndIf
        encrypted_file_found=1 : counter_0=get_counter
        For i = 0 To #HashLength>>3-1 : hash_2$+RSet(Hex(PeekA(@hash(0)+i)), 2, "0") : Next i : hash_2$=LCase(hash_2$)
      Else 
        If mode>1
          CloseFile(file)
          ProcedureReturn "HINT ##08QF - File checked - This is not a valid"+method_0$+"file - Or your key is wrong !"
        EndIf
        encrypt_1:
        If Not mode
          message$="This file looking not valid"+method_0$+"!"+#CRLF$+#CRLF$+
                   "It is also possible that your password is wrong"+#CRLF$+#CRLF$+
                   "Or it is possible that it is a corrupted"+method_0$+"file"+#CRLF$+#CRLF$+
                   "Want to"+method__0$+"this file now with your password ? - Select Yes"+#CRLF$+#CRLF$+
                   "Want to select another file ? - Select No"
          If key_presetted
            result=MessageRequester("HINT", message$, #PB_MessageRequester_YesNo)
          Else
            result=MessageRequester("HINT", message$+#CRLF$+#CRLF$+"To change your password - Select Cancel", #PB_MessageRequester_YesNoCancel)
          EndIf
          
          If result=#PB_MessageRequester_No
            key_1$=key_2$
            CloseFile(file) : Goto restart
          ElseIf result=#PB_MessageRequester_Cancel
            CloseFile(file) : key$="" : Goto restart
          EndIf
        EndIf
        QAES_smart_universal_coder(0, @magic, @magic, 8, ReverseString(key$)+key$, counter) ; QAES crypter - Encrypt magic
        counter_0=counter
      EndIf
      
    Else
      If Not mode
        MessageRequester("ERROR", "Can not open file")
        Goto restart
      Else
        ProcedureReturn "ERROR ##09QF - Can not open file !"
      EndIf
    EndIf
    
    If IsWindow(window_ID)
      AddWindowTimer(window_ID, window_ID, 30)
    EndIf
    
    If progressbar_state=2 : SetGadgetState(progressbar_ID, 0) : EndIf
    
    blocks=(file_size-cryptextender_length)/block_size
    
    rest=file_size-(block_size*blocks)
    
    If encrypted_file_found
      rest-cryptextender_length
    EndIf
    
    Repeat
      readed=ReadData(file, *buffer, block_size)
      
      If encrypted_file_found
        hash_bytes=readed-cryptextender_length
        If readed=block_size : hash_bytes=readed : EndIf
        If hash_bytes>0
          block_counter+1
          If blocks 
            If block_counter>blocks : hash_bytes=rest : EndIf
          Else
            hash_bytes=file_size-cryptextender_length
          EndIf
          hash$=Fingerprint(*buffer, hash_bytes, #PB_Cipher_SHA3, #HashLength)
          hash$+key$+hash_1$+Str(counter_0)
          hash$=Fingerprint(@hash$, StringByteLength(hash$), #PB_Cipher_SHA3, #HashLength)
          hash_1$=hash$
        EndIf
      EndIf
      
      If Not check_integrity And Not set_counter_protection_mode
        QAES_smart_universal_coder(0, *buffer, *buffer, block_size, key$, counter_0, counter_1) ; QAES crypter
      EndIf
      
      If Not encrypted_file_found
        If readed>0
          hash$=Fingerprint(*buffer, readed, #PB_Cipher_SHA3, #HashLength)
          hash$+key$+hash_1$+Str(counter_0)
          hash$=Fingerprint(@hash$, StringByteLength(hash$), #PB_Cipher_SHA3, #HashLength)
          hash_1$=hash$ 
        EndIf
      EndIf
      
      If check_integrity
        writen+readed
      Else
        FileSeek(file, -readed, #PB_Relative) : writen+WriteData(file, *buffer, readed)
      EndIf 
      
      If progressbar_state
        window_event=WindowEvent()
      EndIf
      If progressbar_state=2 And window_event=#PB_Event_Timer And EventTimer()=window_ID
        SetGadgetState(progressbar_ID, 100*writen/file_size)
      EndIf
      counter_0+1 : counter_1+1
    Until Not readed
    
    If progressbar_state=2 : SetGadgetState(progressbar_ID, 100) : EndIf
    
    hash$+key$+#Salt$ ; Finishing fingerprint
    hash$=LCase(Fingerprint(@hash$, StringByteLength(hash$), #PB_Cipher_SHA3, #HashLength))
    
    If encrypted_file_found And hash$<>hash_2$
      If check_integrity
        CloseFile(file) : FreeMemory(*buffer) : *buffer=0
        If Not mode
          If MessageRequester("WARNING", "File hash broken !"+#CRLF$+#CRLF$+
                                         "Want to use the file coder again ? - Select Yes", 
                              #PB_MessageRequester_YesNo)=#PB_MessageRequester_No
            ProcedureReturn ""
          EndIf
          Goto restart
        Else
          ProcedureReturn "WARNING ##10QF - File hash broken ! - Used counter =>"+Str(get_counter)
        EndIf
        
      Else
        file_broken=1
      EndIf
    EndIf
    
    If check_integrity
      CloseFile(file) : FreeMemory(*buffer) : *buffer=0
      If Not mode
        SetClipboardText(GetFilePart(path$)+#CRLF$+hash_2$)
        If MessageRequester("HINT", "All OK !"+#CRLF$+#CRLF$+"File integrity succesfully checked !"+#CRLF$+#CRLF$+
                                    "I put now the file hash and name in your clipboard"+#CRLF$+#CRLF$+hash_2$+#CRLF$+#CRLF$+
                                    "Want to use the file coder again ? - Select Yes", 
                            #PB_MessageRequester_YesNo)=#PB_MessageRequester_Yes
          Goto restart
        EndIf
      Else
        ProcedureReturn "ALLok ##11QF - File integrity succesfully checked ! - Used counter =>"+Str(get_counter)+" - File hash ==>"+hash_2$
      EndIf
      ProcedureReturn ""
    EndIf
    
    If Not encrypted_file_found
      For i=0 To #HashLength>>3-1 : PokeA(@hash(0)+i, Val("$"+PeekS(@hash$+i*SizeOf(character)<<1, 2))) : Next i
      QAES_smart_universal_coder(0, @hash(0), @hash(0), #HashLength>>3, key$+ReverseString(key$), counter) ; QAES crypter - Crypt hash
      QAES_smart_universal_coder(0, @counter, @counter, 8, ReverseString(key$)+key$+#salt$)                ; QAES crypter - Crypt counter
      writen+WriteData(file, @counter, 8)
      writen+WriteData(file, @magic, 8)
      writen+WriteData(file, @hash(0), #HashLength>>3)
      If writen<>file_size+cryptextender_length
        CloseFile(file) : FreeMemory(*buffer)
        If Not mode
          MessageRequester("ERROR", "Writen fails"+#CRLF$+#CRLF$+"Writen Bytes : "+Str(writen))
        Else
          ProcedureReturn "ERROR ##12QF - Writen fails - Writen Bytes : "+Str(writen)+" !"
        EndIf
        ProcedureReturn ""
      EndIf
    EndIf
    
    If encrypted_file_found
      FileSeek(file, -cryptextender_length, #PB_Relative)
      TruncateFile(file)
      If Lof(file)<>file_size-cryptextender_length
        CloseFile(file) : FreeMemory(*buffer)
        If Not mode
          MessageRequester("ERROR", "Truncate file fails")
        Else
          ProcedureReturn "ERROR ##13QF - Truncate file fails !"
        EndIf
        ProcedureReturn ""
      EndIf
    EndIf
    
    CloseFile(file)
    
    If file_extender$<>""
      If encrypted_file_found And Right(path$, Len(file_extender$))=file_extender$
        RenameFile(path$, Left(path$, Len(path$)-Len(file_extender$)))
      Else
        If Not encrypted_file_found
          RenameFile(path$, path$+file_extender$)
        EndIf
      EndIf
    EndIf
    
    If file_broken
      If Not mode
        message$="WARNING - File"+method_1$+"but file hash broken !"
      Else
        message$="WARNING ##14QF - File"+method_1$+"but file hash broken !"
      EndIf
    Else
      If encrypted_file_found
        If Not mode
          message$="All OK - File"+method_1$+"!"+#CRLF$+#CRLF$+
                   "I put now the file hash and name in your clipboard"+#CRLF$+#CRLF$+hash_2$
          SetClipboardText(GetFilePart(path$)+#CRLF$+hash_2$)
        Else
          message$="ALLok ##15QF - File"+method_1$+" ! - Used counter =>"+Str(get_counter)+" - File hash ==>"+hash_2$
        EndIf
      Else
        If Not mode
          message$="ALL OK - File "+method_0$+#CRLF$+#CRLF$+
                   "I put now the file hash and name in your clipboard"+#CRLF$+#CRLF$+hash$
          SetClipboardText(GetFilePart(path$)+#CRLF$+hash$)
        Else
          message$="ALLok ##16QF - File"+method_0$+" ! - File hash ==>"+hash$
        EndIf
      EndIf
    EndIf
    
    If Not mode
      If MessageRequester("HINT", message$+#CRLF$+#CRLF$+
                                  "Want to use the file coder again ?", 
                          #PB_MessageRequester_YesNo)=#PB_MessageRequester_Yes
        key_1$=key_2$
        Goto restart
      EndIf
    EndIf
    
    FreeMemory(*buffer)
    ProcedureReturn message$
    
  EndProcedure
  
EndModule
UseModule QAES_smart_file_coder

; ===================== Using the file crypt Addon ===============================

EnableExplicit
Define mode, window_ID, progressbar_ID , key$, path_0$, path_1$

; mode=0 - Full automatic mode with file selectors
; mode=1 - Encrypt
; mode=2 - Decrypt
; mode=3 - Check the file integrity
; mode=4 - Check if a file is already encrypted
; If not window_ID or not progressbar_ID, you get not a progressbar
; A empty key (Password) open automatically a string selector

#cryptfile_extender$=" [encrypted]" ; You can change how ever you want

; Automatic mode
key$=""
window_ID=OpenWindow(#PB_Any, 0, 0, 280, 50, "QAES smart universal coder", #PB_Window_ScreenCentered)
progressbar_ID=ProgressBarGadget(#PB_Any, 10, 10, 260, 30, 0, 100, #PB_ProgressBar_Smooth)
QAES_smart_file_coder(0, window_ID, progressbar_ID, "", key$, #cryptfile_extender$)

; Manual modes
; key$="This is a pre defined test key"
; path_0$=GetTemporaryDirectory()+"TestPic.jpg" ; Create a little picture for test
; path_1$=path_0$+#cryptfile_extender$
; UseJPEGImageEncoder()
; SaveImage(CreateImage(#PB_Any, 10, 10), path_0$, #PB_ImagePlugin_JPEG)
; Debug QAES_smart_file_coder(1, window_ID, progressbar_ID, path_0$, key$, #cryptfile_extender$) ; Encrypt a file
; Debug QAES_smart_file_coder(4, window_ID, progressbar_ID, path_1$, key$, #cryptfile_extender$) ; Check if the file is already valid encrypted
; Debug QAES_smart_file_coder(3, window_ID, progressbar_ID, path_1$, key$, #cryptfile_extender$) ; Check the file integrity
; Debug QAES_smart_file_coder(2, window_ID, progressbar_ID, path_1$, key$, #cryptfile_extender$) ; Decrypt a file

States back sample :
ALLok ##16QF - File encrypted - File hash ==>f3c11d468f74e52112939f471da8e0b36c68ad0880c6dd2b27c7a82fb8bfddbb
ALLok ##06QF - File checked - This is a valid encrypted file
ALLok ##10QF - File integrity succesfully checked - File hash ==>f3c11d468f74e52112939f471da8e0b36c68ad0880c6dd2b27c7a82fb8bfddbb
ALLok ##14QF - File decrypted - File hash ==>f3c11d468f74e52112939f471da8e0b36c68ad0880c6dd2b27c7a82fb8bfddbb
Last edited by walbus on Fri Dec 15, 2017 10:27 pm, edited 37 times in total.
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Advanced AES Coder for Files &Strings &Termination Handl

Post by walbus »

The module has also a additional mode for file protection

But it is important that you understand how it works, if you want to use it

Primary it is simple, but it is often not so simple to understand complicated looking codes from others !

A demo application for this function, named "Crypted Pinboard", you found here :
http://www.purebasic.fr/english/viewtop ... 78#p507978

For activating this mode set simple set_counter_protection_mode <> 0
Defacto, set a pre defined counter for the universal crypter to this variable
Change this counter for each file you encrypt - Use a random function for creating !
You can, as sample, use the counter_aes for this and the counter_key as block counter for blockwise encrypting

Is this variable setted, selected files with the file crypter addon are no longer encrypted,
only a crypt extender is generated

With this extender you can protect any files !
This crypt extender is a file seal
Mostly files are also executable with a added crypt extender
Nobody can change unnoticed a file with this protection
You can simple check the integrity from any files with a used crypt extender

Little samples
You can encrypt with the universal crypter inside your application simple any strings or data directly
Use for the universal crypter a defined randomized counter
Then save this encrypted data as file
Now protect this encrypted file with the file protection function and your defined counter

You can use the PB functions for writting strings or data also blockwise
Encrypt on demand your data or string contents with the universal crypter, also blockwise
Your ready, add the file protection

With this new feature you must never again read or write unprotected data or strings
All things you read or written are ever pre encrypted

A other sample
Create a string gadget as pinboard for all things, as sample for a lot passwords or secret hints, links, or what ever you want
Save the string gadget content encrypted and protected with the methods above
Ready is your highly flexible AES protected password manager with self authentication
You do not need more than a few code lines for it

For decrypting the main data you can get the needed counter from the crypt extender again

Code: Select all

; Add the modules from the posting above

; ===================== Using the file crypt Addon ===============================
EnableExplicit
Define key$, path_0$, path_1$
Define mode, window_ID, progressbar_ID
Define set_counter_protection_mode.q

; mode=0 - Full automatic mode with file selectors
; mode=1 - Encrypt or add a file protection
; mode=2 - Decrypt or remove a file protection
; mode=3 - Check the file integrity
; mode=4 - Check if a file is already"+method_0$+"or protected

; set_counter_protection_mode <> 0 - activate the file protection mode
; This protect a file, but dont encrypt the file
; Mostly files you can normaly use protected
; Set on this variable your used counter from the universal crypter 

; If not window_ID or not progressbar_ID, you get not a progressbar
; A empty key (Password) open automatically a string selector

#file_extender$=" [encrypted]" ; You can change how ever you want
                               ; #file_extender$=" [protected]" ; You can change how ever you want

; Automatic mode
; key$="xxxxx"
; window_ID=OpenWindow(#PB_Any, 0, 0, 280, 50, "QAES smart universal coder", #PB_Window_ScreenCentered)
; progressbar_ID=ProgressBarGadget(#PB_Any, 10, 10, 260, 30, 0, 100, #PB_ProgressBar_Smooth)
; QAES_smart_file_coder(0, window_ID, progressbar_ID, "", key$, #file_extender$)

; Debug QAES_get_cryptextender_length()

; Manual modes
key$="xxxxx"
path_0$=GetTemporaryDirectory()+"TestPic.jpg" ; Create a little picture for test
path_1$=path_0$+#file_extender$
RandomData(@set_counter_protection_mode, 8)
UseJPEGImageEncoder()
SaveImage(CreateImage(#PB_Any, 10, 10), path_0$, #PB_ImagePlugin_JPEG)
Debug QAES_smart_file_coder(1, window_ID, progressbar_ID, path_0$, key$, #file_extender$, set_counter_protection_mode) ; Protect a file
Debug QAES_smart_file_coder(4, window_ID, progressbar_ID, path_1$, key$, #file_extender$, 1)                           ; Check if the file is already valid protected
Debug QAES_smart_file_coder(3, window_ID, progressbar_ID, path_1$, key$, #file_extender$, 1)                           ; Check the file integrity
Debug QAES_smart_file_coder(2, window_ID, progressbar_ID, path_1$, key$, #file_extender$, 1)                           ; Remove protection from file

Debug QAES_get_cryptextender_length() ; You get this length after any QAES_smart_file_coder call
                                      ; The crypt extender length is not a secret
                                      ; You want this length for ignore the extender to decrypt the main data from post protected files

Last edited by walbus on Wed Nov 29, 2017 10:05 pm, edited 12 times in total.
Post Reply