Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Kleines Weihnachtsgeschenk von der DEC (https://www.delphipraxis.net/216409-kleines-weihnachtsgeschenk-von-der-dec.html)

TurboMagic 24. Dez 2024 11:58

Kleines Weihnachtsgeschenk von der DEC
 
Hallo,

so, Weihnachten naht mit großen Schritten und ich hab's endlich mal wieder geschafft was an der DEC
(Delphi Encryption Compendium) zu machen, u.a. getrieben durch einen Beitrag unseres Schweizer MVP Kollegen Christoph.

Das "Geschenk" ist noch im Development Zweig hier:
https://github.com/MHumm/DelphiEncry...ee/development

Was ist es?
  • Unterstützung des PKCS#7 Paddings bei den Verschlüsselungsalgorithmen (das schließt auch PKCS#5 ein)
  • Erweiterte Cipher_FMX Demo
  • Erweiterte VCL Progress Demo
  • TFormat_UTF8 und TFormat_UTF16 (letzteres ist nur ein Alias für TFormat_BigEndian16)
  • In anderen Pull Requests beigesteuerte Fehlerkorrekturen z. B. in TDECCipher.DecodeRawByteString

Die Doku wurde auch gleich erweitert.
Achtung: es ist bekannt, dass derzeit nicht alle Unit Tests fehlerfrei durchlaufen.
Das betrifft jedoch nur den GCM und den Keccak Algorithmus.Ursachen muss ich noch suchen. Beim Keccak
liegt es an irgendwelchen Stringverarbeitungen und der Fehler ist im Unit Test, sehr wahrscheinlich nicht im Algorithmus,
da andere Tests für diesen bestanden werden.

Was ich noch super fände wäre, wenn mal jemand der FPC installiert hat prüft, ob das
auch unter FPC noch alles compiliert.

So, jetzt aber frohe Weihnachten und einen guten Rutsch ins Jahr 2025!

Kas Ob. 24. Dez 2024 16:03

AW: Kleines Weihnachtsgeschenk von der DEC
 
Happy holidays to you too and too everyone !

Nice and thank you for work and contribution!

One very small thing i saw here
https://github.com/MHumm/DelphiEncry...as#L1451-L1453
This should be exception raised in consistent with the used style and coding, if the length is 0 this PKCS7 padding is absent and broken.


on side note: these exception in general, not only in PKCS7 or any specific unit
Delphi-Quellcode:
raise EDECCipherException.Create('xxxxxxxxxx');
Can affect performance due to code for string handling inserted by the compiler, although using TBytes itself does that too, so the following is not so important performance wise in this case per se, but..
replacing these calls with something centralized would be contain the usage of the strings and open the door for localization or at least just translating, it is cosmetic suggestion mostly.
example
Delphi-Quellcode:
as procedure DECExceptionRaise(DECEXCEPT_CIPHER_PADDING_PKCS7_INVALID;...);
And this could be applied to other exception across the library to make it useful, see these
https://github.com/MHumm/DelphiEncry...Modes.pas#L483
Delphi-Quellcode:
resourcestring
  sInvalidMessageLength = 'Message length for mode %0:s must be a multiple of %1:d bytes';
  sInvalidBlockSize    = 'Block size must be %0:d bit for selected mode %1:s';
  sInvalidModeForMethod = 'Invalid mode for this method. Mode must be %0:s';

.....
procedure TDECCipherModes.SetDataToAuthenticate(const Value: TBytes);
begin
  if (FMode = cmGCM) then
    FGCM.DataToAuthenticate := Value
  else
    raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM']);
end;

Kas Ob. 24. Dez 2024 16:54

AW: Kleines Weihnachtsgeschenk von der DEC
 
More thinking about this RemovePKCS7Padding i have a suggestion, and i am really sorry that i am doing this here not on GitHub

Refactor RemovePKCS7Padding where it could be split into a new public function HasValidPKCS7 return boolean and RemovePKCS7Padding can call it, this is more useful.

Christoph Schneider 28. Dez 2024 11:59

AW: Kleines Weihnachtsgeschenk von der DEC
 
I agree, in case of empty chiffre we should throw an exception.

To your second proposal. What is the workflow? Do you really have a chiffre where you dont know, if PKCS#7 padding was added or not?
The problem is from my point of view, if we would offer such check method, we run decrypt two times, one in this check and one after it for getting the result. Than an option for a facultative padding would be better but result in a more complex interface.

Kas Ob. 28. Dez 2024 14:07

AW: Kleines Weihnachtsgeschenk von der DEC
 
Zitat:

Zitat von Christoph Schneider (Beitrag 1544601)
To your second proposal. What is the workflow? Do you really have a chiffre where you dont know, if PKCS#7 padding was added or not?

No, i don't have specific logic where we are in doubt if there is a PKCS7 padding or not, this should not be the case.

Zitat:

Zitat von Christoph Schneider (Beitrag 1544601)
The problem is from my point of view, if we would offer such check method, we run decrypt two times, one in this check and one after it for getting the result. Than an option for a facultative padding would be better but result in a more complex interface.

My suggestion is small cosmetic, the refactor i suggested is based on the fact PKCS7 padding is used in few other places not just symmetric encryption or in PKCS7 CMS itself, this padding is the most used in asymmetric encryption and signing, also it is de facto the most used data padding scheme in general, so extracting the check for validity will be helpful, instead of repeating that loop, we can have a tidy small check for validity and correctness, .... well naming could be better like HasValidPKCS7Padding (i missed typed it as HasValidPKCS7).

Kas Ob. 28. Dez 2024 14:13

AW: Kleines Weihnachtsgeschenk von der DEC
 
One more thing i missed up there,
Signing and hashing in many case does need padding and in this case we don't need to extract, we need the correctness check only.
Have a look at this question and answers
https://crypto.stackexchange.com/que...y-need-padding

Fun stuff :)

TurboMagic 28. Dez 2024 14:29

AW: Kleines Weihnachtsgeschenk von der DEC
 
Would you like to suggest some code for the implementation of this check?

Kas Ob. 28. Dez 2024 15:55

AW: Kleines Weihnachtsgeschenk von der DEC
 
Zitat:

Zitat von TurboMagic (Beitrag 1544606)
Would you like to suggest some code for the implementation of this check?

Just looked again and saw that this padding handling is declared as private, and this makes things weird to begin with, PKCS7 padding scheme might be its own class as auxiliary.

Looking more.. i can't find more direct and correct way to add this class except in DECFormat, but all classes there are TFormat_XXX so it might be TFormat_PKCS7Padder ( had to check for padder as word, and it does exist), well it is not up to me to decide naming.

The checker is exactly as you did it, the last byte value is repeated "value" times, it should not be 0 and obviously can't be more than 255, so implementing it is trivial, but with an important thing in mind:

There is no scheme or standard in my recollection that demand a limitation, meaning PKCS7 padding when used for symmetric encryption then the target padded size must be satisfy
n*blocksize; n > 0
and this in contrary to the most usual usage of pad to one block size, so for AES the minimum padding is 1 byte to satisfy the full length to a multiply of 16 bytes, but it could be 32, 48... and will still correct and valid,(many stick to pad AES encryption to one block), the scheme by its design when de-padding (removing the padding) will remove all the residue, although not PKCS7 but in TOR as example padding done up to 512 or a multiple of 512 byte for obfuscation, same can be used with PKCS7 you can choose to pad to 128 bytes so all entries in db no matter how long names or addresses are encrypted as the same size.

back to suggested class, in case you decided to add it as separate class, it should accept block_size as optional input (parameter) along the data, so
block_size =0 then the checking or the loop will only make sure the all last trailing k bytes have the value k and k >0
block_size >0 then the checking will be the same as above with extra check that length of the data length is equal to block_size * m, because in this case the size must be padded (aligned)

that is it, removing the padding by truncating the data length by k, padding is the same, so for padding, it could have the block size parameter along with requested length, the actual padding must be more or equal to than the requested length and equal to multiple block size, padding length can't be more than 255 bytes.

TurboMagic 28. Dez 2024 20:17

AW: Kleines Weihnachtsgeschenk von der DEC
 
I do not really like the idea to implement this padding as a new format class.
While padding could be used outside block ciphers it would be really uncommon
in my eyes. Using the format classes outside that scenario is not so uncommon.

PKCS#7 btw. is defined in RFC 5652, which can be found here:
https://tools.ietf.org/html/rfc5652

Kas Ob. 29. Dez 2024 07:22

AW: Kleines Weihnachtsgeschenk von der DEC
 
Zitat:

Zitat von TurboMagic (Beitrag 1544618)
I do not really like the idea to implement this padding as a new format class.
While padding could be used outside block ciphers it would be really uncommon
in my eyes. Using the format classes outside that scenario is not so uncommon.

