HTTPS-Zugriff auf GLOBALTRUST® QUALIFIED TIMESTAMP Server

Der GLOBALTRUST® QUALIFIED TIMESTAMP Server implementiert das "Time-Stamp Protocol via HTTP" (RFC 3161 3.4) mit dem Zusatz, dass SSL verschlüsselte Sockets verwendet werden. Die Benutzerauthentifizierung kann auf 2 Arten erfolgen:
- dem Server wird beim TLS-Handshake ein Client Zertifikat vorgewiesen (im Moment sind alle nicht abgelaufenen und nicht widerrufenen persönlichen GLOBALTRUST® Zertifikate berechtigt, Zeitstempel abzuholen).
- dem Server werden mittels HTTP Basic Authentication Scheme (RFC 2617 2.) Username und Passwort übermittelt.

Der GLOBALTRUST® QUALIFIED TIMESTAMP Server kann über die URL https://timestamp.globaltrust.eu:10080 erreicht werden.

Für Adobe Acrobat (und nur dafür) sind die Ports 12080 und 13080 reserviert, da diese die Zertifikate in der Antwort verlangt, mit zu großen Antwortdaten aber nicht umgehen können bzw, mit der TLS Client Authentifizierung nicht zurecht kommen.

Grundsätzlich können Lösungen in beliebigen Programmierumgebungen verwendet werden, es muss folgende Unterstützung gegeben sein:
- TLS-Unterstützung
- HTTP-Unterstützung
- Möglichkeit zur Erstellung eines Timestamp-Requests gemäß RFC 3161 (unterstützt wird SHA-1, SHA-256, SHA-512, RIPEMD-160)
- Möglichkeit zur Interpretation eines Timestamp-Response gemäß RFC 3161


Der Ablauf ist folgender:
- Der Client verbindet sich zum Server und authentifiziert sich (entweder mittels Zertifikat beim TLS-Handshake oder mittels HTTP Authentication)
- Der Client setzt den HTTP Content-Type auf "application/timestamp-query".
- Der Client schickt den Timestamp Request mittels POST an den Server.
- Der Server schickt eine HTTP Antwort des Content-Type "application/timestamp-response" zurück, welche die Timestamp Response enthält

Eine Java Client Applikation könnte in etwa so aussehen, wenn das File request.tsq ein gültiger Timestamp Request (TSR) ist. Der TSR selbst wurde mittels OpenSSL oder BouncyCastle-Bibliothek generiert.

Beachten Sie, dass der bereitgestellte Mustercode nur eine erste Orientierung darstellt und keine Gewähr für formale, inhaltliche oder syntaktische Richtigkeit übernommen wird. Der Code soll Java-Programmierern den Einstieg in die Timestamp-Problematik erleichtern.

Nutzer anderer Programmiersprachen (C, C++, usw.) benötigen gegebenenfalls RFC3161-konforme Erweiterungen bzw. Funktionsbibliotheken. Kontaktieren Sie diesbezüglich Ihren Lieferanten für Ihre Entwicklungsumgebung. GLOBALTRUST® kann dazu keinen Support leisten.


package eu.globaltrust.test;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

import org.bouncycastle.util.encoders.Base64;

public final class TSAHTTPClientWithHTTPAuth {

    private TSAHTTPClientWithHTTPAuth() {
    }

    public static void main(final String[] args) {
        // 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");

        // Username und Passwort für HTTP Authentifikation setzen
        String username = "USERNAME";
        String password = "PASSWORT";

        try {
            // Laden des Timestamp request
            File fReq = new File("request.tsq");
            byte[] req = new byte[(int) fReq.length()];
            try {
                new FileInputStream(fReq).read(req);
            } catch (Exception e) {
                System.err.println("Error reading from file");
                return;
            }

            // öffnen der Netzwerkverbindung
            HttpsURLConnection conn = (HttpsURLConnection) new URL("https://timestamp.globaltrust.eu:10080")
                    .openConnection();

            // Setzen der HTTP Parameter
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/timestamp-query");
            conn.setRequestProperty("Content-Length", Integer.toString(req.length));

            // Erstellen der Authorization-Information lt. RFC 2617
            // Base64("Username:Password")
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            Base64.encode((username + ":" + password).getBytes(), bout);
            String base64Auth = bout.toString("8859_1");
            conn.setRequestProperty("Authorization", "Basic " + base64Auth);

            // Senden des Requests
            OutputStream os = conn.getOutputStream();
            os.write(req);
            conn.connect();
            os.close();
            System.out.println("Request sent.");

            // Empfangen der Response
            InputStream is = conn.getInputStream();

            byte[] resp = new byte[conn.getContentLength()];
            is.read(resp);
            is.close();
            FileOutputStream osResp = new FileOutputStream("tsatestresp.der");
            osResp.write(resp);
            osResp.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Diese Client Applikation verwendet Authentifizierung mittels Zertifikat.

package eu.globaltrust.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

public final class TSAHTTPClientWithSSLAuth {

    private TSAHTTPClientWithSSLAuth() {
    }

    public static void main(final String[] args) {
        // Client Zertifikat bei TLS 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 {
            // Laden des Timestamp request
            File fReq = new File("request.tsq");
            byte[] req = new byte[(int) fReq.length()];
            try {
                new FileInputStream(fReq).read(req);
            } catch (Exception e) {
                System.err.println("Error reading from file");
                return;
            }

            // öffnen der Netzwerkverbindung
            HttpsURLConnection conn = (HttpsURLConnection) new URL("https://timestamp.globaltrust.eu:10080")
                    .openConnection();

            // Setzen der HTTP Parameter
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/timestamp-query");
            conn.setRequestProperty("Content-Length", Integer.toString(req.length));

            // Senden des Requests
            OutputStream os = conn.getOutputStream();
            os.write(req);
            conn.connect();
            os.close();
            System.out.println("Request sent.");

            // Empfangen der Response
            InputStream is = conn.getInputStream();

            byte[] resp = new byte[conn.getContentLength()];
            is.read(resp);
            is.close();
            FileOutputStream osResp = new FileOutputStream("tsatestresp.der");
            osResp.write(resp);
            osResp.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}