AESDecoder() и AESEncoder() не умеет правильно заполнять байтами заполнения, поэтому и пришлось написать данный костыль..
Метод заполнения CMS (Cryptographic Message Syntax). Заполняет тем же значением, что и количество байтов заполнения. Определено в RFC 5652, PKCS#5, PKCS#7 (сертификат X.509) и RFC 1423 PEM.
Код:
DeclareModule AES
Declare SetEncodedKey(keyHex$)
Declare SetEncodedIV(IV_Hex$)
Declare EncryptFile(InputFile$, OutputFile$="")
Declare DecryptFile(InputFile$, OutputFile$="")
Declare EncryptMemory(*Buffer, Size)
Declare DecryptMemory(*Buffer, Size)
EndDeclareModule
Module AES
Structure doublechar
c1.c
c2.c
EndStructure
Global Dim HexTable.a(127)
Global *EncodedKey, *EncodedIV
Procedure HexTableInit()
Protected i
For i='0' To '9'
HexTable(i)=(i-'0')
Next
For i='a' To 'f'
HexTable(i)=(i-'a'+10)
Next
For i='A' To 'F'
HexTable(i)=(i-'A'+10)
Next
For i=0 To 15
HexTable(i)=Asc(Hex(i))
Next
EndProcedure
HexTableInit()
Procedure hex2mem(*phex.doublechar,*mem=0,memlen=0)
Protected *pos.ascii
Protected hexlen
hexlen=MemoryStringLength(*phex)
If hexlen & %1
ProcedureReturn 0
EndIf
If *mem=0
memlen=hexlen/2
*mem=AllocateMemory(memlen)
ElseIf memlen=0
memlen=MemorySize(*mem)
EndIf
If memlen>=hexlen/2
*pos=*mem
While *phex\c1>0 And *phex\c2>0
*pos\a=HexTable(*phex\c1&$7f)<<4+HexTable(*phex\c2&$7f)
*phex+SizeOf(doublechar)
*pos+1
Wend
ProcedureReturn *mem
EndIf
ProcedureReturn 0
EndProcedure
Procedure SetEncodedKey(keyHex$)
If (Len(keyHex$)/2)%16
Debug ("Invalid key length")
Else
*EncodedKey = hex2mem(@keyHex$)
ProcedureReturn #True
EndIf
EndProcedure
Procedure SetEncodedIV(IV_Hex$)
If Len(IV_Hex$)/2 <> 16
Debug ("Invalid IV length")
Else
*EncodedIV = hex2mem(@IV_Hex$)
ProcedureReturn #True
EndIf
EndProcedure
Procedure CalcPaddingSize(size)
If size%16
ProcedureReturn 16-size%16
Else
ProcedureReturn 16
EndIf
EndProcedure
Procedure AddPadding(*Buffer)
Protected OldBufferSize = MemorySize(*Buffer)
Protected PaddingSize = CalcPaddingSize(OldBufferSize)
Protected NewBufferSize = OldBufferSize + PaddingSize
ReAllocateMemory(*Buffer, NewBufferSize)
For offset = NewBufferSize-1 To OldBufferSize Step -1
PokeA(*Buffer+offset, PaddingSize)
Next
EndProcedure
Procedure DeletePadding(*Buffer)
PaddingSize = PeekA(*Buffer + MemorySize(*Buffer)-1)
ReAllocateMemory(*Buffer, MemorySize(*Buffer) - PaddingSize)
EndProcedure
Procedure EncryptFile(InputFile$, OutputFile$="")
If Not Len(OutputFile$) : OutputFile$ = InputFile$ : EndIf
hInputFile = ReadFile(#PB_Any,InputFile$, #PB_File_SharedRead)
If hInputFile
InputBufferSize = FileSize(InputFile$)
*InputBuffer = AllocateMemory(InputBufferSize)
ReadData(hInputFile, *InputBuffer, InputBufferSize)
CloseFile(hInputFile)
*CipheredBuffer = EncryptMemory(*InputBuffer, InputBufferSize)
FreeMemory(*InputBuffer)
If *CipheredBuffer
hOutputFile = CreateFile(#PB_Any, OutputFile$, #PB_File_SharedWrite)
WriteData(hOutputFile, *CipheredBuffer, MemorySize(*CipheredBuffer))
CloseFile(hOutputFile)
FreeMemory(*CipheredBuffer)
ProcedureReturn #True
EndIf
Else
Debug "Cannot read file: " + InputFile$
EndIf
EndProcedure
Procedure DecryptFile(InputFile$, OutputFile$="")
If Not Len(OutputFile$) : OutputFile$ = InputFile$ : EndIf
hInputFile = ReadFile(#PB_Any,InputFile$, #PB_File_SharedRead)
If hInputFile
InputBufferSize = FileSize(InputFile$)
*InputBuffer = AllocateMemory(InputBufferSize)
ReadData(hInputFile, *InputBuffer, InputBufferSize)
CloseFile(hInputFile)
*DecipheredBuffer = DecryptMemory(*InputBuffer, InputBufferSize)
FreeMemory(*InputBuffer)
If *DecipheredBuffer
hOutputFile = CreateFile(#PB_Any, OutputFile$, #PB_File_SharedWrite)
WriteData(hOutputFile, *DecipheredBuffer, MemorySize(*DecipheredBuffer))
CloseFile(hOutputFile)
FreeMemory(*DecipheredBuffer)
ProcedureReturn #True
EndIf
Else
Debug "Cannot read file: " + InputFile$
EndIf
EndProcedure
Procedure DecryptMemory(*Buffer, Size)
If Not *EncodedKey : Debug "AES key not set, use SetEncodedKey(keyHex$)": ProcedureReturn #False : EndIf
If Not *EncodedIV : Debug "AES key not set, use SetEncodedIV(IV_Hex$)" : ProcedureReturn #False : EndIf
*OutputBuffer = AllocateMemory(Size)
If AESDecoder(*Buffer, *OutputBuffer, Size, *EncodedKey, MemorySize(*EncodedKey) * 8, *EncodedIV)
DeletePadding(*OutputBuffer)
ProcedureReturn *OutputBuffer
EndIf
EndProcedure
Procedure EncryptMemory(*Buffer, Size)
If Not MemorySize(*EncodedKey) : Debug "AES key not set, use SetEncodedKey(keyHex$)": ProcedureReturn #False : EndIf
If Not MemorySize(*EncodedIV) : Debug "AES key not set, use SetEncodedIV(IV_Hex$)" : ProcedureReturn #False : EndIf
*InputBuffer = AllocateMemory(Size)
CopyMemory(*Buffer, *InputBuffer, Size)
AddPadding(*InputBuffer)
Protected CipheredBufferSize = MemorySize(*InputBuffer)
*CipheredBuffer = AllocateMemory(CipheredBufferSize)
If AESEncoder(*InputBuffer, *CipheredBuffer, CipheredBufferSize, *EncodedKey, MemorySize(*EncodedKey) * 8, *EncodedIV)
FreeMemory(*InputBuffer)
ProcedureReturn *CipheredBuffer
EndIf
EndProcedure
EndModule
;-Demo
CompilerIf #PB_Compiler_IsMainFile
; Set Key and IV
AES::SetEncodedKey("8FFEE3909018B5F7D0BFC585E479028AE61C9A17E60C7E2F35D323B4156E1DC6")
AES::SetEncodedIV("FC7187754B1D4EA6FA949BB1AE9E3A37")
; Encrypt / Decrypt File Example
Debug AES::EncryptFile("Example.txt", "Example_crypted.bin")
Debug AES::DecryptFile("Example_crypted.bin", "Example_decrypted.txt")
; Encrypt / Decrypt memory data Example
*OriginalBuffer = AllocateMemory(500)
*CyptedBuffer = AES::EncryptMemory(*OriginalBuffer, MemorySize(*OriginalBuffer))
ShowMemoryViewer(*CyptedBuffer, MemorySize(*CyptedBuffer))
CallDebugger
*DecyptedBuffer = AES::DecryptMemory(*CyptedBuffer, MemorySize(*CyptedBuffer))
ShowMemoryViewer(*DecyptedBuffer, MemorySize(*DecyptedBuffer))
CallDebugger
CompilerEndIfОтредактировано Lin (20.10.2021 18:19:00)