PKCS#7 btw. is defined in RFC 5652, which can be found here:
https://tools.ietf.org/html/rfc5652

Well that is up to you, but on side note most well known libraries do use padding classes as external implementation away from any specific implementation, example, the famous BouncyCastle
https://downloads.bouncycastle.org/j...erPadding.html
https://downloads.bouncycastle.org/j...S7Padding.html

But again, if DEC doesn't do any padding and currently is internal for symmetric encryption then no need to expand on this, and the only missing feature to to pad to more than one block, as i explained above, this nice feature to harden the encryption by obfuscation the length, but this is up top to you to introduce.

Christoph Schneider 30. Dez 2024 16:07

AW: Kleines Weihnachtsgeschenk von der DEC
 
I propose now to introduce a new class abstract class TPadding and a derived class TPKCS7Padding with the following 3 methods:
Code:
class function AddPadding(const Data: TBytes; BlockSize: integer): TBytes; override;
class function HasValidPadding(const Data: TBytes; BlockSize: integer): boolean; override;
class function RemovePadding(const Data: TBytes; BlockSize: integer): TBytes; override;
These classes will be implemented in the DECCipherBase unit and can also be used in the future for asymmetric encryption algorithms, if someone is able to implement a modern algorithm post quantum allgorithm.

TurboMagic 1. Jan 2025 20:22

AW: Kleines Weihnachtsgeschenk von der DEC
 
Hello,

happy new year to all!
The proposed abstract class has been implemented meanwhile and our little joint venture
refactored it out into a separate unit now, to help keeping a good overview.

This also means everybody is invited to add further padding algorithms, especially
if they're standardized ;-)

I hope this is as requested now and the only things missing are the documentation and
some unit tests. The former is already being worked on btw. ;-)

Cheers

TurboMagic

Kas Ob. 2. Jan 2025 14:14

AW: Kleines Weihnachtsgeschenk von der DEC
 
Well, here my thought on how this can be, and sorry again it is here.

@TurboMagic , you are the maintainer so it is up to you for naming and length limiting, the limit i mentioned in earlier posts, for me the whole padding scheme is critical, well when it is critical, see the point of using padding is to protect the data integrity, and the code below does that, only it is relaxed for its usage (a little)

also from https://crypto.stackexchange.com/que...o7816-and-x923
Zitat:

