代码之家  ›  专栏  ›  技术社区  ›  David Cornelius

密码箱3加密与联机工具不匹配,可能是填充或密钥问题

  •  0
  • David Cornelius  · 技术社区  · 7 年前

    我有一个客户机提供了一个API,它要求发送给他们的数据必须用 . 我试图在Delphi10.3Rio中使用密码箱3,但没有得到与 online test tool 他们指出要核实。很近,但不太近。

    这里有很多关于 Unicode , PKCS5Padding ,和 related questions

    有几件事我想确认一下:

    • 密码和密钥的区别
    • PKCS5添加 LB3 Help site 也就是说,填充是根据密码、链接模式等的选择而智能地完成的,那么这是否意味着没有办法强制它使用特定的填充方法?我已经将数据转换为字节数组,并由自己的PKCS5Padding实现,但我认为LB3可能仍在填充。(我试过查看代码,但没有发现任何证据,这就是它所做的。)

    我应该在Delphi中使用不同的加密库来完成这个任务吗? 我已经退房了 DelphiEncryptionCompendium DcPCryptV2

    为了说明我所做的尝试,我将代码从项目中提取到一个控制台应用程序中。也许我上面的假设是正确的,我的代码或LB3参数中有一个明显的错误,我不明白有人会指出:

    program LB3ConsoleTest;
    
    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      System.SysUtils, System.Classes, System.NetEncoding,
      uTPLb_Codec, uTPLb_CryptographicLibrary,
      uTPLb_StreamUtils, uTPLb_Constants;
    
    var
      Codec: TCodec;
      CryptographicLibrary: TCryptographicLibrary;
    
    function PKCS5PadStringToBytes(RawData: string; const PadSize: Integer): TBytes;
    { implement our own block padding }
    var
      DataLen: Integer;
      PKCS5PaddingCount: ShortInt;
    begin
      Result := TEncoding.UTF8.GetBytes(RawData);
      DataLen := Length(RawData);
    
      PKCS5PaddingCount := PadSize - DataLen mod PadSize;
      if PKCS5PaddingCount = 0 then
        PKCS5PaddingCount := PadSize;
      Inc(DataLen, PKCS5PaddingCount);
    
      SetLength(Result, DataLen);
      FillChar(Result[DataLen - PKCS5PaddingCount], PKCS5PaddingCount, PKCS5PaddingCount);
    end;
    
    procedure InitializeAESKey(const AESKey: string);
    { convert the string to a byte array,
      use that to initialize a ByteStream,
      and call LB3's InitFromStream }
    var
      AESKeyBytes: TBytes;
      AESKeyStream: TBytesStream;
    begin
      AESKeyBytes := TEncoding.UTF8.GetBytes(AESKey);
      AESKeyStream := TBytesStream.Create(AESKeyBytes);
      Codec.InitFromStream(AESKeyStream);
    end;
    
    const
      RawData = '{"invoice_id":"456456000018047","clerk_id":"0023000130234234","trans_amount":1150034534,"cust_code":"19455605000987890641","trans_type":"TYPE1"}';
      AESKeyStr = 'CEAA31AD1EE4BDC8';
    var
      DataBytes: TBytes;
      DataStream: TBytesStream;
      ResultStream: TBytesStream;
      ResultBytes: TBytes;
      Base64Encoder: TBase64Encoding;
    begin
      // create the LockBox3 objects
      Codec := TCodec.Create(nil);
      CryptographicLibrary := TCryptographicLibrary.Create(nil);
      try
        // setup LB3 for AES, 128-bit key, ECB
        Codec.CryptoLibrary := CryptographicLibrary;
        Codec.StreamCipherId := uTPLb_Constants.BlockCipher_ProgId;
        Codec.BlockCipherId  := Format(uTPLb_Constants.AES_ProgId, [128]);
        Codec.ChainModeId    := uTPLb_Constants.ECB_ProgId;
    
        // prep the data, the key, and the resulting stream
        DataBytes := PKCS5PadStringToBytes(RawData, 8);
        DataStream := TBytesStream.Create(DataBytes);
        InitializeAESKey(AESKeyStr);
        ResultStream := TBytesStream.Create;
    
        // ENCRYPT!
        Codec.EncryptStream(DataStream, ResultStream);
    
        // take the result stream, convert it to a byte array
        ResultStream.Seek(0, soFromBeginning);
        ResultBytes := Stream_to_Bytes(ResultStream);
    
        // convert the byte array to a Base64-encoded string and display
        Base64Encoder := TBase64Encoding.Create(0);
        Writeln(Base64Encoder.EncodeBytesToString(ResultBytes));
    
        Readln;
      finally
        Codec.Free;
        CryptographicLibrary.Free;
      end;
    end.
    

    online tool 生产。

    为什么?

    0 回复  |  直到 7 年前
        1
  •  1
  •   Arnaud Bouchez    7 年前

    AES使用16字节块,而不是8字节块。

    所以需要16字节填充的PKCS7,而不是固定为8字节的PKCS5。

    DataBytes := PKCS5PadStringToBytes(RawData, 16);
    

    同时考虑改变与欧洲央行的联系方式, which is pretty weak, so is to be avoided for any serious work .

    推荐文章