基于密钥的简单文本文件加密

8
我正在尝试实现一个简单的文本文件加密技术,我正在使用以下代码进行操作。这段代码不是我编写的,我只是通过谷歌搜索得到了它。这种加密技术似乎非常简单、简洁和易于实现。我看到它只有一个函数可以在运行时进行加密和解密。只需传递密钥即可完成操作。然而,我想知道,是否有可能检查用户传递的密钥是否正确。目前它只会根据传递的密钥加密/解密文本文件。但是没有机制来检查我们是否使用正确的密钥进行解密。无论我们传递什么密钥,它都将被解密,但它将无法读取。有什么办法解决这个问题吗?
procedure TEnDeCrypt.EnDecryptFile(pathin, pathout: string; Chave: Word);
var
  InMS, OutMS: TMemoryStream;
  cnt: Integer;
  C: byte;
begin
  InMS  := TMemoryStream.Create;
  OutMS := TMemoryStream.Create;
  try
    InMS.LoadFromFile(pathin);
    InMS.Position := 0;
    for cnt := 0 to InMS.Size - 1 DO
      begin
        InMS.Read(C, 1);
        C := (C xor not (ord(chave shr cnt)));
        OutMS.Write(C, 1);
      end;
    OutMS.SaveToFile(pathout);
  finally
    InMS.Free;
    OutMS.Free;
  end;
end;

2
不是我干的,但这种加密方式并不是很安全,也不值得投资。它更像是混淆而非加密。至于你真正的问题:没有办法,因为你没有真正的密钥系统可以在不包含秘密部分的情况下进行安全认证。 - Marco van de Voort
1
@jimsweb 这是我很久以前写的东西,如果我没记错的话,它是用 D7 写的。下载源代码和二进制版本,玩得开心!http://www.delphigeist.com/2010/09/filestream-compressiondecompression.html - user497849
3
请参考encrypt-decrypt-text-file-in-delphi了解更多信息。 - LU RD
2
我通常使用dcpcrypt中的AES加密。 - Marco van de Voort
1
@jimsweb,你应该直接问这个问题,而不是让读者猜测你的意图。显然,你有两个不同的问题,后一个(使用多表代换进行校验和)我觉得非常有趣。请分而治之。 - OnTheFly
显示剩余5条评论
3个回答

7

如果您知道文件将包含哪种内容(是二进制文件/文本文件等),则可以对文本进行取样并查看解密后文件中是否存在任何非ASCII或不符合预期的字符。

另一件事情是在文件末尾添加水印文本。解密后,您可以检查水印是否包含了超出预期数据类型的数据(如果您只期望字符,但在其中看到了非字符数据,则可能存在问题)。这虽然不是百分之百可靠,但可以起到某种缓冲作用。

话虽如此,我想问您一个问题-这背后的意图是什么?用户传递的密钥是用于加密的;因此,如果用户传递了无效密钥,则会得到无效输出。为什么要引导用户使用正确的密钥?如果有某些业务用例需要这样做,那么您还需要了解这会使您的加密变得很容易被破解。我建议您选择标准的加密算法来加密文件。


感谢Gangadhar的宝贵建议。
  • 这个应用程序没有商业用途。这是我的爱好应用程序。
- jimsweb

7
使用哈希算法在明文上生成校验和,并将其存储在加密文件的开头。
您可以通过对解密后的文本进行哈希并确保校验和匹配来验证密钥。
如果使用强哈希算法(例如SHA256)生成校验和,用户很难自动执行暴力攻击,因为这将是计算上昂贵的。
为确保文件完整性,您可能还希望在加密文件上存储校验和,并在文件头中存储它。否则,将无法区分无效密码和截断文件。
我通常使用Blowfish加密算法,该算法可从多个来源获取Delphi。 Blowfish没有已知的弱点,而且相当紧凑且快速。

2
你所要求的正确方法是对数据进行加密,然后进行认证。这里有一些相关讨论: 我们应该先进行MAC再加密还是先加密再进行MAC? 传统的方法是首先使用标准密码算法,如AES在CBC模式下,然后计算密文的HMAC(如HMAC-SHA256)。还有一些密码模式,如CCM、EAX、GCM,可以同时执行加密和认证。 不要使用哈希代替HMAC。
你用于加密的密钥必须与用于认证的密钥独立。例如,你可以随机生成两个密钥,但绝对不能使用System.Random函数。如果你部署到Vista SP2或更高版本,则可以使用Windows API中的CryptGenRandom,否则应该使用支持加密随机数生成的加密库。
如果你使用基于密码的加密,请使用PBKDF2实现来派生加密密钥和认证密钥。有四种常见的方法来确保这两个密钥是独立的:
  • 使用两个单独的Salt值;
  • 使用一个Salt但将其与单独的“标签”连接,例如字符串'E'和'A';
  • 生成两倍长的派生密钥,并将一半用作加密密钥,另一半用作认证密钥;或者
  • 让派生密钥成为你用于加密随机生成的加密密钥和认证密钥的“密钥加密密钥”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接