在Java中使用可信时间戳

受信任的时间戳记是使受信任的第三方(“时间戳记权威”,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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348858.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

无限滚动重置服务器,简单无限滚动的实现

在使用elementUI组件库的时候,用到了无限滚动这个功能。我没有看源码,直接在网上学习了下实现的思路,然后自己手动编码以下。在此总结下。假设页面上有一个盒子容器,容器内有一些子元素。容器的高度是固定的,有纵向滚动…

java配置openjdk_Java大新闻不断涌现:Java SE 6和OpenJDK

java配置openjdk我最近公布的最新的Java 8新闻 ,总结了一些最近的事态发展中的Java 8 。 自从发布该文章不到一周,就发布了更多重要的Java新闻报道,我在本文中总结了其中的一些内容。 共同的主题包括不同的Java SE 6实现和OpenJDK 。 Java安…

Fatjars,Thinwars以及为什么OpenLiberty很酷

法特哈斯 构建一个Fatjar(或Uberjar),其中包含将应用程序很好地打包在一起运行所需的一切,这意味着您可以: java -jar myapp.jar然后离开。 没有应用程序服务器。 没有类路径。 这种方法已经被诸如Springboot之类的微…

Spring Cloud Config Server简介

1.概述 在本教程中,我们将回顾Spring Cloud Config Server的基础知识。 我们将设置一个Config Server ,然后构建一个客户端应用程序 ,该客户端应用程序在启动时会消耗配置 ,然后刷新配置而不重新启动。 我们正在构建的应用程序与《…

朴素贝叶斯算法实现分类以及Matlab实现

开始 其实在学习机器学习的一些算法,最近也一直在看这方面的东西,并且尝试着使用Matlab进行一些算法的实现。这几天一直在看得就是贝叶斯算法实现一个分类问题。大概经过了一下这个过程: 看书→算法公式推演→网上查询资料→进一步理解→搜…

编写自定义的AssertJ断言

AssertJ是广泛使用的Hamcrest匹配器的替代匹配库。 实际上,对于我自己的项目,我已经更改为仅使用AssertJ-我只是发现流畅的界面和可扩展性非常吸引人。 您可以编写自定义断言,如下所示: 想象一下一种具有强度和饮料类型的咖啡 &…

LintCode-A + B 问题

文章转载 http://blog.csdn.net/wangyuquanliuli/article/details/47755461 给出两个整数a和b, 求他们的和, 但不能使用 等数学运算符。 您在真实的面试中是否遇到过这个题? Yes样例 如果 a1 并且 b2,返回3 注意 你不需要从输入流读入数据,…

位操作基础篇之位操作全面总结

转载自 http://blog.csdn.net/morewindows/article/details/7354571 Title: 位操作基础篇之位操作全面总结 KeyWord: C/C 位操作 位操作技巧 判断奇偶 交换两数 变换符号 求绝对值 位操作压缩空间 筛素数 位操作趣味应用 位操作笔试面试 位操作篇共分为基础篇和提高…

机器学习中的算法-支持向量机(SVM)基础

机器学习中的算法-支持向量机(SVM)基础 版权声明: 本文由LeftNotEasy发布于http://leftnoteasy.cnblogs.com, 本文可以被全部的转载或者部分使用,但请注明出处,如果有问题,请联系wheeleastgmail.com。也可以加我的微博: leftnotea…

使用JDK 8轻松进行细粒度排序

Java的8的推出流和有用的静态 / 默认的方法比较接口可以很容易地根据个人的领域两个对象比较“值,而不需要实现一个比较(T,T)在其对象的类方法被比较。 我将使用一个简单的Song类来帮助演示这一点,接下来显示其Song.j…

主成分分析以及应用:企业综合实力排序

这段时间一直在学习数据挖掘的一些算法,今天通过不断查阅资料,学习整理了一下主成分分析这个数据降维算法。并且结合一个实例进行matlab编程实现。 主成分基本原理 在数据挖掘中,经常会遇到一个问题就是一个问题出现了n多个变量,…

自定义MongoDB的Spring Social Connect框架

在上一篇文章中 ,我谈到了我面临的第一个挑战是更改数据模型并添加连接框架。 在这里,我想提供有关我如何做的更多详细信息。 Spring Social项目已经提供了基于jdbc的连接存储库实现,以将用户连接数据持久保存到关系数据库中。 但是&#xff…

算法题:输入aaaabbbcccccc输出a4b3c6。

今日在地铁上浏览今日头条的时候看到这么个小题目,说是输出一长串字符串,输出字母串类别并且统计其出现次数,然后按照顺序将其输出来。例如输入aaaabbbcccccc,输出a4b3c6。 最近也一直在学习,所以就想着就Matlab来试了…

Java World中的GraphQL简介

许多人认为GraphQL仅适用于前端和JavaScript,它在Java等后端技术中没有定位,但事实确实如此。 还经常将GraphQL与REST进行比较,但是这种比较是否合理? 首先,让我开始回答其中最重要的问题。 什么是GraphQL&#xff1…

算法题:在一个字符串中找到只出现一次的字符。如输入abaccdeeff,则输出bd。

今天的算法学习还是和字符串有关,这个题目据说是以前的某公司面试的笔试题目。题目意思就是说,在一个字符串中找到只出现了一次的那些字符,并且输出来。 作为非IT的我,平时使用Matlab比较多。不是科班出身,对于这个题…

Kafka的Spring Cloud Stream

总览 该示例项目演示了如何使用事件驱动的体系结构 , Spring Boot ,Spring Cloud Stream, Apache Kafka和Lombok构建实时流应用程序。 在本教程结束时,您将运行一个简单的基于Spring Boot的Greetings微服务 从REST API获取消息 …

使用JShell的Java 9 Streams API

这篇文章着眼于使用JShell的Java 9 Streams API。 Streams API的更改以Java 8中Streams的成功为基础,并引入了许多实用程序方法– takeWhile,dropWhile和iterate。 这篇文章延续了My Top Java 9功能,并使用Jshell探索了这些方法。 流API Str…

常见的股票技术因子学习以及计算

最近在看《量化投资数据挖掘技术与实践(MATLAB版)》。学习了其中的常见的股票衍生变量,并且利用WIND金融数据终端的matlab借口windmatlab导出一些数据进行了一个简单的学习。特此记录。 下面是我对于书中提到的几个因子的学习总结&#xff1…

算法题:输入一个表示整数的字符串,把该字符串转换成整数并输出。例如输入字符串“12345”,则输出整数“12345”

今天这道算法题比较简单,主要考察的思考问题的全面性。这个需要考虑的几种情况。 如果输入的整数字符串是个负数,怎么处理? 如果输入的第一个字符是0,则怎么处理? 如果输入的是非0~9之间的字符怎么处理?…

排序算法一:冒泡排序,插入排序以及选择排序原理与MATLAB实现

最近在学习排序算法的一些知识。还是比较有趣的。所以好好研究了一下各个算法。并且使用matlab进行了个基本的实现,目前仅仅是实现吧,优化什么的可能目前的水平达不到吧,毕竟是用matlab实现,还是比较简单。以后还是希望使用C/C&am…