Der GLOBALTRUST® QUALIFIED TIMESTAMP Server ist ein Service, das Zeitstempeldienste im Sinne von RFC3161 anbietet.
– Dieser Hash wird an den GLOBALTRUST® QUALIFIED TIMESTAMP Server in Form eines in RFC3161 spezifizierten Timestamp Request geschickt.
– Der GLOBALTRUST® QUALIFIED TIMESTAMP Server schickt den Zeitstempel in Form eines Timestamp Reply zurück.
– TLS-Unterstützung
– Verwendung von Clientzertifikaten beim TLS-Handshake muss unterstützt werden
– Möglichkeit zur Erstellung und Interpretation eines „Socket Based Protocol“-Headers (RFC 3161 3.3)
– Möglichkeit zur Erstellung eines Timestamp-Requests gemäß RFC 3161 (unterstützt wird SHA-1, SHA-256, SHA-512 und RIPEMD-160)
– Möglichkeit zur Interpretation eines Timestamp-Response gemäß RFC 3161
import org.bouncycastle.tsp.TimeStampResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.math.BigInteger;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
/**
* This class contains a main method that connects to a timestamping server
* using the TCP protocol specified in RFC3161 with an additional SSL layer. It
* should only be used for reference purposes.
* @author DW
*
*/
public final class TSATCPClient {
private TSATCPClient() {
}
public static void main(final String[] args) {
// Client Zertifikat bei SSL Handshake "vorweisen"
System.setProperty("javax.net.ssl.keyStore", "zertifikat.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "PASSWORT");
System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
// Truststore setzen; Truststore enthält GLOBALTRUST root
// Zertifikat – notwendig, da der Client dem TLS Serverzertifikat
// sonst nicht traut – siehe
// http://java.sun.com/j2se/1.4.2/docs/guide/security/jsse/JSSERefGuide.html#CreateKeystore
System.setProperty("javax.net.ssl.trustStore", "truststore-client");
try {
// Timestamp Request einlesen
File fReq = new File("request.tsq");
FileInputStream fis = new FileInputStream(fReq);
byte[] request = new byte[(int) fReq.length()];
fis.read(request);
fis.close();
// Header für direct TCP-based TSA message vorbereiten
// length-Header Feld
int len = request.length + 1;
byte[] blength = new BigInteger(Integer.toString(len)).toByteArray();
byte[] length = new byte[4];
// Falls Länge weniger bytes verbraucht, als vorgesehen ist,
// wird der Rest mit 0-Bytes aufgefüllt.
for (int i = 3; i > 3 – blength.length; i–) {
length[i] = blength[(blength.length – 1) + (i – 3)];
}
for (int i = 0; i < 4 – blength.length; i++) {
length[i] = 0;
}
// Verbindung aufbauen
SSLSocket s = (SSLSocket) SSLSocketFactory.getDefault().createSocket("timestamp.globaltrust.eu", 10318);
// length-Header Feld schicken
s.getOutputStream().write(length);
// flag-Header Feld vorbereiten und schicken
byte[] flag = new byte[1];
flag[0] = 0;
s.getOutputStream().write(flag);
// timestamp request schicken
s.getOutputStream().write(request);
// Antwort lesen
InputStream is = s.getInputStream();
// Length-Header Feld lesen
blength = new byte[4];
int readlen;
if ((readlen = is.read(blength, 0, 4)) < 4) {
System.out.println("Couldn’t read length");
System.out.println("only read " + readlen + " bytes");
return;
}
int ilength = new BigInteger(blength).intValue();
// Flag-Header Feld lesen
flag = new byte[1];
if (is.read(flag, 0, 1) != 1) {
System.out.println("flag not read");
}
// Timestamp Response lesen
byte[] value = new byte[ilength – 1];
if ((readlen = is.read(value, 0, ilength – 1)) != ilength – 1) {
System.out.println("could not read message");
System.out.println("only read " + readlen + " bytes");
return;
}
// Timestamp Response abspeichern
FileOutputStream reply = new FileOutputStream("reply.tsr");
reply.write(value);
reply.close();
// Timestamp Response interpretieren
TimeStampResponse resp = new TimeStampResponse(value);
System.out.println("Response Status: " + resp.getStatus());
System.out.println("Timestamp at: " + resp.getTimeStampToken().getTimeStampInfo().getGenTime());
} catch (Exception e) {
e.printStackTrace();
}
}
}