当前位置: 首页 > 面试题库 >

合并或不合并Java加密服务提供者

尉迟兴修
2023-03-14
问题内容
  • MessageDigest =>根据需要频繁创建新实例
  • KeyFactory =>使用单个共享实例
  • SecureRandom =>使用StackObjectPool
  • 密码=>使用StackObjectPool

在对安全 框架 进行编码时,我经常遇到两难的问题:“ 合并还是不合并”

基本上,这个问题分为两个“组”:

  1. 第1组:SecureRandom因为对的调用nextBytes(...)是同步的,并且可能成为WebApp /多线程应用程序的瓶颈

  2. 第2组:加密服务提供商,如MessageDigestSignatureCipherKeyFactory,…(因为成本的getInstance()?)

你有什么意见 ?

您对这些问题有什么习惯?

编辑09/07/2013

我终于花了一些时间独自测试@Qwerky Share类,我发现结果相当……令人惊讶。

该类缺少我的主要关注:GenericObjectPool或StackObjectPool之类的池。

因此,我对课程进行了重新设计,以测试所有4种选择:

  • 具有同步要点的单个共享实例
  • 每个环内的新实例(我不是在案件感兴趣时,你可以拉环外的摘要生成)要点
  • GenericObjectPool:要点
  • StackObjectPool:要点

由于1M在池中花费了太多时间,因此我不得不将循环数降低到100000。

我还在Thread.yield()每个循环的末尾添加了一个,以使负载具有更好的形状。

结果(累计运行时间):

  • 信息摘要
    • 新实例:420秒
    • 一次实例:550秒
    • StackObjectPool:800秒
    • GenericObjectPool:1900秒
  • 密钥工厂
    • 新实例:400秒
    • 一次实例:350秒
    • StackObjectPool:2900秒
    • GenericObjectPool:3500秒
  • 安全随机
    • StackObjectPool:1600秒
    • 新实例:2300秒
    • GenericObjectPool:2300秒
    • 单实例:2800秒
  • 密码
    • StackObjectPool:2800秒
    • GenericObjectPool:3500秒
    • 单实例:5100秒
    • 新实例:8000秒

结论

对于MessageDigest和KeyFactory而言,池是性能的杀手,甚至比具有同步瓶颈的单个实例还要糟糕,而对于SecureRandom和Cipher来说,它们确实非常有用


问题答案:

如果让100个线程访问一个共享,MessageDigest并让它们分别计算1,000,000个哈希,则在我的计算机上,第一个线程完成70,160ms,最后一个完成98,748ms。

如果线程MessageDigest每次都创建一个新实例,那么第一个线程将在43,392ms内完成,最后一个58,691ms。

编辑:
实际上,在此示例中,只有两个线程,该示例创建新实例的运行速度更快。

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Share {

  final byte[] bytes = new byte[100];
  final MessageDigest sharedDigest;
  final ExecutorService pool;
  int threads = 100;

  Share() throws NoSuchAlgorithmException {
    sharedDigest = MessageDigest.getInstance("MD5");
    pool = Executors.newFixedThreadPool(threads);
  }

  void go() {

    for (int i=0; i<threads; i++) {
      pool.execute(new Runnable() {
        public void run() {
          long start = System.currentTimeMillis();
          for (int i=0; i<1000000; i++) {
            /*
            synchronized (sharedDigest) {
              sharedDigest.reset();
              sharedDigest.update(bytes);
              sharedDigest.digest();
            }*/
            try {
              MessageDigest digest = MessageDigest.getInstance("MD5");
              digest.reset();
              digest.update(bytes);
              digest.digest();
            } catch (Exception ex) {
              ex.printStackTrace();
            }
          }
          long end = System.currentTimeMillis();
          System.out.println(end-start);
          pool.shutdown();
        }
      });
    }

  }

  public static void main(String[] args) throws Exception {
    Share share = new Share();
    share.go();
  }

}


 类似资料:
  • 图表视图 该视图直观地显示发布服务器及其订阅服务器的层次结构和关系。将鼠标悬停在订阅服务器上以显示其同步状态。 实例块和箭头以颜色表示复制的不同状态。 绿色块表示服务器已启动(稳定)。 红色块表示服务器已关闭。 绿色箭头表示事务复制已启动,并且订阅服务器与其发布服务器保持同步。 红色箭头表示事务复制已关闭(断开),并且订阅服务器可能未能与其发布服务器保持同步。 黑色箭头表示合并复制。 【提示】使用

  • 返回当前有效的通信服务提供器。 调用: web3.providers web3.eth.providers web3.shh.providers web3.bzz.providers ... 返回值: Object, 参见以下服务提供器对象: Object - HttpProvider: HTTP服务提供器已经被弃用,因为它不支持订阅。 Object - WebsocketProvider: W

  • 问题内容: 我整个上午都在搜索,但是大多数合并示例仅基于一个键,而在多个键上却找不到任何东西。 pid = 111,sid = 6,eid = 123的值在x和y中都匹配,然后合并为一条记录。如果它们不匹配,只需将其原样带过来。 我想要的最终结果: 问题答案: 这是从元组中重新锁定:

  • 我不熟悉XSLT和XPath,正在努力编写一个样式表来合并两个文件。 对于这个问题,我只想用一个简单的例子来说明我正在努力解决的概念,而不是我的实际数据。假设我有两个xml文件,其中包含独立但相关的数据。作者。xml和书籍。xml。作者。xml包含作者的集合,以及关于他们的一些基本信息,而书籍。xml包含一个书籍集合,其中包含有关书籍的信息(重要的是,包括作者)。 我希望得到一个包含作者集合的XM

  • 把两个分支合并到一块儿。你为了新想法,新功能,或者修复项目的 bug 创建了一些分支,最终你还是希望把这些分支合并到主分支上。Git 有几种合并算法,Fast-Forward 合并,3-Way 合并。 git merge 分支 练习 1,Fast-Forward 合并练习。介绍分支的时候我们创建了一个新分支叫 smiley-face,在这个分支上做了一次提交。这期间在主分支(master)上没发

  • 合并有时会产生冲突. 通常这些冲突很容易解决, 你也必须得去解决, 不然你的版本库就会变成多头怪 (多个最新版本). 有谁希望自己肩膀上扛着好几个脑袋? 合并 版本管理的一个重要功能是帮助多人团队进行协同代码开发. 假设 Rose 和我都想修改鳄梨酱的配方. Rose 想提高鳄梨的品质标准. 于是她把中央库最新的变更都获取了下来, 现在她的本地库是最新的: C:\Users\rose\recipe