【问题标题】:How to compress a random string?如何压缩随机字符串?
【发布时间】:2014-03-20 23:22:18
【问题描述】:

我正在开发一个基于 RSA 非对称算法的加密器应用程序。 它生成一个密钥对,用户必须保留它。 由于密钥对是长随机字符串,我想创建一个函数,让我根据模式压缩生成的长随机字符串(密钥对)。

(例如函数获取一个包含100个字符的字符串,返回一个包含30个字符的字符串)

所以当用户输入压缩字符串时,我可以根据我压缩的模式重新生成密钥对。

但是有人告诉我,不可能压缩随机的东西,因为它们是随机的!

你的想法是什么? 有什么办法吗?

谢谢

【问题讨论】:

  • 那个人是对的。您应该阅读信息论和熵。
  • 好吧,如果它是随机的,那么你就有一个随机的机会来压缩它!
  • 最简单的答案是尝试压缩它们,看看你得到了什么,看看它是否足够好。需要注意的是,压缩算法通常产生二进制输出而不是字符串。您可以使用 BASE64 编码将二进制转换为字符串,但这会导致 25% (IIRC) 的通货膨胀损失。你仍然可能会得到更短的字符串 - 取决于它的内容。
  • 我不是密码学方面的专家,但您尝试做的是将压缩从 100 个字符的密钥变为 30 个字符的密钥。如果您依赖攻击者不知道您的“功能”,那么这将永远不会起作用:en.wikipedia.org/wiki/Security_through_obscurity
  • 有些数据是可压缩的,有些则不是。您不能期望每次都有一定程度的压缩。

标签: c# .net string compression


【解决方案1】:

压缩(几乎所有)随机数据是不可能的。稍微了解一下信息论、熵、压缩的工作原理以及鸽笼原理,就会非常清楚。

此规则的一个例外是“随机字符串”是指“以可压缩形式表示的随机数据,例如十六进制”。在这种情况下,您可以压缩字符串或(更好的选择)简单地将字节编码为 base 64,而不是使其更短。例如

// base 16, 50 random bytes (length 100)
be01a140ac0e6f560b1f0e4a9e5ab00ef73397a1fe25c7ea0026b47c213c863f88256a0c2b545463116276583401598a0c36
// base 64, same 50 random bytes (length 68)
vgGhQKwOb1YLHw5KnlqwDvczl6H+JcfqACa0fCE8hj+IJWoMK1RUYxFidlg0AVmKDDY=

您可以改为给用户一个较短的哈希值或指纹值(例如最后 x 个字节)。然后通过将完整的密钥和哈希存储在某处,您可以在他们给您哈希时给他们密钥。您必须让这个哈希值足够长,以免影响安全性。根据您的应用程序,这可能会破坏目的,因为散列必须与密钥一样长,否则可能不是问题。

【讨论】:

  • 这确实似乎是更好、更安全的工作方式,甚至可能将它们与 GUID 相关联,而不是密钥的哈希。
  • @woutervs 可能,是的,但 GUID 不是一个安全的东西。 It's mostly pseudorandom now,但不是加密安全的。生成的适当长度的安全伪随机数也可以工作。
  • 是的,但我纯粹是针对,将其存储在某处,在这种情况下,我认为 GUID 可能更适合引用实际密钥。据我所知,这与安全无关。当然,从客户端到客户端的密钥传输应该是安全的。 (例如通过 WCF 使用传输/消息安全)。
【解决方案2】:
public static string ZipStr(String str)
{
    using (MemoryStream output = new MemoryStream())
    {
        using (DeflateStream gzip = 
          new DeflateStream(output, CompressionMode.Compress))
        {
            using (StreamWriter writer = 
              new StreamWriter(gzip, System.Text.Encoding.UTF8))
            {
                writer.Write(str);           
            }
        }

        return Convert.ToBase64String(output.ToArray());
    }
}

public static string UnZipStr(string base64)
{
    byte[] input = Convert.FromBase64String(base64);

    using (MemoryStream inputStream = new MemoryStream(input))
    {
        using (DeflateStream gzip = 
          new DeflateStream(inputStream, CompressionMode.Decompress))
        {
            using (StreamReader reader = 
              new StreamReader(gzip, System.Text.Encoding.UTF8))
            {
                return reader.ReadToEnd();
            }
        }
    }
}

考虑到这根本不需要更短...取决于字符串的内容。

【讨论】:

    【解决方案3】:

    尝试使用 gzip 压缩,看看是否有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-08
      • 1970-01-01
      • 2015-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多