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)