池化还是不池化 java 加密服务提供商

2024-01-29

Solution

  • MessageDigest => 根据需要经常创建新实例
  • KeyFactory => 使用单个共享实例
  • SecureRandom => 使用堆栈对象池 http://commons.apache.org/proper/commons-pool/apidocs/org/apache/commons/pool/impl/StackObjectPool.html
  • 密码 => 使用堆栈对象池 http://commons.apache.org/proper/commons-pool/apidocs/org/apache/commons/pool/impl/StackObjectPool.html

Question

我在编写安全代码时经常遇到困境构架:“池或不池”

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

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

  2. 第 2 组:加密货币服务提供商,例如MessageDigest, Signature, Cipher, KeyFactory,...(因为成本getInstance() ?)

你有什么意见 ?

你对此类问题有什么习惯?

编辑 09/07/2013

我终于花时间测试了@QwerkyShare我自己上课,我发现结果相当......令人惊讶。

这门课缺乏我主要关心的内容:像游泳池这样的通用对象池 http://commons.apache.org/proper/commons-pool/apidocs/org/apache/commons/pool/impl/GenericObjectPool.html or 堆栈对象池 http://commons.apache.org/proper/commons-pool/apidocs/org/apache/commons/pool/impl/StackObjectPool.html.

所以我重新设计了课程来测试所有 4 个替代方案:

  • 具有同步功能的单个共享实例gist https://gist.github.com/GrmpCerber/5956460
  • 每个循环内的新实例(我对可以将摘要创建拉到循环之外的情况不感兴趣)gist https://gist.github.com/GrmpCerber/5956464
  • 通用对象池:gist https://gist.github.com/GrmpCerber/5956444
  • 堆栈对象池:gist https://gist.github.com/GrmpCerber/5956417

我必须将循环数降低到 100000,因为 1M 占用池的时间太多。

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

结果(累积运行时间):

  • MessageDigest
    • 新实例:420 秒
    • 单实例:550秒
    • StackObjectPool:800秒
    • 通用对象池:1900 秒
  • KeyFactory
    • 新实例:400s
    • 单实例:350秒
    • 堆栈对象池:2900 秒
    • 通用对象池:3500 秒
  • SecureRandom
    • 堆栈对象池:1600 秒
    • 新实例:2300 秒
    • 通用对象池:2300s
    • 单实例:2800秒
  • Cipher
    • 堆栈对象池:2800 秒
    • 通用对象池:3500 秒
    • 单实例:5100秒
    • 新实例:8000秒

结论

对于 MessageDigest 和 KeyFactory,池是性能杀手,甚至比具有同步瓶颈的单个实例更糟糕,而当涉及到 SecureRandom 和 Cipher 时,它们确实非常有用


如果你给 100 个线程访问共享MessageDigest让它们分别计算 1,000,000 个哈希值,然后在我的机器上,第一个线程在 70,160 毫秒内完成,最后一个线程在 98,748 毫秒内完成。

如果线程创建一个新实例MessageDigest每次,第一个线程在 43,392 毫秒内完成,最后一个线程在 58,691 毫秒内完成。

Edit:
事实上,在这个示例中,只有两个线程,创建新实例的示例运行得更快。

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();
  }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

池化还是不池化 java 加密服务提供商 的相关文章

