受信任的时间戳记是让受信任的第三方(“时间戳记权威”,TSA)以电子形式证明给定事件的时间的过程。 欧盟法规eIDAS赋予了这些时间戳合法的力量-即,如果事件带有时间戳,则没有人可以质疑事件的时间或内容。 它适用于多种情况,包括带有时间戳记的审核日志。 (注意:时间戳记不足以进行良好的审核,因为它不能阻止恶意行为者完全删除事件)

有许多用于可信时间戳的标准,核心标准是RFC 3161 。 与大多数RFC一样,很难阅读。 幸运的是,对于Java用户,BouncyCastle实现了该标准。 不幸的是,与大多数安全性API一样,使用它非常困难,甚至很糟糕。 我必须实现它,所以我将共享为数据加时间戳所需的代码。

整个要点可以在这里找到,但是我将尝试解释主要流程。 显然,有很多代码可以简单地遵循该标准。 BouncyCastle类是一个很难导航的迷宫。

主要方法显然是timestamp(hash, tsaURL, username, password, tsaPolicyOid)

public TimestampResponseDto timestamp(byte[] hash, String tsaUrl, String tsaUsername, String tsaPassword, String tsaPolicyOid) throws IOException {MessageImprint imprint = new MessageImprint(sha512oid, hash);ASN1ObjectIdentifier tsaPolicyId = StringUtils.isNotBlank(tsaPolicyOid) ? new ASN1ObjectIdentifier(tsaPolicyOid) : baseTsaPolicyId;TimeStampReq request = new TimeStampReq(imprint, tsaPolicyOid, new ASN1Integer(random.nextLong()),ASN1Boolean.TRUE, null);byte[] body = request.getEncoded();try {byte[] responseBytes = getTSAResponse(body, tsaUrl, tsaUsername, tsaPassword);ASN1StreamParser asn1Sp = new ASN1StreamParser(responseBytes);TimeStampResp tspResp = TimeStampResp.getInstance(asn1Sp.readObject());TimeStampResponse tsr = new TimeStampResponse(tspResp);checkForErrors(tsaUrl, tsr);// validate communication level attributes (RFC 3161 PKIStatus)tsr.validate(new TimeStampRequest(request));TimeStampToken token = tsr.getTimeStampToken();TimestampResponseDto response = new TimestampResponseDto();response.setTime(getSigningTime(token.getSignedAttributes()));response.setEncodedToken(Base64.getEncoder().encodeToString(token.getEncoded()));return response;} catch (RestClientException | TSPException | CMSException | OperatorCreationException | GeneralSecurityException e) {throw new IOException(e);}
}

它通过创建消息标记来准备请求。 请注意,您传递的是散列本身,还传递了用于进行散列的散列算法。 我不知道为什么API不会向您隐藏它。 在我的情况下,散列是以更复杂的方式获得的,因此它很有用,但仍然如此。 然后,我们获得请求的原始形式,并将其发送到TSA(时间戳授权机构)。 这是一个HTTP请求,很简单,但是您必须注意一些在TSA之间不一定一致的请求和响应标头。 用户名和密码是可选的,某些TSA无需身份验证即可提供服务(限速)。 还要注意tsaPolicyOid –大多数TSA在其页面上都有其特定策略的记录,您应该从那里获取OID。

返回原始响应后,将其解析为TimeStampResponse。 同样,您必须遍历2个中间对象(ASN1StreamParser和TimeStampResp),这可能是一个适当的抽象,但不是可用的API。

然后,您检查响应是否成功,并且还必须对其进行验证-TSA可能返回了错误的响应。 理想情况下,所有这些都可以对您隐藏。 验证会引发异常,在这种情况下,我只是通过包装在IOException中进行传播。

最后,您获得令牌并返回响应。 最重要的是令牌的内容,在我的情况下需要将其作为Base64,因此我对其进行了编码。 也可能只是原始字节。 如果您想从令牌中获取任何其他数据(例如,签名时间),就不是那么简单; 您必须解析低级属性(要点)。

好的,您现在有了令牌,可以将其存储在数据库中。 有时您可能想验证时间戳是否未被篡改(这是我的用例)。 代码在这里,我什至不尝试解释它-这是一堆样板文件,也说明了TSA响应方式的变化(我已经尝试了几次)。 需要DummyCertificate类的事实要么意味着我错了,要么证实了我对BouncyCastle API的批评。 某些TSA可能不需要DummyCertificate,但对于其他TSA则需要DummyCertificate,实际上您不能轻易地实例化它。 您需要一个真实的证书来构造它(要点中没有包括该证书;使用下一个要点中的init()方法,您可以使用dummyCertificate = new DummyCertificate(certificateHolder.toASN1Structure());创建虚拟dummyCertificate = new DummyCertificate(certificateHolder.toASN1Structure()); )。 在我的代码中,这些都是一类,但是为了呈现它们,我决定将其拆分,因此很少重复。

好的,现在我们可以标记时间戳并验证时间戳了。 那应该足够了; 但出于测试目的(或有限的内部使用),您可能需要在本地进行时间戳记,而不是询问TSA。 该代码可以在这里找到。 它使用spring,但是您可以改为将密钥库详细信息作为参数传递给init方法。 您需要一个带有密钥对和证书的JKS存储,并且我使用KeyStore Explorer来创建它们。 如果您在AWS中运行应用程序,则可能要使用KMS(密钥管理服务)对密钥库进行加密,然后在应用程序加载时对其进行解密,但这不在本文的讨论范围之内。 对于本地时间戳验证,按预期进行,对于时间戳–无需调用外部服务,只需调用localTSA.timestamp(req);

我怎么知道要实例化哪些类以及要传递哪些参数–我不记得了。 查看测试,示例,答案,资源。 花了一段时间,所以我要分享它,以潜在地避免其他人遇到的麻烦。

可以测试的TSA列表: SafeCreative , FreeTSA , time.centum.pl 。

我意识到这似乎并不适用于许多情况,但是我建议您在应用程序数据的一些关键部分添加时间戳。 通常,将其放在您的“工具箱”中以备使用,而不是试图阅读标准并与BouncyCastle类作战几天,以完成此所谓的简单任务,通常是很有用的。

翻译自: https://www.javacodegeeks.com/2017/12/using-trusted-timestamping-java.html

在Java中使用可信时间戳相关推荐

  1. java中实现具有传递性吗_Java中volatile关键字详解,jvm内存模型,原子性、可见性、有序性...

    一.Java内存模型 想要理解volatile为什么能确保可见性,就要先理解Java中的内存模型是什么样的. Java内存模型规定了所有的变量都存储在主内存中.每条线程中还有自己的工作内存,线程的工作 ...

  2. java中调用python

    在Java中调用Python </h1><div class="clear"></div><div class="postBod ...

  3. java中hashcode_浅谈Java中的Hash值

    1.Hash值有什么用? HashMap.HashTable.HashSet,所以涉及到使用Hash值进行优化存储的地方,都会用到HashCode.HashCode是Key,这种计算为提高计算的性能. ...

  4. JAVA中获取当前系统时间

    JAVA中获取当前系统时间 转自:http://www.cnblogs.com/Matrix54/archive/2012/05/01/2478158.html 一. 获取当前系统时间和日期并格式化输 ...

  5. Java中的对象和包

    什么是对象 对象就是实际生活中的事物,可以说一切事物都是对象. 对象的三个特点 1  对象的行为:这个对象能做什么, 例如包子是用来吃的 2  对象的状态:对象保持的一种状态,例如这个包子是热的还是凉 ...

  6. java中标识符,关键字,数据类型

    什么是标识符? 在java语言中用来给一个类,变量或方法命名的符号 标识符的命名规则 标识符可以由字母.数字.下划线(_).美元符($)组成,但不能包含 @.%.空格等其它特殊字符,不能以数字开头. ...

  7. Java中byte与16进制字符串的互相转换

    https://www.cnblogs.com/qinwangchen/p/5418028.html * Convert byte[] to hex string.这里我们可以将byte转换成int, ...

  8. JAVA中priorityqueue详解

    Java中PriorityQueue通过二叉小顶堆实现,可以用一棵完全二叉树表示.本文从Queue接口函数出发,结合生动的图解,深入浅出地分析PriorityQueue每个操作的具体过程和时间复杂度, ...

  9. 使用java中replaceAll方法替换字符串中的反斜杠

    今天在项目中使用java中replaceAll方法将字符串中的反斜杠("\")替换成空字符串(""),结果出现如下的异常: 1 java.util.regex. ...

最新文章

  1. 初识软件体系结构(1-4课时)
  2. mysql left join 慢 的一个原因
  3. python可以干什么-Python可以用来做什么 为你揭开python神秘面纱
  4. 设置路由器端口转发功能如何操作
  5. 超方便、最简单版本:java 邮件发送 (半分钟写完代码)
  6. 安装docker-machine
  7. 用CSS3实现图像风格
  8. 规则引擎 drools_网易考拉规则引擎平台架构设计与实践
  9. 南农计算机分数线,2021南京农业大学录取分数线_历年各专业分数线(2017-2020),各省投档线_一品高考网...
  10. web前端实战小游戏两则(附源码)
  11. ASP.NET MVC:UrlHelper.cs
  12. 如何翻滚截屏_怎么进行滚动截屏
  13. 从openssl rsa pem文件中提取公私钥数据实现
  14. 手把手教学endnote设置毕业论文参考文献格式(特别完整)
  15. android多开原理和检测。
  16. bam文件读取_bam格式文件处理大全(一)
  17. 使用cmd上传指定文件到ftp服务器,命令行下的FTP使用详解
  18. IMAU 软件项目管理 期末复习总结 第七章
  19. 跟益达学Solr5之从MySQL数据库导入数据并索引
  20. CEC2015:动态多目标野狗优化算法求解CEC2015(提供完整MATLAB代码,含GD、IGD、HV和SP评价指标)

热门文章

  1. Linux中netfilter模块编程实践
  2. poj 1269 计算几何
  3. AliOS Things KV组件的写平衡特性
  4. SCOM Logical Disk Free Space Monitor
  5. 《iOS 9 开发指南》——第6章,第6.4节 Interface Builder中的故事板——Storyboarding...
  6. win8中离线安装net framework 3.5
  7. rsync备份之windows+linux
  8. 招人—凡客诚品 数据中心系统工程师(海外及手机业务方向)
  9. telegram 创建机器人
  10. mysql 报错 sql_mode=only_full_group_by 解决方法