https://github.com/dnl50/tsa
Java implementation of a RFC3161 Time Stamp Authority
https://github.com/dnl50/tsa
bouncycastle graalvm-native-image quarkus rfc3161 rfc5816 sveltekit time-stamp
Last synced: 11 months ago
JSON representation
Java implementation of a RFC3161 Time Stamp Authority
- Host: GitHub
- URL: https://github.com/dnl50/tsa
- Owner: dnl50
- License: mit
- Created: 2021-10-23T14:57:12.000Z (over 4 years ago)
- Default Branch: develop
- Last Pushed: 2024-12-21T15:22:50.000Z (about 1 year ago)
- Last Synced: 2025-04-25T03:01:32.630Z (11 months ago)
- Topics: bouncycastle, graalvm-native-image, quarkus, rfc3161, rfc5816, sveltekit, time-stamp
- Language: Java
- Homepage:
- Size: 1.04 MB
- Stars: 25
- Watchers: 1
- Forks: 3
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Time Stamp Authority
This is a Java implementation of a Time Stamp Authority using the Time-Stamp Protocol (_TSP_) as defined
in [RFC 3161](https://tools.ietf.org/html/rfc3161) and [RFC 5816](https://tools.ietf.org/html/rfc5816).
It uses [Bouncy Castle](https://www.bouncycastle.org/java.html) and [Quarkus](https://quarkus.io) under the hood.
The application utilizes GraalVM's Native Image technology, which leads to a very small memory footprint of about
10 MB and a near instant startup in about 50 milliseconds.
## Docker Images
Docker images are automatically published to [Docker Hub](https://hub.docker.com/r/dnl50/tsa-server).
By default, the embedded H2 database writes its data to the `/work/data/tsa.mv.db` file. Mounting a directory or a named
volume to the `/work/data` will make the DB data persistent.
The keystore containing the certificate and private key used to sign the requests with is loaded
from `/work/keystore.p12` by default.
There are two Docker Image variants: _Native_ and _JVM_.
Native Images (e.g. `dnl50/tsa-server:3.1.0`) are only available for `x86-64`. The JVM variant
(e.g. `dnl50/tsa-server:3.1.0-jvm`) is available for `x86-64` and `arm64`.
## Features
### Time Stamping
The main purpose of this application is to sign TSP requests using
the [HTTP Protocol](https://datatracker.ietf.org/doc/html/rfc3161.html#section-3.4). The application therefore offers an
HTTP endpoint under `/sign` which accepts `POST` requests with the content type `application/timestamp-query`. The
ASN.1 DER-encoded Timestamp Request must be supplied in the request body.
The following OpenSSL commands can be used to send a timestamp request for an existing file:
```bash
# create a timestamp request
openssl ts -query -data /path/to/file -sha512 -cert -out request.tsq
# send the request using cURL
curl -X POST --data-binary @request.tsq --header "Content-Type: application/timestamp-query" http://localhost:8080/sign -o response.tsr
````
### Web UI
⚠️ The Web UI ist yet to be reimplemented after the migration to Quarkus ⚠️
### REST API
The available REST endpoints are documented in a OpenAPI specification which can be downloaded from
the [release page](https://github.com/dnl50/tsa/releases).
### WebSocket Endpoint
The application exposes an WebSocket endpoint under `/history/responses`. The JSON representation of every TSP
response will be broadcast there.
## Configuration
All Parameters mentioned below can be configured in variety of ways. Please refer to
the [Quarkus Documentation](https://quarkus.io/guides/config-reference#configuration-sources) for more information.
| Parameter Name | Mandatory | Default Value | Description |
|--------------------------------|-----------|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `tsa.ess-cert-id-algorithm` | No | SHA256 | The hash algorithm which is used to calculate the TSA's certificate identifier (ESSCertIDv2). |
| `tsa.signing-digest-algorithm` | No | SHA256 | The hash algorithm which is used to calculate the TSP requests digest, which will be signed by the TSA. |
| `tsa.accepted-hash-algorithms` | No | SHA256,SHA512 | Comma-separated list of hash algorithm names/OIDs which are accepted by the Time Stamp Authority. |
| `tsa.policy-oid` | No | 1.2 | The OID of the policy under which the TSP responses are produced. |
| `tsa.keystore.path` | Yes | | The path of the PKCS#12 archive containing the certificate and private key used to sign TSP requests. Prefixing the path with `classpath:` will result in the PKCS#12 archive from being loaded from the classpath (not supported in native image). |
| `tsa.keystore.password` | No | | The password of the PKCS#12 archive. |
| `tsa.include-tsa-name` | No | true | Specifies whether the [`tsa` Field in the `TSTInfo`](https://datatracker.ietf.org/doc/html/rfc3161#autoid-8) should include the subject of the certificate. |
### Logging
By default, all log messages will be printed to STDOUT. Please refer to
the [Quarkus Documentation](https://quarkus.io/guides/logging) for further information on how to configure the log
output.
## Issuing a signing certificate
The signing certificate used by the Time Stamp Authority must be an RSA, DSA or EC certificate with
an [Extended Key Usage](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12) extension marked as _critical_.
The only `KeyPurposeId` present in the sequence must be `id-kp-timeStamping` (OID `1.3.6.1.5.5.7.3.8`).
### Issuing a CA and TSA certificate with OpenSSL
> You should use a certificate issued by a trusted third party for production use
To issue a signing certificate using a custom CA, you can use the following commands:
First, create a file named `tsa-x509-extensions.cnf` with the following content:
```
[v3_ca]
basicConstraints = CA:TRUE
keyUsage = digitalSignature, keyCertSign
[usr_timestamping]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, nonRepudiation
extendedKeyUsage = critical, timeStamping
```
This file contains the extension profiles which are used later.
Then create a new private key for the CA:
```bash
openssl ecparam -genkey -name secp384r1 -out ca.privkey
```
After that, create a CSR (_Certificate Signing Request_) for the CA certificate
```bash
openssl req -new -key ca.privkey -out cacertreq.pem
```
and sign it with CA's private key created before
```bash
openssl x509 -req -in cacertreq.pem -extfile tsa-x509-extensions.cnf -extensions v3_ca -key ca.privkey -out cacert.pem
```
After that you can create a new private key which will be used by the TSA to sign the timestamp requests:
```bash
openssl ecparam -genkey -name secp384r1 -out tsa.privkey
```
Then create a CSR for it
```bash
openssl req -new -key tsa.privkey -out tsacertreq.pem
```
and issue a certificate using the CA certificate and private key created before:
```bash
openssl x509 -req -in tsacertreq.pem -extfile tsa-x509-extensions.cnf -extensions usr_timestamping -CA cacert.pem -CAkey ca.privkey -CAcreateserial -out tsacert.pem
```
The TSA certificate and private key can then be put into a PKCS#12 keystore which can be used by the application:
```bash
openssl pkcs12 -export -CAfile cacert.pem -chain -in tsacert.pem -inkey tsa.privkey -out tsa-keystore.p12
```
## Development
### Running in development mode
In normal operation, no signing certificate is configured by default since you probably want to use your own/your
organizations key pair and not a self-signed key pair I issued to use in integration tests. Configuring a file system
path to a valid certificate for development is error-prone though. That's what the development mode is for. It is
automatically enabled when running Quarkus using the `quarkusDev` Gradle Task. The dev mode has the following effects:
* application data is written into an in-memory Database which will be scrapped on application shutdown
* uses a self-signed EC certificate for signing TSP requests
### Using the code formatter
The source code is formatted using the Eclipse Code Formatter. The formatter config file is located
under `/eclipse-formatter.xml`. A custom import order configuration file os located under `/spotless.importorder`. The
code can also be formatted using the [Spotless Gradle Plugin](https://github.com/diffplug/spotless). Just execute
the `spotlessApply` Gradle Task and you are good to go!
## License
This project is licensed under the terms of the MIT license.