随机推荐

  • 如何显示合并提交中所做更改的差异?

    当我编写一堆代码时 我没有意识到我正处于合并过程中 现在git log p不会向我显示此更改的差异 它作为合并提交自动提交 我怎样才能让它显示在我的日志差异历史记录中 有点令人失望的是 Git 没有向您显示用于合并的补丁 p 部分原因是由
  • 如何正确更改 Microsoft Azure 中的 SSH 端口?

    我有一个基于 Ubuntu 14 04 LTS 的虚拟机 用于测试 而不是生产服务器 Azure 上默认打开默认 SSH 端口 22 我想将其更改为 12131 我编辑了 SSH 配置文件并将端口更改为 12131 然后通过以下方式重新加载
  • 集成陀螺仪和加速度计读数[重复]

    这个问题在这里已经有答案了 可能的重复 结合陀螺仪和加速度计数据 https stackoverflow com questions 1586658 combine gyroscope and accelerometer data 我读过很
  • 使用 Python 查找单词列表的字谜

    假设我有一个字符串列表 例如 car tree boy girl arc 等等 我想在该列表中找到字谜组 在这种情况下 car arc 我尝试编写代码来循环列表并比较字符串对 但如何解释字母可以采用不同顺序的事实 For the speci
  • 从数据库创建 Grails 域类

    我想从现有数据库创建 grails 域类 通常我是从域类创建数据库 现在我需要从现有数据库模式创建它 如果有可用的命令 请帮助我 我遇到了同样的问题 我发现这个 Grails 插件 https web archive org web 201
  • PHP 解析 XML 时出错(RSS 提要)

    我正在使用基于的 PHP 类在这个答案中找到的 https stackoverflow com questions 250679 best way to parse rss atom feeds with php解析五个 RSS 提要 五人
  • 关闭模态视图

    如果我没记错的话 模态视图必须从父视图中消除 而不是从模态视图本身中消除 在我当前的项目中 我有两个模式视图 在第一个中 我将数据传递给父视图 当数据传递到父视图时 执行dismiss 现在 我有另一个模态视图 它不将数据传递给父视图 所以
  • 处理 WebBrowser 控件上的按键事件?

    目前我正在使用一个可以播放的应用程序ppt并在 WebBrowser 控件中闪烁 在 WebBrowser 中 我可以使用隐藏上下文菜单 this IsWebBrowserContextMenuEnabled false 并使用捕获关键事件
  • 如何捕获 Sequelize 连接错误

    如果存在续集连接错误 如何捕获续集连接错误 我尝试做 var connection new Sequelize db uri connection on error function perhaps reconnect here 但显然这不
  • Akka Stream 和 Kamon-Prometheus 不返回任何指标,但加载空页面

    我尝试将 kamon prometheus 与 akka Stream 项目集成 但在http 本地主机 9095 http localhost 9095 它加载一个空页面 在控制台中 我可以看到一条消息 表明指标信息可在http 本地主机
  • 在 Windows 上使用 HDF5 库和 CMake(错误:“无法找到 HDF5”)

    我想在我的 C 程序中使用 HDF5 库 我在Windows 7上使用VS 2010 x64编译器和CMake 3 8 0rc2 我安装的HDF5版本是1 8 10 通过运行官方 安装程序 安装 在我的 CMakeLists 文件中 我添加
  • 如何在 Laravel 中执行 MYSQL 查询?

    我有一个 MYSQL 查询 我想在 laravel 中执行这个查询 select d1 update id from select update id count update id as ct from updates tags wher
  • 为什么 GCC 说“不再支持命名返回值”?

    我不小心将函数定义的左大括号放在 return 语句之后 int id int k return k 但 GCC 回答了一个奇怪的错误消息 错误 不再支持命名返回值 谁能解释一下这个奇怪的功能可能是什么 我从来没有听说过 See here
  • 编程中的“阻塞”是什么意思?

    有人可以提供外行定义和用例吗 阻塞 意味着调用者等待 直到被调用者完成其处理 例如 来自套接字的 阻塞读取 会等待 直到有数据返回 非阻塞 读取不会 它只是返回是否有读取的指示 通常是计数 您听到这个术语主要是围绕 API 来访问不一定需要
  • Common lisp:有没有一种不那么痛苦的方法来输入数学表达式?

    我喜欢 Common lisp 但有时输入简单的数学表达式真的很痛苦 a 8b 2 1 4bc 4b 2 1 当然我可以转换它 但是有点慢 我先写 然后在每个括号中写 我想知道这里是否有人知道更好的输入方法 我正在考虑编写一个数学宏 其中
  • Azure 逻辑应用响应 HTTP 操作在 60 秒后超时

    我有一个非常简单的 Azure 逻辑应用程序 它对 SAP Web 服务器进行 REST 调用 并在将响应发送回逻辑应用程序的调用者之前转换响应 JSON 令我困惑的是 当 SAP 调用仅花费 1 分钟多一点时 响应操作就会抛出此错误 操作
  • Python C 程序子进程挂在“for line in iter”处

    好的 我正在尝试从 python 脚本运行 C 程序 目前我正在使用一个测试 C 程序 include
  • 为什么即使参数没有经过 URL 编码,某些查询字符串仍然可以工作?

    这是一个例子 The url范围 http journals plos org plosone s file id wjVg PLOSOne formatting sample main body pdf 未编码 它包含保留字符 例如冒号
  • 如何在android中上传PDF文件到服务器?

    我提到了一些以前提出的问题 但没有得到正确的解决方案 我正在创建一个应用程序 并希望通过从文件管理器中选择它来发送 PDF 文件 感谢任何类型的帮助 只有当您必须从图库中选择 PDF 文件时 您才需要更改这行代码 intent setTyp
  • 池化还是不池化 java 加密服务提供商

    Solution MessageDigest gt 根据需要经常创建新实例 KeyFactory gt 使用单个共享实例 SecureRandom gt 使用堆栈对象池 http commons apache org proper comm