Turbopower Lockbox3 - 我可以控制AES-256加密的初始化向量和填充吗?

时间:2012-06-01 09:30:17

标签: delphi aes lockbox-3

在从Delphi2007迁移到XE2的过程中,我们正考虑将加密库从DCPCrypt切换到Turbopower Lockbox 3。

a)在DCPCrypt中,我可以明确控制初始化向量。我如何在TPLB3中设置IV?

b)DCPCrypt没有填充,我们在加密前用明文填充明文。 TPLB如何填充?我们当然可以自己做。

测试载体

  • 密码= AES-256;
  • 链接模式= CBC;
  • 终止= C#样式全零填充;
  • IV传输=在密文流中以明文开头的完整块。
  • Key = 33d46cffa158533194214a91e712fc2b45b587076675affd910edeca5f41ac64 little-endien
  • IV = 917fe226df8308f4d96c33304768354a
  • Ciphertext = + kdTGzdV5KZIw8tv466nhQ ==(base64)
  • Plaintext ='a_decent_text'(ansistring)

由于 扬

1 个答案:

答案 0 :(得分:3)

a)IV

让我先说你可能正试图解决一个不需要解决的问题。 Lockbox 3是自动加盐的。这意味着在大多数情况下会自动生成64位nonce并将其插入IV。通过插入密文流来传输随机数值。结果是您可以使用TCodec组件而无需编写单行代码来管理IV,并且您仍然可以获得salting的所有加密优势(基本上意味着不可预测的IV)。这与DCPCrypt形成鲜明对比,在DCPCrypt中,您要么将IV归零,要么自行管理IV。

我无法想象一个场景,除了“已知的测试答案”测试,你想要或需要覆盖这种行为,但话虽如此,如果你真的想坚持设置你自己的IV,如果你有在cvs客户端,您可以下载修订版231(尚未“稳定版本”状态),并实现TCodec组件的OnSetIV()事件处理程序以将IV设置为您的自定义值。由于IV与消息一起传输,因此在解密时不需要执行此步骤。

如果您需要一些演示代码,请告诉我。

b)填充(从第一篇帖子更正。抱歉错误。)

这取决于链接方法。使用标准的流到块适配器时,在以下情况下处理终止。

  • 零长度消息

零长度消息被加密为零长度密文。

  • ECB模式

对于ECB模式,Lockbox 3使用ISO / IEC 9797-1方法2填充。 ISO / IEC 9797-1方法2本质上是一个字节的填充,其值为$ 80,后跟到达下一个块边界所需的零字节。

  • 不是ECB,但是消息是块对齐的

没有填充。不需要特殊的终止处理。

  • 密钥流模式(例如OFB)

没有填充。终止由截断处理。

  • 其他(例如CBC)

没有填充。终止是通过密文窃取来处理的,这对于学校来说“太酷了”!如果消息对于密文窃取来说太短(少于2个块),那么它会自动切换到CFB-8位并视为密钥流。


更新

买者

LockBox 3从未设计用于与CSharp样式的用户管理IV和全零填充的互操作性。 (恕我直言,这种类型的填充是有问题的,应避免使用)。

以下代码片段演示了LockBox3从注释中给出的测试向量进行解密。假设密文流前置有完整的IV,并且加密编解码器使用(令人讨厌的)全零填充。

procedure TForm5.Button1Click(Sender: TObject);
const
  Key: ansistring = #$33#$d4#$6c#$ff#$a1#$58#$53#$31#$94#$21#$4a#$91#$e7#$12#$fc#$2b +
                       #$45#$b5#$87#$07#$66#$75#$af#$fd#$91#$0e#$de#$ca#$5f#$41#$ac#$64;
  Reference_Plaintext: ansistring = 'a_decent_text';
  IV: ansistring = #$91#$7f#$e2#$26#$df#$83#$08#$f4#$d9#$6c#$33#$30#$47#$68#$35#$4a;
var
  Stream, ReconStream: TStream;
  Cipherb64: ansistring;
  Recon_Plaintext: ansistring;
begin
Stream := TMemoryStream.Create;
Stream.WriteBuffer( Key[1], Length( Key));
Stream.Position := 0;
CryptographicLibrary1.RegisterStreamCipher( StreamToBlock_Adapter_CSharpVariant);
Codec1.StreamCipherId := 'CSharp.StreamToBlock';
Codec1.BlockCipherId  := Format( AES_ProgId, [256]);
Codec1.InitFromStream( Stream);
Stream.Size := 0;
Stream.WriteBuffer( IV[1], Length( IV));
Cipherb64 := '+kdTGzdV5KZIw8tv466nhQ==';
Base64_to_stream( Cipherb64, Stream);
ReconStream := TMemoryStream.Create;
Stream.Position := 0;
Codec1.DecryptStream( ReconStream, Stream);
ReconStream.Position := 0;
SetLength( Recon_Plaintext, ReconStream.Size);
ReconStream.ReadBuffer( Recon_Plaintext[1], Length( Recon_Plaintext));
SetLength( Recon_Plaintext, StrLen( PAnsiChar( Recon_Plaintext)));
ReconStream.Free;
Stream.Free;
if Recon_Plaintext = Reference_Plaintext  then
    ShowMessage( 'Test passed! LockBox3 decrypts from CSharp-style zero padding.')
  else
    ShowMessage( 'Test failed!')
end;

需要注意的一些要点:

  1. 假设您已预先创建了一个TCodec和TCryptographicLibrary(暗示命名),可能在设计时在表单上。
  2. TCodec的链接模式和其他属性已在设计时设置。在我们的测试向量的情况下,它应该设置为CBC。
  3. 给定的流到块适配器是一个特殊的适配器,通常不包含在加密库中。这就是为什么有一行代码可以显式注册它。
  4. 您需要一个CVS客户端来从TurboPower LockBox 3 CVS存储库下载最新版本。此适配器尚未正式发布。
  5. 使用此适配器,您只能解密。 CSharp兼容加密尚不可用。 (如果您需要早点而不是晚点,请告诉我。)
  6. 我在Delphi 2007和Delphi 2010上测试过它。它对我有用。

  7. 校正

    最大短消息长度,即明文消息的最大长度,对于经典密文流来说将被视为太短,因此它的链接模式被视为密钥流式传输(CFB 8位) ,是一个字节小于一个块,(如前所述,不是“少于2个块”)。一个半块消息仍然可以使用密文窃取来进行块量化方法。半块消息不能。