If used in an unauthenticated scheme, the bytes should be checked for correctness, since some attacker advantage could be achieved through their manipulation. Verification is done with bitwise OR against those bytes, which then must either equal 0x00 for ANSI or the length byte for PKCS#7 padding.
Both only support up to 255 bytes of padding.
So my proposed implementation is about both usage, you can strict the checking by applying the BlockSize for a value above 0, also combining the usage with MinLength, makes these useful, for the limit padding lengths (PKCS#7,PKCS#5) and none limited lengths like ISO-7816 (the one known as 1zero)

Delphi-Quellcode:
{*****************************************************************************
  The DEC team (see file NOTICE.txt) licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License. A copy of this licence is found in the root directory
  of this project in the file LICENCE.txt or alternatively at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied. See the License for the
  specific language governing permissions and limitations
  under the License.
*****************************************************************************}
unit DECCipherPaddings;
{$INCLUDE DECOptions.inc}

interface

uses
  {$IFDEF FPC}
  SysUtils,
  {$ELSE}
  System.SysUtils,
  {$ENDIF}
  DECRandom,
  DECTypes;

type
  /// <summary>
  ///   Base class for implementing block padding algorithms.
  /// </summary>
  /// <remarks>
  ///   Padding algorithms are used to fill data to a specific block size when the
  ///   data length is not an integer multiple of the block size.
  ///   This abstract class defines the basic interfaces for adding, validating,
  ///   and removing padding.
  /// </remarks>
  TDECPadding = class abstract
  protected
    class procedure DoPadding(var Data : TBytes;
                              Start : Integer); virtual; abstract;
  public
    /// <summary>
    ///   Adds padding to the specified data to align it with the given block size.
    /// </summary>
    /// <param name="Data">
    ///   The data to be padded.
    /// </param>
    /// <param name="BlockSize">
    ///   The block size to align the data with.
    /// </param>
    /// <returns>
    ///   The padded data.
    /// </returns>
    /// <remarks>
    ///   The specific method of padding depends on the implementation of the subclass.
    /// </remarks>
    class function AddPadding(const Data : TBytes;
                              BlockSize : Integer;
                              MinLength : Integer = 0): TBytes; overload; virtual; abstract;

    // <summary>
    ///   Adds PKCS#7 padding to a string.
    /// </summary>
    /// <param name="data">
    ///   The string to which padding should be added.
    /// </param>
    /// <param name="BlockSize">
    ///   The block size in byte to align the data with.
    /// </param>
    /// <returns>
    ///   A new byte string with PKCS#7 padding applied.
    /// </returns>
    /// <remarks>
    ///   PKCS#7 padding, as defined in RFC 5652 (which updates RFC 2315), adds
    ///   bytes to the end of the data so that the total length is a multiple of
    ///   the block size. Each padding byte contains the number of padding bytes
    ///   added. For example, if 5 bytes of padding are needed, each of the 5
    ///   padding bytes will have the value $5.
    /// <para>
    ///   Call this method before starting encryption.
    //  </para>
    /// </remarks>
    class function AddPadding(const Data : string;
                              BlockSize : Integer;
                              MinLength : Integer = 0): string; overload; virtual; abstract;
    // <summary>
    ///   Adds PKCS#7 padding to a raw byte string.
    /// </summary>
    /// <param name="data">
    ///   The raw byte string to which padding should be added.
    /// </param>
    /// <param name="BlockSize">
    ///   The block size in byte to align the data with.
    /// </param>
    /// <returns>
    ///   A new byte raw byte string with PKCS#7 padding applied.
    /// </returns>
    /// <remarks>
    ///   PKCS#7 padding, as defined in RFC 5652 (which updates RFC 2315), adds
    ///   bytes to the end of the data so that the total length is a multiple of
    ///   the block size. Each padding byte contains the number of padding bytes
    ///   added. For example, if 5 bytes of padding are needed, each of the 5
    ///   padding bytes will have the value $5.
    /// <para>
    ///   Call this method before starting encryption.
    /// </para>
    /// </remarks>
    class function AddPadding(const Data : RawByteString;
                              BlockSize : Integer;
                              MinLength : Integer = 0): RawByteString; overload; virtual; abstract;
    /// <summary>
    ///   Checks if the specified data contains valid padding.
    /// </summary>
    /// <param name="Data">
    ///   The data to be checked.
    /// </param>
    /// <param name="BlockSize">
    ///   The expected block size.
    /// </param>
    /// <returns>
    ///   True if the padding is valid; otherwise, False.
    /// </returns>
    /// <remarks>
    ///   This method is used to ensure the integrity and consistency of the padding.
    /// </remarks>
    class function HasValidPadding(const Data : TBytes;
                                   BlockSize : Integer = 0): Boolean; virtual; abstract;
    /// <summary>
    ///   Removes padding from the specified data.
    /// </summary>
    /// <param name="Data">
    ///   The data from which padding will be removed.
    /// </param>
    /// <param name="BlockSize">
    ///   The block size in bytes used for padding.
    /// </param>
    /// <returns>
    ///   The original data without padding.
    /// </returns>
    /// <remarks>
    ///   This method assumes that the padding has already been validated.
    /// </remarks>
    class function RemovePadding(const Data : TBytes;
                                 BlockSize : Integer = 0): TBytes; overload; virtual; abstract;
    // <summary>
    ///   Removes PKCS#7 padding from a raw byte string.
    /// </summary>
    /// <param name="data">
    ///   The padded byte raw byte string.
    /// </param>
    /// <param name="BlockSize">
    ///   The block size in bytes used for padding.
    /// </param>
    /// <returns>
    ///   A new raw byte string with the padding removed. Raises an exception
    ///   if the padding is invalid.
    /// </returns>
    /// <exception cref="EDECCipherException">
    ///   Raised if the padding is invalid or missing.
    /// </exception>
    /// <remarks>
    ///   This function checks for valid PKCS#7 padding and raises an
    ///   `EDECCipherException` exception if the padding is incorrect. This
    ///   includes cases where the final bytes do not match the pad count or if
    ///   the pad count is greater than the block size.
    ///   <para>
    ///     Call this method after decryption.
    ///   </para>
    /// </remarks>
    class function RemovePadding(const Data : RawByteString;
                                 BlockSize : Integer = 0): RawByteString; overload; virtual; abstract;
    // <summary>
    ///   Removes PKCS#7 padding from a string.
    /// </summary>
    /// <param name="data">
    ///   The padded byte raw byte string.
    /// </param>
    /// <param name="BlockSize">
    ///   The block size in bytes used for padding.
    /// </param>
    /// <returns>
    ///   A new raw byte string with the padding removed. Raises an exception
    ///   if the padding is invalid.
    /// </returns>
    /// <exception cref="EDECCipherException">
    ///   Raised if the padding is invalid or missing.
    /// </exception>
    /// <remarks>
    ///   This function checks for valid PKCS#7 padding and raises an
    ///   `EDECCipherException` exception if the padding is incorrect. This
    ///   includes cases where the final bytes do not match the pad count or if
    ///   the pad count is greater than the block size.
    ///   <para>
    ///     Call this method after decryption.
    ///   </para>
    /// </remarks>
    class function RemovePadding(const Data : string;
                                 BlockSize : Integer = 0): string; overload; virtual; abstract;
  end;

  TDECPaddingCommon = class(TDECPadding)
  protected
    class function CalculatePaddingLength(DataLength : Integer ;
                                    BlockSize: Integer;
                                    MinLength: Integer = 0): Integer;
  public
    class function AddPadding(const Data: string;
                              BlockSize: Integer;
                              MinLength : Integer = 0): string; override;
    class function AddPadding(const Data : RawByteString;
                              BlockSize : Integer;
                              MinLength : Integer = 0): RawByteString; override;
    class function RemovePadding(const Data : string;
                                 BlockSize : Integer = 0): string; override;
    class function RemovePadding(const Data : RawByteString;
                                 BlockSize : Integer = 0): RawByteString; override;
  end;


  /// <summary>
  ///   Implementation of the PKCS7 padding algorithm.
  /// </summary>
  /// <remarks>
  ///   PKCS7 padding is a standard algorithm used in symmetric cryptosystems like AES.
  ///   It appends the number of padding bytes as the value of the padding itself.
  /// </remarks>
  TDECPKCS7Padding = class(TDECPaddingCommon)
  protected
    class procedure DoPadding(var Data : TBytes;
                              Start : Integer); reintroduce; virtual;
  public
    /// <summary>
    ///   Adds PKCS7 padding to the specified data.
    /// </summary>
    /// <param name="Data">
    ///   The data to be padded.
    /// </param>
    /// <param name="BlockSize">
    ///   The block size in byte to align the data with.
    /// </param>
    /// <returns>
    ///   The padded data following the PKCS7 algorithm.
    /// </returns>
    class function AddPadding(const Data: TBytes; BlockSize: Integer; MinLength:
        Integer = 0): TBytes; override;
    /// <summary>
    ///   Checks if the specified data contains valid padding.
    /// </summary>
    /// <param name="Data">
    ///   The data to be checked.
    /// </param>
    /// <param name="BlockSize">
    ///   The expected block size.
    /// </param>
    /// <returns>
    ///   True if the padding is valid; otherwise, False.
    /// </returns>
    /// <remarks>
    ///   This method is used to ensure the integrity and consistency of the padding.
    /// </remarks>
    class function HasValidPadding(const Data : TBytes;
                                   BlockSize : Integer = 0): Boolean; override;
    /// <summary>
    ///   Removes PKCS7 padding from the specified data.
    /// </summary>
    /// <param name="Data">
    ///   The data from which padding will be removed.
    /// </param>
    /// <param name="BlockSize">
    ///   The block size used for padding.
    /// </param>
    /// <exception cref="EDECCipherException">
    ///   Raised if the padding is invalid or missing.
    /// </exception>
    /// <returns>
    ///   The original data without padding.
    /// </returns>
    class function RemovePadding(const Data : TBytes;
                                 BlockSize : Integer = 0): TBytes; override;
  end;

  TDECPKCS5Padding = class(TDECPaddingCommon)
  protected
    class procedure DoPadding(var Data : TBytes;
                              Start : Integer); reintroduce; virtual;
  public
    class function AddPadding(const Data: TBytes; BlockSize: Integer; MinLength:
        Integer = 0): TBytes; override;
    class function HasValidPadding(const Data : TBytes;
                                   BlockSize : Integer = 0): Boolean; override;
    class function RemovePadding(const Data : TBytes;
                                 BlockSize : Integer = 0): TBytes; override;
  end;

// https://www.ibm.com/docs/en/linux-on-systems?topic=processes-ansi-x923-cipher-block-chaining
// https://crypto.stackexchange.com/questions/61689/what-is-ansi-x-923-padding-standard
// Doesn't need specific fill for padding (like random, 0, or soecific value) but limited to block size of 8
  TDECANSIX923Padding = class(TDECPaddingCommon)
  protected
    class procedure DoPadding(var Data : TBytes;
                              Start : Integer); reintroduce; virtual;
  public
    class function AddPadding(const Data: TBytes; BlockSize: Integer; MinLength:
        Integer = 0): TBytes; override;
    class function HasValidPadding(const Data : TBytes;
                                   BlockSize : Integer = 0): Boolean; override;
    class function RemovePadding(const Data : TBytes;
                                 BlockSize : Integer = 0): TBytes; override;
  end;

  // both are limited to 8 bytes in their original references so both should not be used with AES or any modern standard
  // but many modern uses and implementation remove this limitiation
  // for Ansi X9.23 random fill used here, but in many implmentation it is zero, while ISO 10126 is random fill
  TDECISO10126Padding = class(TDECPaddingCommon)
  protected
    class procedure DoPadding(var Data : TBytes;
                              Start : Integer); reintroduce; virtual;
  public
    class function AddPadding(const Data: TBytes; BlockSize: Integer; MinLength:
        Integer = 0): TBytes; override;
    class function HasValidPadding(const Data : TBytes;
                                   BlockSize : Integer = 0): Boolean; override;
    class function RemovePadding(const Data : TBytes;
                                 BlockSize : Integer = 0): TBytes; override;
  end;


  TDECISO7816Padding = class(TDECPaddingCommon)
  protected
    class procedure DoPadding(var Data : TBytes; Start : Integer); reintroduce; virtual;
  public
    class function AddPadding(const Data: TBytes; BlockSize: Integer; MinLength:
        Integer = 0): TBytes; override;
    class function HasValidPadding(const Data : TBytes;
                                   BlockSize : Integer = 0): Boolean; override;
    class function RemovePadding(const Data : TBytes;
                                 BlockSize : Integer = 0): TBytes; override;
  end;

  TDECOneZeroesPadding = TDECISO7816Padding;

  // W3C padding mainly used in XML encryption
  // https://www.w3.org/TR/xmlenc-core1/#sec-Padding
  // It require arbitrary fill (can be random), so we can use our ISO 10126
  TDECW3CPadding = TDECISO10126Padding;


// additional resources
// https://www.cryptosys.net/pki/manpki/pki_paddingschemes.html
// https://crypto.stackexchange.com/questions/31372/what-are-the-relative-merits-of-padding-algorithms-pkcs7-iso7816-and-x923
implementation

uses
  DECUtil;

{ TPaddingCommon }

class function TDECPaddingCommon.CalculatePaddingLength(DataLength, BlockSize, MinLength: Integer): Integer;
begin
  if (MinLength < 0) or (DataLength < 0) or (BlockSize < 0) or (MinLength or BlockSize = 0) then
  begin
    Result := -1;
  end
  else if MinLength <= DataLength then
  begin
    Result := DataLength + BlockSize - (DataLength mod BlockSize);
  end
  else
  begin
    Result := MinLength;
    if BlockSize > 0 then
      Result := Result + BlockSize - ((MinLength - 1) mod BlockSize) - 1;
  end;
end;

class function TDECPaddingCommon.AddPadding(const Data: RawByteString; BlockSize, MinLength: Integer): RawByteString;
var
  Buf: TBytes;
begin
  Buf := AddPadding(RawStringToBytes(Data), BlockSize);
  Result := BytesToRawString(Buf);
  ProtectBytes(Buf);
end;

class function TDECPaddingCommon.AddPadding(const Data: string; BlockSize, MinLength: Integer): string;
var
  Buf: TBytes;
begin
  Buf := AddPadding(StringToBytes(Data), BlockSize);
  Result := BytesToString(Buf);
  ProtectBytes(Buf);
end;

class function TDECPaddingCommon.RemovePadding(const Data: RawByteString; BlockSize: Integer = 0): RawByteString;
var
  Buf: TBytes;
begin
  Buf := RemovePadding(RawStringToBytes(Data), BlockSize);
  Result := BytesToRawString(Buf);
  ProtectBytes(Buf);
end;

class function TDECPaddingCommon.RemovePadding(const Data: string; BlockSize: Integer = 0): string;
var
  Buf: TBytes;
begin
  Buf := RemovePadding(StringToBytes(Data), BlockSize);
  Result := BytesToString(Buf);
  ProtectBytes(Buf);
end;


{ TPKCS7Padding }

class procedure TDECPKCS7Padding.DoPadding(var Data: TBytes; Start: Integer);
var
  I: Integer;
  PadByte: Byte;
begin
  PadByte := Length(Data) - Start;

  if PadByte < 1 then
    raise EDECCipherException.Create('Invalid PKCS#7 Padding operation');

  for I := Start to High(Data) do
    Data[I] := PadByte;
end;

class function TDECPKCS7Padding.AddPadding(const Data: TBytes; BlockSize: Integer; MinLength: Integer = 0): TBytes;
var
  ResLength: Integer;
begin
  ResLength := CalculatePaddingLength(Length(Data), BlockSize, MinLength);

  if (ResLength < 0) or (ResLength - Length(Data) > 255) then
    raise EDECCipherException.Create('Invalid PKCS#7 Padding operation');

  SetLength(Result, ResLength);

  if Length(Data) > 0 then
    Move(Data[0], Result[0], Length(Data));

  DoPadding(Result, Length(Data));
end;

class function TDECPKCS7Padding.HasValidPadding(const Data: TBytes; BlockSize: integer = 0): boolean;
var
  PadLength: Integer;
  I: Integer;
begin
  Result := False;
  if (Length(Data) = 0) or ((BlockSize > 0) and (Length(Data) mod BlockSize <> 0)) then
    exit;

  PadLength := Data[High(Data)];
  for I := Length(Data) - PadLength to High(Data) do
    if Data[I] <> PadLength then
      exit;

  Result := True;
end;

class function TDECPKCS7Padding.RemovePadding(const Data: TBytes; BlockSize: integer = 0): TBytes;
var
  PadLength: Integer;
begin
  if not HasValidPadding(Data, BlockSize) then
    raise EDECCipherException.Create('Invalid PKCS#7 padding');
  PadLength := Data[High(Data)];
  SetLength(Result, Length(Data) - PadLength);
  if length(Result) > 0 then
    Move(Data[0], Result[0], Length(Result));
end;


{ TDECPKCS5Padding }

class procedure TDECPKCS5Padding.DoPadding(var Data: TBytes; Start: Integer);
var
  I: Integer;
  PadByte: Byte;
begin
  PadByte := Length(Data) - Start;

  // limiting PadByte to less 8 is the correct form , but its usage is really outdated, by removing this
  // but by removing the limit we almost have the PKCS7, which should be used instead
  if (PadByte < 1) {or (PadByte>8)} then
    raise EDECCipherException.Create('Invalid PKCS#5 Padding operation');

  for I := Start to High(Data) do
    Data[I] := PadByte;
end;

class function TDECPKCS5Padding.AddPadding(const Data: TBytes; BlockSize, MinLength: Integer): TBytes;
var
  ResLength: Integer;
begin
  ResLength := CalculatePaddingLength(Length(Data), BlockSize, MinLength);

  if (ResLength < 0) or (ResLength - Length(Data) > 255) then
    raise EDECCipherException.Create('Invalid PKCS#5 Padding operation');

  SetLength(Result, ResLength);

  if Length(Data) > 0 then
    Move(Data[0], Result[0], Length(Data));

  DoPadding(Result, Length(Data));
end;

class function TDECPKCS5Padding.HasValidPadding(const Data: TBytes; BlockSize: Integer): Boolean;
var
  PadLength: Integer;
  I: Integer;
begin
  Result := False;
  if (Length(Data) = 0) or ((BlockSize > 0) and (Length(Data) mod BlockSize <> 0)) then
    exit;

  PadLength := Data[High(Data)];
  if PadLength > 8 then   // PKCS5 is outdated and limited to 8 bytes
    Exit;

  for I := Length(Data) - PadLength to High(Data) do
    if Data[I] <> PadLength then
      exit;

  Result := True;
end;

class function TDECPKCS5Padding.RemovePadding(const Data: TBytes; BlockSize: Integer): TBytes;
var
  PadLength: Integer;
begin
  if not HasValidPadding(Data, BlockSize) then
    raise EDECCipherException.Create('Invalid PKCS#5 padding');
  PadLength := Data[High(Data)];
  SetLength(Result, Length(Data) - PadLength);
  if length(Result) > 0 then
    Move(Data[0], Result[0], Length(Result));
end;


{ TANSIX923Padding }

class procedure TDECANSIX923Padding.DoPadding(var Data: TBytes; Start: Integer);
var
  PadByte: Byte;
begin
  PadByte := Length(Data) - Start;

  if PadByte < 1 then
    raise EDECCipherException.Create('Invalid ANSI X9.23 Padding operation');

  //RandomBuffer(Data[Start], PadByte);   // comment for zero fill

  Data[High(Data)] := PadByte;
end;

class function TDECANSIX923Padding.AddPadding(const Data: TBytes; BlockSize, MinLength: Integer): TBytes;
var
  ResLength: Integer;
begin
  {if (BlockSize <> 8) and (MinLength mod 8 <> 0)and ((Length(Data)-MinLength) >= 8) then // for limiting the length to one block of 8 bytes
    raise EDECCipherException.Create('Invalid ANSI X9.23 Padding operation'); }
  ResLength := CalculatePaddingLength(Length(Data), BlockSize, MinLength);

  if (ResLength < 0) or (ResLength - Length(Data) > 255) then
    raise EDECCipherException.Create('Invalid ANSI X9.23 Padding operation');

  SetLength(Result, ResLength);

  if Length(Data) > 0 then
    Move(Data[0], Result[0], Length(Data));

  DoPadding(Result, Length(Data));
end;

class function TDECANSIX923Padding.HasValidPadding(const Data: TBytes; BlockSize: Integer): Boolean;
var
  PadLength: Integer;
begin
  Result := False;
  {if (Length(Data) = 0) or ((BlockSize <> 8)and (BlockSize<>0) and (Length(Data) mod BlockSize <> 0)) then  // for limiting the length to one block of 8 bytes
    exit; }
  if (Length(Data) = 0) or ((BlockSize > 0) and (Length(Data) mod BlockSize <> 0)) then
    exit;

  PadLength := Data[High(Data)];

  {if PadLength > 8 then            // for limiting the length to one block of 8 bytes
    Exit;}
  if PadLength > Length(Data) then
    Exit;

  Result := True;
end;

class function TDECANSIX923Padding.RemovePadding(const Data: TBytes; BlockSize: Integer): TBytes;
var
  PadLength: Integer;
begin
  if not HasValidPadding(Data, BlockSize) then
    raise EDECCipherException.Create('Invalid ANSI X9.23 padding');

  PadLength := Data[High(Data)];
  SetLength(Result, Length(Data) - PadLength);

  if length(Result) > 0 then
    Move(Data[0], Result[0], Length(Result));
end;


{ TDECISO10126Padding }

class procedure TDECISO10126Padding.DoPadding(var Data: TBytes; Start: Integer);
var
  PadByte: Byte;
begin
  PadByte := Length(Data) - Start;

  if PadByte < 1 then
    raise EDECCipherException.Create('Invalid ISO 10126 Padding operation');

  RandomBuffer(Data[Start], PadByte);

  Data[High(Data)] := PadByte;
end;

class function TDECISO10126Padding.AddPadding(const Data: TBytes; BlockSize, MinLength: Integer): TBytes;
var
  ResLength: Integer;
begin
  ResLength := CalculatePaddingLength(Length(Data), BlockSize, MinLength);

  if (ResLength < 0) or (ResLength - Length(Data) > 255) then
    raise EDECCipherException.Create('Invalid ISO 10126 Padding operation');

  SetLength(Result, ResLength);

  if Length(Data) > 0 then
    Move(Data[0], Result[0], Length(Data));

  DoPadding(Result, Length(Data));
end;

class function TDECISO10126Padding.HasValidPadding(const Data: TBytes; BlockSize: Integer): Boolean;
var
  PadLength: Integer;
begin
  Result := False;
  if (Length(Data) = 0) or ((BlockSize > 0) and (Length(Data) mod BlockSize <> 0)) then
    exit;

  PadLength := Data[High(Data)];

  if PadLength > Length(Data) then
    Exit;

  Result := True;
end;

class function TDECISO10126Padding.RemovePadding(const Data: TBytes; BlockSize: Integer): TBytes;
var
  PadLength: Integer;
begin
  if not HasValidPadding(Data, BlockSize) then
    raise EDECCipherException.Create('Invalid ISO 10126 padding');

  PadLength := Data[High(Data)];
  SetLength(Result, Length(Data) - PadLength);

  if length(Result) > 0 then
    Move(Data[0], Result[0], Length(Result));
end;

{ TDECISO7816Padding }

class procedure TDECISO7816Padding.DoPadding(var Data: TBytes; Start: Integer);
begin
  Data[Start] := $80; // first bit is one followed by zeros;
end;

class function TDECISO7816Padding.AddPadding(const Data: TBytes; BlockSize, MinLength: Integer): TBytes;
var
  ResLength: Integer;
begin
  ResLength := CalculatePaddingLength(Length(Data), BlockSize, MinLength);

  if (ResLength < 0) then
    raise EDECCipherException.Create('Invalid ISO 7816 Padding operation');

  SetLength(Result, ResLength);

  if Length(Data) > 0 then
    Move(Data[0], Result[0], Length(Data));

  DoPadding(Result, Length(Data));
end;

class function TDECISO7816Padding.HasValidPadding(const Data: TBytes; BlockSize: Integer): Boolean;
var
  I: Integer;
begin
  Result := False;
  if (Length(Data) = 0) or ((BlockSize > 0) and (Length(Data) mod BlockSize <> 0)) then
    exit;

  I := High(Data);

  while I > 0 do
    if Data[I] <> 00 then
      Break
    else
      Dec(I);

  if Data[I] <> $80 then
    Exit;

  Result := True;
end;

class function TDECISO7816Padding.RemovePadding(const Data: TBytes; BlockSize: Integer): TBytes;
var
  I: Integer;
begin
  if (Length(Data) = 0) or ((BlockSize > 0) and (Length(Data) mod BlockSize <> 0)) then
    raise EDECCipherException.Create('Invalid ISO 7816 padding');

  I := High(Data);

  while I > 0 do
    if Data[I] <> 00 then
      Break
    else
      Dec(I);

  if (Data[I] <> $80) then
    raise EDECCipherException.Create('Invalid ISO 7816 padding');

  SetLength(Result, I);

  if length(Result) > 0 then
    Move(Data[0], Result[0], Length(Result));
end;

end.
Simple Project to use with that
Delphi-Quellcode:
program DECPadding;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  DECCipherPaddings,
  DECFormat,
  DECUtil;

type
  TLocalPadding = type of TDECPadding;

procedure TestPadding(PaddingClass: TLocalPadding; const Data: TBytes; BlockSize: Integer; MinLength: Integer = 0);
var
  Padded, UnPadded: TBytes;
begin
  Padded := PaddingClass.AddPadding(Data, BlockSize, MinLength);

  Writeln('Data: '#9 + IntToStr(Length(Data)) + #9' _ ' + StringOf(TFormat_HEX.Encode(Data)));
  Write('Padded:'#9 + IntToStr(Length(Padded)) + #9' _ ' + StringOf(TFormat_HEX.Encode(Padded)));

  //if not PaddingClass.HasValidPadding(Padded,16) then  // some values should fail for TPKCS7Padding ....
  if not PaddingClass.HasValidPadding(Padded) then
  begin
    Writeln(' _ Couldn''t validate !!!!');
    Exit;
  end;

  //UnPadded := PaddingClass.RemovePadding(Padded, 7);    // should raise exception for TPKCS7Padding ..
  //UnPadded := PaddingClass.RemovePadding(Padded, 16);   // should raise exception for TPKCS7Padding ..
  UnPadded := PaddingClass.RemovePadding(Padded);
  if not IsEqual(Data, UnPadded) then
    Writeln(' _ Wrong Padding !!!!')
  else
    Writeln(' _ OK');
end;

procedure TestMultiPadding(PaddingClass: TLocalPadding);
var
  Data: TBytes;
  I, J: Integer;
begin
  Writeln(#13#10 + PaddingClass.ClassName);
  for I := 0 to 35 do
  begin
    SetLength(Data, I);
    for J := Low(Data) to High(Data) do
      Data[J] := J + 55;
    TestPadding(PaddingClass, Data, 8);
  end;
  for I := 0 to 67 do
  begin
    SetLength(Data, I);
    for J := Low(Data) to High(Data) do
      Data[J] := 255 - J; //J + 55;
    TestPadding(PaddingClass, Data, 8, 64);
  end;

  Data := BytesOf('Test!');
  TestPadding(PaddingClass, Data, 16);
  TestPadding(PaddingClass, Data, 0, 23);

  Data := BytesOf('Longer Test !_1234567890');
  TestPadding(PaddingClass, Data, 16, 48);
  TestPadding(PaddingClass, Data, 0, 128);
end;

procedure TestPKCS7Padding;
begin
  TestPadding(TDECANSIX923Padding, BytesOf('Test!'), 16, 48);
  TestPadding(TDECISO7816Padding, BytesOf('Test!'), 0, 512);
  TestMultiPadding(TDECPKCS7Padding);
  TestMultiPadding(TDECPKCS5Padding);
  TestMultiPadding(TDECANSIX923Padding);
  TestMultiPadding(TDECISO10126Padding);
  TestMultiPadding(TDECISO7816Padding);
  //TestMultiPadding(TDECW3CPadding);
end;

begin
  try
    TestPKCS7Padding;
  except
    on E: Exception do
      Writeln(#13#10'Exception: ' + E.Message);
  end;

  Writeln('Done!');
  Readln;
end.
Some parts of the output
Code:
Data:  5        _ 5465737421
Padded: 48       _ 54657374210000000000000000000000000000000000000000000000000000000000000000000000000000000000002B _ OK
Data:  5        _ 5465737421
Padded: 512      _ 54657374218000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000......
...
TDECPKCS7Padding
Data:  0        _
Padded: 8        _ 0808080808080808 _ OK
Data:  1        _ 37
Padded: 8        _ 3707070707070707 _ OK
Data:  2        _ 3738
Padded: 8        _ 3738060606060606 _ OK
Data:  3        _ 373839
Padded: 8        _ 3738390505050505 _ OK
Data:  4        _ 3738393A
Padded: 8        _ 3738393A04040404 _ OK
Data:  5        _ 3738393A3B
Padded: 8        _ 3738393A3B030303 _ OK
Data:  6        _ 3738393A3B3C
Padded: 8        _ 3738393A3B3C0202 _ OK
Data:  7        _ 3738393A3B3C3D
Padded: 8        _ 3738393A3B3C3D01 _ OK
Data:  8        _ 3738393A3B3C3D3E
Padded: 16       _ 3738393A3B3C3D3E0808080808080808 _ OK
Data:  9        _ 3738393A3B3C3D3E3F
Padded: 16       _ 3738393A3B3C3D3E3F07070707070707 _ OK
Data:  10       _ 3738393A3B3C3D3E3F40
Padded: 16       _ 3738393A3B3C3D3E3F40060606060606 _ OK
Data:  11       _ 3738393A3B3C3D3E3F4041
Padded: 16       _ 3738393A3B3C3D3E3F40410505050505 _ OK
Data:  12       _ 3738393A3B3C3D3E3F404142
Padded: 16       _ 3738393A3B3C3D3E3F40414204040404 _ OK
Data:  13       _ 3738393A3B3C3D3E3F40414243
Padded: 16       _ 3738393A3B3C3D3E3F40414243030303 _ OK
Data:  14       _ 3738393A3B3C3D3E3F4041424344
Padded: 16       _ 3738393A3B3C3D3E3F40414243440202 _ OK
Data:  15       _ 3738393A3B3C3D3E3F404142434445
Padded: 16       _ 3738393A3B3C3D3E3F40414243444501 _ OK
Data:  16       _ 3738393A3B3C3D3E3F40414243444546
Padded: 24       _ 3738393A3B3C3D3E3F404142434445460808080808080808 _ OK
Data:  17       _ 3738393A3B3C3D3E3F4041424344454647
Padded: 24       _ 3738393A3B3C3D3E3F404142434445464707070707070707 _ OK
Data:  18       _ 3738393A3B3C3D3E3F404142434445464748
Padded: 24       _ 3738393A3B3C3D3E3F404142434445464748060606060606 _ OK
Data:  19       _ 3738393A3B3C3D3E3F40414243444546474849
Padded: 24       _ 3738393A3B3C3D3E3F404142434445464748490505050505 _ OK
Data:  20       _ 3738393A3B3C3D3E3F404142434445464748494A
Padded: 24       _ 3738393A3B3C3D3E3F404142434445464748494A04040404 _ OK
Data:  21       _ 3738393A3B3C3D3E3F404142434445464748494A4B
Padded: 24       _ 3738393A3B3C3D3E3F404142434445464748494A4B030303 _ OK
Data:  22       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C
Padded: 24       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C0202 _ OK
Data:  23       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D
Padded: 24       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D01 _ OK
Data:  24       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E
Padded: 32       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E0808080808080808 _ OK
Data:  25       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F
Padded: 32       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F07070707070707 _ OK
Data:  26       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50
Padded: 32       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50060606060606 _ OK
Data:  27       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F5051
Padded: 32       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50510505050505 _ OK
Data:  28       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152
Padded: 32       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515204040404 _ OK
Data:  29       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253
Padded: 32       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253030303 _ OK
Data:  30       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F5051525354
Padded: 32       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253540202 _ OK
Data:  31       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455
Padded: 32       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253545501 _ OK
Data:  32       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253545556
Padded: 40       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455560808080808080808 _ OK
Data:  33       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F5051525354555657
Padded: 40       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565707070707070707 _ OK
Data:  34       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758
Padded: 40       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758060606060606 _ OK
Data:  35       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253545556575859
Padded: 40       _ 3738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758590505050505 _ OK
Data:  0        _
Padded: 64       _ 40404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040 _ OK
Data:  1        _ FF
Padded: 64       _ FF3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F _ OK
Data:  2        _ FFFE
Padded: 64       _ FFFE3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E _ OK
Data:  3        _ FFFEFD
Padded: 64       _ FFFEFD3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D _ OK
Data:  4        _ FFFEFDFC
Padded: 64       _ FFFEFDFC3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C _ OK
Data:  5        _ FFFEFDFCFB
Padded: 64       _ FFFEFDFCFB3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B _ OK
Data:  6        _ FFFEFDFCFBFA
Padded: 64       _ FFFEFDFCFBFA3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A _ OK
Data:  7        _ FFFEFDFCFBFAF9
Padded: 64       _ FFFEFDFCFBFAF9393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939 _ OK
Data:  8        _ FFFEFDFCFBFAF9F8
Padded: 64       _ FFFEFDFCFBFAF9F83838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838 _ OK
Data:  9        _ FFFEFDFCFBFAF9F8F7
Padded: 64       _ FFFEFDFCFBFAF9F8F737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737 _ OK
Data:  10       _ FFFEFDFCFBFAF9F8F7F6
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636 _ OK
Data:  11       _ FFFEFDFCFBFAF9F8F7F6F5
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F53535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535 _ OK
Data:  12       _ FFFEFDFCFBFAF9F8F7F6F5F4
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434 _ OK
Data:  13       _ FFFEFDFCFBFAF9F8F7F6F5F4F3
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 _ OK
Data:  14       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F23232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232 _ OK
Data:  15       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131 _ OK
Data:  16       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030 _ OK
Data:  17       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EF
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EF2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F _ OK
Data:  18       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEE
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEE2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E _ OK
Data:  19       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEED
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEED2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D _ OK
Data:  20       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDEC
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDEC2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C _ OK
Data:  21       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEB
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEB2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B _ OK
Data:  22       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEA
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEA2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A _ OK
Data:  23       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE92929292929292929292929292929292929292929292929292929292929292929292929292929292929 _ OK
Data:  24       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E828282828282828282828282828282828282828282828282828282828282828282828282828282828 _ OK
Data:  25       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7272727272727272727272727272727272727272727272727272727272727272727272727272727 _ OK
Data:  26       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E62626262626262626262626262626262626262626262626262626262626262626262626262626 _ OK
Data:  27       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E525252525252525252525252525252525252525252525252525252525252525252525252525 _ OK
Data:  28       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4242424242424242424242424242424242424242424242424242424242424242424242424 _ OK
Data:  29       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E32323232323232323232323232323232323232323232323232323232323232323232323 _ OK
Data:  30       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E222222222222222222222222222222222222222222222222222222222222222222222 _ OK
Data:  31       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1212121212121212121212121212121212121212121212121212121212121212121 _ OK
Data:  32       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E02020202020202020202020202020202020202020202020202020202020202020 _ OK
Data:  33       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DF
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DF1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F _ OK
Data:  34       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDE
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDE1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E _ OK
Data:  35       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDD
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDD1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D _ OK
Data:  36       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDC
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDC1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C _ OK
Data:  37       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDB
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDB1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B _ OK
Data:  38       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDA
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDA1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A _ OK
Data:  39       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD919191919191919191919191919191919191919191919191919 _ OK
Data:  40       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8181818181818181818181818181818181818181818181818 _ OK
Data:  41       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D71717171717171717171717171717171717171717171717 _ OK
Data:  42       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D616161616161616161616161616161616161616161616 _ OK
Data:  43       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5151515151515151515151515151515151515151515 _ OK
Data:  44       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D41414141414141414141414141414141414141414 _ OK
Data:  45       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D313131313131313131313131313131313131313 _ OK
Data:  46       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2121212121212121212121212121212121212 _ OK
Data:  47       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D11111111111111111111111111111111111 _ OK
Data:  48       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D010101010101010101010101010101010 _ OK
Data:  49       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CF
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CF0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F _ OK
Data:  50       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCE
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCE0E0E0E0E0E0E0E0E0E0E0E0E0E0E _ OK
Data:  51       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECD
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECD0D0D0D0D0D0D0D0D0D0D0D0D0D _ OK
Data:  52       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCC
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCC0C0C0C0C0C0C0C0C0C0C0C0C _ OK
Data:  53       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCB
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCB0B0B0B0B0B0B0B0B0B0B0B _ OK
Data:  54       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCA
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCA0A0A0A0A0A0A0A0A0A0A _ OK
Data:  55       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9090909090909090909 _ OK
Data:  56       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C80808080808080808 _ OK
Data:  57       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C707070707070707 _ OK
Data:  58       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6060606060606 _ OK
Data:  59       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C50505050505 _ OK
Data:  60       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C404040404 _ OK
Data:  61       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3030303 _ OK
Data:  62       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C20202 _ OK
Data:  63       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1
Padded: 64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C101 _ OK
Data:  64       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0
Padded: 72       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C00808080808080808 _ OK
Data:  65       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BF
Padded: 72       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BF07070707070707 _ OK
Data:  66       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBE
Padded: 72       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBE060606060606 _ OK
Data:  67       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBD
Padded: 72       _ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBD0505050505 _ OK

TDECANSIX923Padding
Data:  0        _
Padded: 8        _ 0000000000000008 _ OK
Data:  1        _ 37
Padded: 8        _ 3700000000000007 _ OK
Data:  2        _ 3738
Padded: 8        _ 3738000000000006 _ OK
Data:  3        _ 373839
Padded: 8        _ 3738390000000005 _ OK
Data:  4        _ 3738393A
Padded: 8        _ 3738393A00000004 _ OK
Data:  5        _ 3738393A3B
Padded: 8        _ 3738393A3B000003 _ OK
Data:  6        _ 3738393A3B3C
Padded: 8        _ 3738393A3B3C0002 _ OK
Data:  7        _ 3738393A3B3C3D
Padded: 8        _ 3738393A3B3C3D01 _ OK
Data:  8        _ 3738393A3B3C3D3E
Padded: 16       _ 3738393A3B3C3D3E0000000000000008 _ OK
Data:  9        _ 3738393A3B3C3D3E3F
Padded: 16       _ 3738393A3B3C3D3E3F00000000000007 _ OK
Data:  10       _ 3738393A3B3C3D3E3F40
Padded: 16       _ 3738393A3B3C3D3E3F40000000000006 _ OK
Data:  11       _ 3738393A3B3C3D3E3F4041
Padded: 16       _ 3738393A3B3C3D3E3F40410000000005 _ OK

TDECISO10126Padding
Data:  0        _
Padded: 8        _ 4284CDE2A1FCA908 _ OK
Data:  1        _ 37
Padded: 8        _ 37F28EE75CE38507 _ OK
Data:  2        _ 3738
Padded: 8        _ 3738266443C00406 _ OK
Data:  3        _ 373839
Padded: 8        _ 3738392DF1BDEE05 _ OK
Data:  4        _ 3738393A
Padded: 8        _ 3738393A51EA4C04 _ OK
Data:  5        _ 3738393A3B
Padded: 8        _ 3738393A3BE17703 _ OK
Data:  6        _ 3738393A3B3C
Padded: 8        _ 3738393A3B3C9D02 _ OK
Data:  7        _ 3738393A3B3C3D
Padded: 8        _ 3738393A3B3C3D01 _ OK
Data:  8        _ 3738393A3B3C3D3E
Padded: 16       _ 3738393A3B3C3D3E7322A43A816EFE08 _ OK
Data:  9        _ 3738393A3B3C3D3E3F
Padded: 16       _ 3738393A3B3C3D3E3F0DD18B7CFC4707 _ OK
Data:  10       _ 3738393A3B3C3D3E3F40
Padded: 16       _ 3738393A3B3C3D3E3F402A8368130E06 _ OK
Data:  11       _ 3738393A3B3C3D3E3F4041
Padded: 16       _ 3738393A3B3C3D3E3F40414185976A05 _ OK

TDECISO7816Padding
Data:  0        _
Padded: 8        _ 8000000000000000 _ OK
Data:  1        _ 37
Padded: 8        _ 3780000000000000 _ OK
Data:  2        _ 3738
Padded: 8        _ 3738800000000000 _ OK
Data:  3        _ 373839
Padded: 8        _ 3738398000000000 _ OK
Data:  4        _ 3738393A
Padded: 8        _ 3738393A80000000 _ OK
Data:  5        _ 3738393A3B
Padded: 8        _ 3738393A3B800000 _ OK
Data:  6        _ 3738393A3B3C
Padded: 8        _ 3738393A3B3C8000 _ OK
Data:  7        _ 3738393A3B3C3D
Padded: 8        _ 3738393A3B3C3D80 _ OK
Data:  8        _ 3738393A3B3C3D3E
Padded: 16       _ 3738393A3B3C3D3E8000000000000000 _ OK
Data:  9        _ 3738393A3B3C3D3E3F
Padded: 16       _ 3738393A3B3C3D3E3F80000000000000 _ OK
Data:  10       _ 3738393A3B3C3D3E3F40
Padded: 16       _ 3738393A3B3C3D3E3F40800000000000 _ OK
Data:  11       _ 3738393A3B3C3D3E3F4041
Padded: 16       _ 3738393A3B3C3D3E3F40418000000000 _ OK
Data:  12       _ 3738393A3B3C3D3E3F404142
Padded: 16       _ 3738393A3B3C3D3E3F40414280000000 _ OK
Data:  13       _ 3738393A3B3C3D3E3F40414243
Padded: 16       _ 3738393A3B3C3D3E3F40414243800000 _ OK
Data:  14       _ 3738393A3B3C3D3E3F4041424344
Padded: 16       _ 3738393A3B3C3D3E3F40414243448000 _ OK
Data:  15       _ 3738393A3B3C3D3E3F404142434445
Padded: 16       _ 3738393A3B3C3D3E3F40414243444580 _ OK
Data:  16       _ 3738393A3B3C3D3E3F40414243444546
Padded: 24       _ 3738393A3B3C3D3E3F404142434445468000000000000000 _ OK
Notes : i added TPaddingCommon as middle layer and i am not fan of it, yet i don't want to break your own abstraction or roles, so it is up to you to keep it or expand it into the inherited or move it to the base.

Sorry again for running your code and your help, that help need to be rewritten in case you used the suggested schemes/code.

Happy and peaceful new year to everyone !

TurboMagic 2. Jan 2025 16:06

AW: Kleines Weihnachtsgeschenk von der DEC
 
Phew! Quite a lot! I still need to understand parts of it, but I'm gratefull for
your donation of other paddings!

We (Christoph and me) need to have a look at your stuff and try to understand it,
then we can make up or minds about whether to take it 1:1 or in a modified variant.

This will take a little bit of time.

About the test data used in your sample run: do you have any URLs for the srouce
of those? I'm asking because I had already learned years ago that some of the
test data in DEC (a project which I inherited btw.) was not 100% correct and thus
masked 1 or 2 bugs in DEC. I tried to find the original/official test data for the
hash algorithms then at least and was only partially successfull. But I "implemented"
what I found as original test data.

Kas Ob. 2. Jan 2025 16:55

AW: Kleines Weihnachtsgeschenk von der DEC
 
Zitat:

Zitat von TurboMagic (Beitrag 1544709)
About the test data used in your sample run: do you have any URLs for the srouce
of those? I'm asking because I had already learned years ago that some of the
test data in DEC (a project which I inherited btw.) was not 100% correct and thus
masked 1 or 2 bugs in DEC. I tried to find the original/official test data for the
hash algorithms then at least and was only partially successfull. But I "implemented"
what I found as original test data.

Alas, there is no test vector for these simple padding !, i made the tests above to check data integrity for different case, and to use BlockSize and MinLength in useful way.

As for the implementation, it is in the scattered few links in the sources above, well.. along with this too
https://en.wikipedia.org/wiki/Padding_(cryptography)

ISO(s) standards are strictly to paid access, but the description for padding is easy enough to implement.

As for test vectors, i have similar when i implement Gimli cipher block https://gimli.cr.yp.to/spec.html
and ended up with 3 versions, one published by the author, and another submitted to NIST competition LightWeight Cryptography
https://csrc.nist.gov/Projects/Lightweight-Cryptography
but in second round there was different version of these vectors

Here an answer from one of the authors
https://crypto.stackexchange.com/que...for-gimli-hash

And the reason was the permutation is the same as it should not be changed, but the difference and the confliction in the last step after perform the rounds and on padding and bit locking, the original was locking different bit, while NIST prefer their own bit locking
and here how it look like
Delphi-Quellcode:
procedure Gimli_PadThenSqueeze(GimliContext: PlcGimliState; Last: Integer); //inline;
begin
  // enable one of these padding schemes
  // 1) padding with xor'ing $1F at last byte and $80 at the end of block
  {GimliContext^.Bytes[Last] := GimliContext^.Bytes[Last] xor $1F;
  GimliContext^.Bytes[GIMLI_RATE - 1] := GimliContext^.Bytes[GIMLI_RATE - 1] xor $80;}
  //  2) padding with xor'ing 1 at the last of text with 1 at the last byte of the state
  GimliContext^.Bytes[Last] := GimliContext^.Bytes[Last] xor $1;
  GimliContext^.Bytes[GIMLI_STATE_LAST_BYTE] := GimliContext^.Bytes[GIMLI_STATE_LAST_BYTE] xor $1;
  //  3) //// removed and should not be used

  GimliPermute(GimliContext^);
end;
So i think your problem is something similar to this bit locking, SHA1 and SHA256 doesn't have these and this is great weakness for them.

Rollo62 2. Jan 2025 17:10

AW: Kleines Weihnachtsgeschenk von der DEC
 
TL;DR;

What just jump into my eye is this, cant this be written more efficient?
Delphi-Quellcode:
class function TDECPaddingCommon.CalculatePaddingLength(DataLength, BlockSize, MinLength: Integer): Integer;
begin
  if (MinLength < 0) or (DataLength < 0) or (BlockSize < 0) or (MinLength or BlockSize = 0) then
  begin
  ...
like so

Delphi-Quellcode:
class function TDECPaddingCommon.CalculatePaddingLength(DataLength, BlockSize, MinLength: Integer): Integer;
begin
  if (MinLength <= 0) or (DataLength <= 0) or (BlockSize <= 0) then
  begin
  ...
Not sure is there is any hidden math trick behind that logic, have not thought too deep into it ...

TurboMagic 2. Jan 2025 17:38

AW: Kleines Weihnachtsgeschenk von der DEC
 
Hello,

thanks for all these contributions!

1. I'm currently changing the code a bit so it will have PKCS#7 and ANSI X9.23. As they are
quite similar I'll introduce another abstract class from which these two will inherit.

2. I already had some conversation with Christoph about the submission and he rates it as
high quality but will only have time to look at it somewhen next week. So don't be disappointed
when you don't hear much (except for my implementation I'll finish and push tonight) from us.
We value that! Oh and I'll add the necessary calls in TDECCipherFormats so somewhen tonight
we at least can choose between PKCS#7 and ANSI X9.23. The other one will follow as soon as we
find the time (unfortunately there are some other things in other projects to do as well...)

3. About the more efficient code: yep, we have to think this through and if there's no math catch
somewhere we'll implement it that way.

4. And later on I need to update the documentation once again. ;-)

TurboMagic 2. Jan 2025 18:05

AW: Kleines Weihnachtsgeschenk von der DEC
 
Hello,

according to this stack exckange discussion you linked:
https://crypto.stackexchange.com/que...677d098ea2c5dd

ANSI X9.23 uses 0 as filler bytes instead of the padding length PKCS#7 uses.
If that is correct I wonder why your validity check method doesn't check for the #0
like the one for PKCS#7 checks for that specific padding byte.

I also wonder why you have a separate PKCS#5 implementation. As far as I understood so far (correct me if I'm wrong)
is PKCS#7 a superset of PKCS#5.

Kas Ob. 3. Jan 2025 07:01

AW: Kleines Weihnachtsgeschenk von der DEC
 
Zitat:

Zitat von Rollo62 (Beitrag 1544713)
TL;DR;

What just jump into my eye is this, cant this be written more efficient?
Delphi-Quellcode:
class function TDECPaddingCommon.CalculatePaddingLength(DataLength, BlockSize, MinLength: Integer): Integer;
begin
  if (MinLength < 0) or (DataLength < 0) or (BlockSize < 0) or (MinLength or BlockSize = 0) then
  begin
  ...
like so

Delphi-Quellcode:
class function TDECPaddingCommon.CalculatePaddingLength(DataLength, BlockSize, MinLength: Integer): Integer;
begin
  if (MinLength <= 0) or (DataLength <= 0) or (BlockSize <= 0) then
  begin
  ...
Not sure is there is any hidden math trick behind that logic, have not thought too deep into it ...

Simple, none of these can be negative but all can be zero, with only one condition that MinLength and BlockSize can't be zero at the same time.

Kas Ob. 3. Jan 2025 07:24

AW: Kleines Weihnachtsgeschenk von der DEC
 
Zitat:

Zitat von TurboMagic (Beitrag 1544720)
Hello,

according to this stack exckange discussion you linked:
https://crypto.stackexchange.com/que...677d098ea2c5dd

ANSI X9.23 uses 0 as filler bytes instead of the padding length PKCS#7 uses.
If that is correct I wonder why your validity check method doesn't check for the #0
like the one for PKCS#7 checks for that specific padding byte.

I also wonder why you have a separate PKCS#5 implementation. As far as I understood so far (correct me if I'm wrong)
is PKCS#7 a superset of PKCS#5.

Well, to be honest i thought about this and here what logic echoed in my brain,
Lets look at the most accurate original definition of ANSI X9.23,
from https://www.ibm.com/docs/en/linux-on...block-chaining
Zitat:

The ANSI X9.23 method always appends from 1 - 8 bytes to the plaintext before encipherment. The last appended byte is the count of the added bytes and is in the range of X'01' - X'08'. The standard defines that any other added bytes, or pad characters, be random.
also from https://en.wikipedia.org/wiki/Padding_(cryptography)
Zitat:

In ANSI X9.23, between 1 and 8 bytes are always added as padding. The block is padded with random bytes (although many implementations use 00) and the last byte of the block is set to the number of bytes added.[6]
PKCS#7 has concretely defined fill value unlike this one.
on other hand random fill can't be validated, also this padding schemes is old, very old and used many in many cases with both 0 fill and random, this exactly what rendered it unreliable to be used widely in securing traffic over wire, in fact it is not used and not recommended, these days as de facto is zero fill but yet not quit, as many php libraries (old and some are new) still use it as both zero fill and random fill, this what made me let remove the zero checking, and that is it just for legacy compatibility with older libraries from different platform,
Also as suggestion per best practice only 2 padding schemes are currently recommended, PKCS#7 and the unlimited length scheme "ISO/IEC 7816-4", both are validated and checked right.

As for PKCS#7 and PKCS#5 padding, you are right, and it is there for cosmetic, see PKCS#5 is old and was fixed at 8 bytes block size, so it even can't and shouldn't be used with AES !!, it designed for DES and 3DES...
i left it in case users of this library needed to be sure when they are in doubt and needed the name to be exist, again it is your call, also i relaxed the length checking as many libraries extended the length for it making it %100 copy of PKCS#7 padding without changing the name.

TurboMagic 3. Jan 2025 15:46

AW: Kleines Weihnachtsgeschenk von der DEC
 
Zitat:

Zitat von Kas Ob. (Beitrag 1544730)
Well, to be honest i thought about this and here what logic echoed in my brain,
Lets look at the most accurate original definition of ANSI X9.23,
from https://www.ibm.com/docs/en/linux-on...block-chaining
Zitat:

The ANSI X9.23 method always appends from 1 - 8 bytes to the plaintext before encipherment. The last appended byte is the count of the added bytes and is in the range of X'01' - X'08'. The standard defines that any other added bytes, or pad characters, be random.
also from https://en.wikipedia.org/wiki/Padding_(cryptography)
Zitat:

In ANSI X9.23, between 1 and 8 bytes are always added as padding. The block is padded with random bytes (although many implementations use 00) and the last byte of the block is set to the number of bytes added.[6]
PKCS#7 has concretely defined fill value unlike this one.
on other hand random fill can't be validated, also this padding schemes is old, very old and used many in many cases with both 0 fill and random, this exactly what rendered it unreliable to be used widely in securing traffic over wire, in fact it is not used and not recommended, these days as de facto is zero fill but yet not quit, as many php libraries (old and some are new) still use it as both zero fill and random fill, this what made me let remove the zero checking, and that is it just for legacy compatibility with older libraries from different platform.

Ok, I can fully understand this. People not properly implementing a standard are a nuisance ;-)
What about having two classes for this: one with random fill and one with zero fill for best compatibility?
Or would one variant (the one with random fill) be sufficient?

Zitat:

Zitat von Kas Ob. (Beitrag 1544730)
As for PKCS#7 and PKCS#5 padding, you are right, and it is there for cosmetic, see PKCS#5 is old and was fixed at 8 bytes block size, so it even can't and shouldn't be used with AES !!, it designed for DES and 3DES...
i left it in case users of this library needed to be sure when they are in doubt and needed the name to be exist, again it is your call, also i relaxed the length checking as many libraries extended the length for it making it %100 copy of PKCS#7 padding without changing the name.

Understood. I created a PKCS#5 class now wich is a 1:1 alias of the PCKS#7 class. Just a type definition.
Is that ok? I'll add this to the enumeration and treat it like PKCS#7.

Kas Ob. 3. Jan 2025 16:47

AW: Kleines Weihnachtsgeschenk von der DEC
 
Zitat:

Zitat von TurboMagic (Beitrag 1544774)
What about having two classes for this: one with random fill and one with zero fill for best compatibility?
Or would one variant (the one with random fill) be sufficient?

I prefer to either
1) leave with 0 fill, but without strict validation (checking against 0), as i mentioned it should not be used in real data trafficking or storing, so the danger of not checking its fill correctness make sense .. or
2) have two classes as you suggested, and i suggest to make sure to name the one with random as old or legacy, as it is really very rare to be using random fill in other libraries, and in contrary to its own original specification, which the cause of this mess.

