a) 四
让我先说您可能正在尝试解决一个不需要解决的问题。密码箱 3 是自动加盐的。这意味着在大多数情况下,会自动生成一个 64 位随机数并将其插入 IV。随机数值通过插入密文流的方式传输。结果是您可以使用 TCodec 组件而无需编写单行代码来管理 IV,并且您仍然可以获得加盐的所有加密优势(基本上意味着不可预测的 IV)。这与 DCPCrypt 形成对比,在 DCPCrypt 中,您要么将 IV 归零,要么自行管理 IV。
我无法想象除了“已知测试答案”测试之外的场景,您希望或需要覆盖此行为,但话虽如此,如果您真的想坚持设置自己的 IV,如果您有 cvs 客户端,您可以下载修订版 231(尚未“稳定发布”状态),并实现 TCodec 组件的 OnSetIV() 事件处理程序以将 IV 设置为您的自定义值。由于 IV 与消息一起传输,因此在解密时无需执行此步骤。
如果您想要一些演示代码,请告诉我。
b)填充(从第一篇文章中更正。抱歉错误。)
这取决于链接方法。当使用标准流到块适配器时,在以下情况下处理终止。
零长度消息被加密为零长度密文。
对于 ECB 模式 Lockbox 3 使用 ISO/IEC 9797-1 方法 2 填充。ISO/IEC 9797-1 方法 2 本质上是一个字节的填充,其值为 $80,后跟到达下一个块边界所需的零字节。
没有填充。不需要特殊的终止处理。
没有填充。通过截断处理终止。
没有填充。终止是通过密文窃取来处理的,这“对学校来说太酷了”!如果消息太短而无法窃取密文(少于 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;
需要注意的几点:
- 假设您在设计时可能在表单上预先创建了 TCodec 和 TCryptographicLibrary(建议命名)。
- TCodec 的链接模式和其他属性已在设计时设置。对于我们的测试向量,它应该设置为 CBC 。
- 给定的流到块适配器是一个特殊的适配器,通常不包含在密码库中。这就是为什么有一行代码可以显式注册它的原因。
- 您将需要一个 CVS 客户端从 TurboPower LockBox 3 CVS 存储库下载最新版本。这个适配器还没有在正式的稳定版本中。
- 使用此适配器,您只能解密。CSharp 兼容的加密尚不可用。(让我知道您是否需要尽早而不是稍后)。
- 我在 Delphi 2007 和 Delphi 2010 上对其进行了测试。它对我有用。
更正
最大短消息长度,即对于经典密文流将被视为太短的明文消息的最大长度,因此将其链接模式视为密钥流(CFB 8位),是一字节小于一个块,(不是前面所说的“小于 2 个块”)。一个半块消息仍然可以使用密文窃取作为其块量化方法。半块消息不能。