具有大型随机密钥文件的一次性键盘聊天应用程序



我正准备使用One Time Pad构建一个简单的聊天应用程序。我已经制作了算法,为了加密消息,我需要某种双方都相同的密钥材料。密钥材料的分发应该通过物理接触(例如USB加密狗)进行。所以我想制作一些非常大的随机密钥文件,两个客户端可以用来通信。所以我的问题是:

  • 我需要一个非常安全的随机数/字符串生成器,你知道我可以在 C# 中使用的任何好的吗?
  • 当我使用这么大的文件时,我如何避免将整个文件加载到内存中,因为我计划读取密钥材料的一大块(例如 1 MB),并在读取时将其从文件中删除,这样相同的密钥就不会使用两次。

我可能应该从这个开始:我认为这是一个为了娱乐或锻炼的项目 - 而不是试图创造真正安全的东西。

  1. 正如owlstead所说:使用RNGCryptoServiceProvider。
  2. 如果反向使用,则从文件中删除使用的密钥材料要容易得多。如果需要加密 1024 个字节,请从文件中读取最后 1024 个字节并将其截断。简化:

 

byte[] Encrypt(byte[] plain){
  using (FileStream keyFile = new FileStream(FileName, FileMode.Open))
  {
    keyFile.Seek(-plain.Length, SeekOrigin.End);
    byte[] key = new byte[plain.Length];
    keyFile.Read(key, 0, plain.Length);    
    byte[] encrypted = new byte[plain.Length];
    for(int i=0;i<plain.Length;i++){
      encrypted[i] = (byte) (plain[i] ^ key[plain.Length - 1 - i]);
    } 
    keyFile.SetLength(keyFile.Length - plain.Length);   
    return encrypted;
  }      
}

您正在尝试解决一个已经解决的问题:使用AES几乎可以肯定与使用一次性键盘一样安全。在这种情况下,您的密钥变为 16 个字节(尽管您需要 NONCE 或 IV,具体取决于模式)。

  1. 您需要使用安全的随机数生成器RNGCryptoServiceProvider。
  2. 使用 MemoryMappedFile 将文件读入内存。

只是(原子地)将偏移量存储在文件中。 例如,使用同一文件中的前 8 个字节来存储 ulong 类型,以便在需要时进行同步。如果您确实需要,除了使用的字节之外,您还可以在文件中写入零。请注意,例如,使用 SSD,您实际上可能不会覆盖物理数据。

你设计的几乎肯定不是一次性键盘。 生成大量真正随机的字节远非易事。 如果你真的必须走这条路,你真的应该在硬件卡上花几千美元。 即使是加密质量的 C# RNG 也无法生成如此大量的真正随机数据。 它可以足够安全地生成一个短密钥,但没有足够的熵输入来生成大量真正的随机数据。 一旦熵用完,它的输出就会恢复为伪随机,你不再有一次性键盘。

正如@owlstead所说,在CBC或CTR模式下使用AES。 这是安全的,易于获得的,不是由业余爱好者设计的。

最新更新