Zitat:

Zitat von TurboMagic (Beitrag 1544774)
Understood. I created a PKCS#5 class now wich is a 1:1 alias of the PCKS#7 class. Just a type definition.
Is that ok? I'll add this to the enumeration and treat it like PKCS#7.

Absolutely OK, PKCS#5 padding should have been killed and never used since the dawn of computer cryptography.
I think it is, yes, unifying their implementation makes sense, the problem with PKCS#5 padding is the wrong implementation and naming in many libraries, they do use PKCS#7 padding under the name of PKCS#5.


And thank you and Christoph for your effort, work and contribution.

TurboMagic 5. Jan 2025 17:37

AW: Kleines Weihnachtsgeschenk von der DEC
 
We did some more work on this. Bear in mind that this is, while pushed to development branch, is not finished completely yet.
We still need to think about some of your stuff and unit tests need to be worked at as well, basing them most likely on your
data from this post.

=> stay tuned but don't hold your breath ;-)

TurboMagic 7. Jan 2025 20:14

AW: Kleines Weihnachtsgeschenk von der DEC
 
Ok, you can start breathing again ;-)
Well, I think the current version in the development branch "is it".
What we didn't take is the idea of being able to add further blocks at the end.
Christoph doesn't like to have such an unstandard extension.

Well, this of course has two sides, as nearly everything.
But: thanks for your valuable additions and the test data!

