some stuff that might be usefull to someone...
Code: Select all
Procedure.l x_crypt(*channel.x_crypt,dat.l)
Protected mode.l, key_p.l, key_c.l, key_l.l, old.l, n.l
Global x_retval.l
;
; *** en- or decrypt a single element
;
; in: *channel.x = 0..7 - 8 structures handled by the x_crypt() routines themselves
; = n - the memory address of a struct defining the behaviour
; dat.l - data to en- or decrypt
; retval.l - de- or encrypted data
; out: x_retval.l - same as retval
;
; all information related to the encryption mechanism is stored in a structure, so multiple
; crypto sets can run in parallel, all necessary fields have to be set before first time
; calling x_crypt()
;
; typically, one will have to set for x_crypt():
;
; ...\mode
; ...\key_p = address of first element in key (see note below regarding using strings as keys)
; ...\key_l = number of elements in key (length in bytes)
; ...\key_c = 0
; ...\old = 0
; ...\n = 0
;
; for de/encrypting blocks, the following fields are also important:
;
; ...\mem_p = address of first element in block to process
; ...\mem_l = length of block
; ...\mem_c = 0
;
; note 1: the routine x_crypt_set() sets these fields
;
; note 2: it is perfectly possible to use a string to contain the key, but remember that
; the pointer to this string (key_p) may change due to garbage recollection! so get the
; memory location of the key string every time before calling the x_crypt routines using @<stringvar>
;
; note 3: you can either define your own structs and point to those, or use an 'identifier' 0..7
; when using 0..7 the x_crypt() routines maintain their own buffers
;
; sample usage:
;
; x_init();
; ;
; s.s = "This is a string to encrypt, including 1234567890 and ##########."
; s_l = Len(s)
; ;
; x_crypt_set(1,#x_crypt_blue1,0,0,0,0,"","This is a key.") ; first channel with key
; x_crypt_text(1,s) ; encrypt the text, channel is going to create a buffer
; ;
; Debug x_peekhex(x_crypt_channel(1)\mem_p,x_crypt_channel(1)\mem_l,1)
; Debug PeekB(x_crypt_channel(1)\mem_p)
; Debug PeekS(x_crypt_channel(1)\mem_p,s_l)
; Debug ""
; Debug x_crypt_channel(1)\key_c
; Debug x_crypt_channel(1)\mem_p
; Debug x_crypt_channel(1)\mem_l
; Debug x_crypt_channel(1)\key_p
; Debug x_crypt_channel(1)\key_l
; Debug ""
; ;
; x_crypt_set(2,#x_crypt_blue1,0,0,0,0,"","This is a key.") ; second channel with same key
; x_crypt_block(2,x_crypt_channel(1)\mem_p,s_l) ; note that channel 2 doesn't have its own memory block
; ;
; Debug x_peekhex(x_crypt_channel(1)\mem_p,x_crypt_channel(1)\mem_l,1)
; Debug PeekS(x_crypt_channel(1)\mem_p,s_l)
; Debug ""
; ;
; x_crypt_text(1,s) ; do it again, the hex result should be different from the first call
; ;
; Debug x_peekhex(x_crypt_channel(1)\mem_p,x_crypt_channel(1)\mem_l,1)
; Debug PeekS(x_crypt_channel(1)\mem_p,s_l)
; Debug ""
; Debug x_crypt_channel(1)\key_c
; Debug x_crypt_channel(1)\mem_p
; Debug x_crypt_channel(1)\mem_l
; Debug x_crypt_channel(1)\key_p
; Debug x_crypt_channel(1)\key_l
; Debug ""
; ;
; x_crypt_block(2,x_crypt_channel(1)\mem_p,s_l) ; and decrypt it again using the second channel
; ;
; Debug x_peekhex(x_crypt_channel(1)\mem_p,x_crypt_channel(1)\mem_l,1)
; Debug PeekS(x_crypt_channel(1)\mem_p,s_l)
; Debug ""
;
;
; time to code... first move struct elements to vars, it's probably slower but makes code easier to read
;
If *channel < 0
ElseIf *channel <= 7
x_crypt(@x_crypt_channel(*channel),dat.l)
Else
;
old = *channel\old ; previously processed element (byte, word, whatever)
key_p = *channel\key_p ; pointer to first byte of key
key_l = *channel\key_l ; length of key
key_c = *channel\key_c ; counter (pointer to current element of key)
mode = *channel\mode ; what to do (type of encoding, how to encode, etc.)
n = *channel\n ; counter, number of bytes encrypted
;
Select mode
Case #x_crypt_none
;
; - for debugging purposes
;
x_retval = dat
;
Case #x_crypt_invert
;
; - symmetric (encoding algoritm is the same as decoding algoritm)
; - very insecure
;
x_retval = (dat ! $FF)
;
Case #x_crypt_count_encode
;
; - for debugging purposes
;
key_c = key_c+1
x_retval = (dat+key_c) & $FF
;
Case #x_crypt_count_decode
;
; - for debugging purposes
;
key_c = key_c+1
x_retval = (dat-key_c) & $FF
;
Case #x_crypt_keyxor
;
; this is a simple encryption mechanism that xor's the original string with the key
;
; - symmetric
; - continuous (ie. repeated calls will use a previous position of the key pointer)
; - poor security
;
x_retval = ( dat ! PeekB(key_p+key_c) ) & $FF
key_c = key_c+1
;
Case #x_crypt_blue1
;
; this is a more complex mechanism that uses previously processed data with key and counter
; and should at least be confusing to hackers...
;
; - symmetric
; - continuous
; - reasonably secure (but don't use it to scramble your bank account data :-))
;
x_retval = ( key_c ! old ! dat ! PeekB(key_p+key_c) ) & $FF
key_c = key_c+1
old = x_rolb(x_retval)
;
EndSelect
;
If key_c >= key_l
key_c = 0
EndIf
n = n+1
;
; store all (changed) data back in the struct
;
*channel\key_c = key_c
*channel\old = old
*channel\n = n
;
EndIf
;
ProcedureReturn x_retval
EndProcedure
Procedure.l x_crypt_block(*channel.x_crypt,mem_p,mem_l)
Global x_retval_p.l, x_retval_l.l, x_retval_x.l
;
; *** in memory encryption of given data block using specified struct for method and parameters
;
; in: *channel.x_crypt = 0..7 - identifier of channel
; = n - pointer to structure to use
; mem_p.l = n - start of block to en/decrypt, 0 to use address in channel struct
; mem_l.l = n - length of block, 0 to use length in channel struct
; retval: - none
; out: x_retval_p.l = n - pointer to processed block
; x_retval_l.l = n - length of processed block
;
If *channel < 0
ElseIf *channel < 8
If mem_p < 1
mem_p = x_crypt_channel(*channel)\mem_p
EndIf
If mem_l < 1
mem_l = x_crypt_channel(*channel)\mem_l
EndIf
x_crypt_block(@x_crypt_channel(*channel),mem_p,mem_l)
Else
;
n = 0
While n < mem_l
PokeB(mem_p+n,x_crypt(*channel,PeekB(mem_p+n)))
n = n+1
Wend
;
x_retval_p = mem_p
x_retval_l = mem_l
;
EndIf
;
EndProcedure
Procedure.l x_crypt_text(*channel.x_crypt,string.s)
Protected l.l
Global x_retval_p.l, x_retval_l.l, x_retval_x.l
;
; *** use settings of previous x_crypt_set or specified structure to process given string
;
; in: *channel.x_crypt = 0..7 - channel
; = n - pointer to structure
; string.s - string to place
; retval: - none
; out: x_retval_p - pointer to processed block
; x_retval_l - length of processed block
;
l = Len(string)
If *channel < 0
ElseIf *channel < 8
FreeMemory(x_crypt_channel(*channel)\mem_p)
x_crypt_channel(*channel)\mem_p = AllocateMemory(l)
x_pokes(x_crypt_channel(*channel)\mem_p,string,l)
x_crypt_channel(*channel)\mem_l = l
x_crypt_block(*channel,-1,-1)
Else
x_pokes(*channel\mem_p,string,l)
*channel\mem_l = l
x_crypt_block(*channel,-1,-1)
EndIf
;
EndProcedure
Procedure.s x_crypt_gettext(*channel.x_crypt)
;
; *** get decrypted string
;
; in: *channel.x_crypt = 0..7 - channel to use, or...
; = n - pointer to x_crypt structure
; retval: .s - string containing (de)crypted data
; out: x_retval_p.l = n - pointer to data
; x_retval_l.l = n - length of data
;
If *channel < 0
Else
x_crypt_block(*channel,-1,-1)
ProcedureReturn PeekS(x_retval_p,x_retval_l)
EndIf
;
EndProcedure
Procedure x_crypt_set(*channel.x_crypt,mode.l,mem_p.l,mem_l.l,key_p.l,key_l.l,string.s,key.s)
;
; *** set encryption / decryption parameters
;
; in: *channel.x_crypt = 0..7 - if < 8 an identifier or...
; = n - if > 7 a memory address of a structure that controls the en/decryption behaviour
;
; for 'channel' 0..7: mem_p.l = -1 - keep old memory pointer, counter, and data intact
; mem_l.l > 0 - wipe and resize data buffer to given size
; key_p.l = -1 - keep old key pointer, counter, And Data intact
; key_l.l > n - resize key buffer to given size
; string.s > "" - overwrite data with given string, adjust mem_l and mem_p
; key.s > "" - overwrite key with given string, adjust key_l and key_p
;
; for given structure: mem_p.l = n - set start data block
; mem_l.l = n - set size data block
; key_p.l = n - set start of key
; key_l.l = n - set length of key
; string.s > "" - overwrite data with given string, adjust mem_l
; key.s > "" - overwrite key with given string, adjust key_l
;
; note: when specifying the structs you have to make sure the buffers pointed to are of sufficient size!
;
If *channel < 0
ElseIf *channel < 8
If mem_p = -1
mem_p = x_crypt_channel(*channel)\mem_p
mem_l = x_crypt_channel(*channel)\mem_l
Else
mem_p = x_crypt_channel(*channel)\mem_p
mem_l = x_max(mem_l,Len(string))
If mem_l > 0
If x_crypt_channel(*channel)\mem_p <> 0
FreeMemory(mem_p)
EndIf
mem_p = AllocateMemory(mem_l+1)
EndIf
EndIf
If key_p = -1
key_p = x_crypt_channel(*channel)\key_p
key_l = x_crypt_channel(*channel)\key_l
Else
key_p = x_crypt_channel(*channel)\key_p
key_l = x_max(key_l,Len(key))
;
If key_l > 0
If x_crypt_channel(*channel)\key_p <> 0
FreeMemory(key_p)
EndIf
key_p = AllocateMemory(key_l+1)
EndIf
EndIf
x_crypt_set(@x_crypt_channel(*channel),mode,mem_p,mem_l,key_p,key_l,string,key)
Else
;
l = Len(string)
If l > 0 And mem_p > 0
x_pokes(mem_p,string,l)
mem_l = Len(string)
EndIf
l = Len(key)
If l > 0 And key_p > 0
x_pokes(key_p,key,l)
key_l = Len(key)
EndIf
;
*channel\mode = mode ; what to do / how to encrypt (see below)
*channel\mem_p = mem_p ; pointer to block of memory to encrypt
*channel\mem_l = mem_l ; length of block
*channel\mem_c = 0 ; counter, points to the next byte to encrypt
*channel\key_p = key_p ; pointer to block of memory containing key
*channel\key_l = key_l ; length of key
*channel\key_c = 0 ; counter to keep track of next element of the key
*channel\old = 0 ; previous processed element (byte, word, whatever)
*channel\n = 0 ; counter (how many bytes have been processed, used by some encryption schemes)
*channel\crc32 = 0 ; crc32 of data (not used yet)
*channel\md5 = "" ; md5 hash of data (not used yet)
;
EndIf
;
EndProcedure