【问题标题】:Memcache key generation strategyMemcache 密钥生成策略
【发布时间】:2011-02-08 07:21:05
【问题描述】:

给定函数 f1 接收 n 个字符串参数,就运行时性能而言,什么会被认为更好,memcache 的随机密钥生成策略?

我们的 Memcache 客户端对其获取的键执行内部 md5sum 散列:

   public class MemcacheClient {  
       public Object get(String key) {
            String md5 = Md5sum.md5(key)
            // Talk to memcached to get the Serialization... 
            return memcached(md5);
       }
   }

我的使用场景是:

第一个选项

    public static String f1(String s1, String s2, String s3, String s4) {
         String key = s1 +  s2 + s3 + s4;
         return get(key);
    }

第二个选项

    /**
     * Calculate hash from Strings
     *
     * @param objects vararg list of String's
     *
     * @return calculated md5sum hash
     */
    public static String stringHash(Object... strings) {
        if(strings == null) 
            throw new NullPointerException("D'oh! Can't calculate hash for null");

        MD5 md5sum = new MD5();

//      if(prevHash != null)
//          md5sum.Update(prevHash);

        for(int i = 0; i < strings.length; i++) {
            if(strings[i] != null) {
                md5sum.Update("_"); 
                md5sum.Update(strings[i].toString()); // Convert to String...
                md5sum.Update("_");

            } else {
                // If object is null, allow minimum entropy  by hashing it's position
                md5sum.Update("_");
                md5sum.Update(i);
                md5sum.Update("_");
            }
        }

        return md5sum.asHex();
    }


    public static String f1(String s1, String s2, String s3, String s4) {
         String key = stringHash(s1, s2, s3, s4);
         return get(key);
    }

请注意,第二个选项的可能问题是我们正在对已经 md5sum 的摘要结果进行第二次 md5sum(在 memcache 客户端中)。

感谢阅读, 马克西姆。

-- 编辑 使用MD5 utility source

【问题讨论】:

    标签: java algorithm md5 memcached


    【解决方案1】:

    “更好”在什么意义上?为什么您认为第二个选项“更好”?它做了更多的字符串连接,更多的 MD5 哈希,而且通常看起来比第一个效率低得多......

    【讨论】:

    • 我不同意。在第一个选项中,我正在执行字符串连接,这意味着我正在复制内存而不创建另一个将被 GC 处理的字符串实例。在第二个选项中,我正在做 md5sum,这是一种廉价的数学运算。对于“更好”,我指的是运行时 BigO 性能。
    • 请将“without”更正为“thus”,应为“...复制内存,从而创建...的另一个实例”
    • 我已编辑问题以更好地解释“更好”。感谢您的评论。
    • @Maxim:你在第二个版本中做 more 字符串连接:"_" + strings[i] + "_" 每个字符串两个!
    • @Ants: 也许吧,但a + b + c + d 也将被编译器优化为与string.Concat(a, b, c, d) 等效的java。
    【解决方案2】:

    只是吹毛求疵,但您可能不想要随机密钥生成,密钥生成应该是确定性,但应该生成均匀分布 在关键空间中。

    如果您只考虑意外碰撞,那么第一种方法几乎没问题。您应该在字符串前面加上它们的长度,这样当子字符串从一个参数移动到另一个参数时,您就不会发生冲突。鉴于 md5 非常好的雪崩特性,这将确保意外碰撞非常罕见,可以忽略不计。

    但是,如果您处理用户输入,请小心使用 MD5,因为它具有已知的冲突攻击。如果不受信任的用户可以为函数参数选择一些任意字节并返回错误的结果可能会产生安全隐患,那么您就有了安全漏洞。例如,如果您使用它来缓存授权信息,攻击者可以计算出两组散列为单个值的参数。一个会访问公共的东西,而另一个会访问受保护的服务。现在只需使用第一组请求授权,获取缓存的授权,然后使用另一组访问受保护的服务,从缓存的授权中收到绿灯。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-30
      • 2013-08-31
      • 2019-08-24
      • 1970-01-01
      • 2014-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多