I couldn't add you to notices.txt, but only because you are already listed as
contributor ;-)

If I can find the necessary time for some cleanup in some other area of the library
this should get released as V6.5 along with the other things which got added since V6.4.x.

Kas Ob. 8. Jan 2025 09:47

AW: Kleines Weihnachtsgeschenk von der DEC
 
Big thank to you and to Christoph.

You are the maintainer and its your call.

As for non-standard extension, well you made a call and it is right, but i want to explain few things to any one here who want to encrypt data without leaking information (aka best practice and things might be missed), namely the data length,
To do that i want to give an example, lets say this forum do encrypt users name in DB using BlowFish, so a name like our respected Uwe will be 6 bytes in Unicode, encrypting the name without padding (using lets say CTR mode) will be 6 bytes, while when padded will be 8 byte (on all modes), while any name with 4 chars will be 8 bytes and padded will be 16 bytes, so short names will stand out in a table, other names like Wolfeschlegelsteinhausenbergerdorff (36 bytes) will be unique too at 80 padded byte, but if we padded every name to 80 byte, meaning all names up to 39 chars will be the same, and this will prevent any information leak, or at least will decrease the chance to perform any useful information analysis to isolate and differentiate users and their other stored data.

Also when you pushed the separation for padding into its own unit, i had to say my opinion and wrote that code out of now or never, as it is pushed to development, and of course if padding in your current target is for only cipher and what had been standardized, then it is not wrong at all and you call is the right one, as there is no wrong call here, but if you want to leave it with some flexibility to be used with not only block cipher then, lets say this in other words .. some one had to read my very this post to understand how to obfuscate and protect a batch encryption, and even after that he will need to perform/implement the padding (a padding) code on his own !, and that is it.

Thank you again.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:52 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz