Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use trusted timestamps in JAVA

2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces how to use trusted timestamps in JAVA, which has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article, let the editor take you to know it.

A trusted timestamp is a process that allows a trusted third party (TSA) to prove the time of a given event electronically. The EU regulation eIDAS gives legal effect to these timestamps-that is, if the event has a timestamp, no one can dispute the time or the content of the event. Suitable for a variety of scenarios, including timestamp audit logs. (note: timestamps are not enough for a good audit trail because it does not prevent malicious actors from deleting events completely.)

There are many standards for trusted timestamps, one of which is RFC 3161. Like most RFC, it is difficult to read. Fortunately for Java users, BouncyCastle implements this standard. Unfortunately, like most secure API, it is difficult, even bad, to use. I have to implement it, so I'll share the code needed for the timestamp data.

I will try to explain the main process. Obviously, there is a lot of code that can simply follow the standard. The BouncyCastle class is a maze that is difficult to navigate.

The main method is obviously 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);}}

It prepares the request by creating a message imprint. Note that you are passing the hash itself and the hash algorithm used to generate the hash. Why API didn't hide it from you, I don't know. In my case, the hash is obtained in a more complex way, so it is useful and still useful. Then we take the original form of the request and send it to the TSA (timestamp authority). This is a HTTP request, which is a bit simple, but you have to deal with some request and response headers that are not necessarily consistent in TSA. Usernames and passwords are optional, and some TSA provide services that do not require authentication (speed limit). Also note tsaPolicyOid-most TSA have their specific policy records on their pages, and you should get the OID from there.

When you return the original response, you parse it to TimeStampResponse. Again, you have to pass through two intermediate objects (ASN1StreamParser and TimeStampResp), which may be an appropriate abstraction, but not an available API.

Then you check whether the response is successful, and you must also verify it-- TSA may have returned an incorrect response. Ideally, all of this can be hidden from you. Validation throws an exception, in which case I just propagate it in IOException through wrapper.

Finally, you get the token and return the response. The most important thing is the content of the token, which in my case requires Base64, so I coded it. It could also be just a raw byte. If you want to get any extra data (such as signature time) from a token, it's not that simple; you have to parse low-level attributes (see the main point).

Well, you now have a token and you can store it in the database. Sometimes you may want to verify that the timestamp has not been tampered with. The code is here, and I won't even try to explain it-- it's a bunch of templates and illustrates the changes in the way TSA responds (I've tried some). The fact that I need the DummyCertificate class either means I did something wrong or confirms my criticism of BouncyCastle API. Some TSA may not require DummyCertificate, but others need DummyCertificate, and you can't actually instantiate it that easily. You need a real certificate to build it (it is not included in the point; using the init () method in the next point, you can use dummyCertificate = new DummyCertificate (certificateHolder.toASN1Structure ());). In my code, these are all one class, but in order to render them, I decided to split them, so there is a bit of repetition.

OK, now we can add the timestamp and verify the timestamp. This should be sufficient; but for testing purposes (or limited internal use), you may want to timestamp locally instead of asking TSA. The code can be found here. It uses spring, but you can pass the KeyStore details as parameters to the init method. You need a JKS store with key pairs and certificates, which I create using KeyStore Explorer. If you are running your application in AWS, you may want to use KMS (key Management Service) to encrypt your KeyStore and then decrypt it when the application loads, but this is beyond the scope of this article. For local timestamp validation works as expected, for timestamp-no need to call external services, just call localTSA.timestamp (req)

How I knew which classes to instantiate and which parameters to pass-- I don't remember. View tests, examples, answers, sources. It took a while, so I shared it to potentially avoid some trouble for others.

List of TSA that you can test: SafeCreative, FreeTSA, time.centum.pl.

I realize that this doesn't seem to apply to many scenarios, but I suggest adding timestamps to some key parts of the application data. It is often useful to keep it in your "toolbox" and make it available at any time, rather than trying to read the standard and struggle with the BouncyCastle class for days to accomplish this so-called simple task.

Thank you for reading this article carefully. I hope the article "how to use trusted timestamps in JAVA" shared by the editor will be helpful to everyone. At the same time, I also hope that you will support and follow the industry information channel. More related knowledge is waiting for you to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report