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)