Discussion:
Erzeugen und speichern einer Zertifikatskette
(zu alt für eine Antwort)
Stefanie Wiemann
2005-05-27 14:51:33 UTC
Permalink
Hallo,

ich möchte mit bouncycastle mehrere Zertifikate erzeugen, die eine
Zertifikatskette bilden.

In org.bouncycastle.tsp.test.TSPTest passiert folgendes:

String signDN = "O=Bouncy Castle, C=AU";
KeyPair signKP = TSPTestUtil.makeKeyPair();
X509Certificate signCert = TSPTestUtil.makeCACertificate(signKP,
signDN, signKP, signDN);

String origDN = "CN=Eric H. Echidna, E=***@bouncycastle.org, O=Bouncy
Castle, C=AU";
KeyPair origKP = TSPTestUtil.makeKeyPair();
X509Certificate origCert = TSPTestUtil.makeCertificate(origKP,
origDN, signKP, signDN);


makeCACertificate erstellt ein Root-Zertifikat "signCert",
makeCertificate erstellt ein Zertifikat "origCert" für origDN mit
signDN als Issuer.

Die Kette kann man natürlich verlängern.

Wie speichere ich die so erstellten Zertifikate ab, so daß ich wieder
an die Zertifikatskette komme?

Wenn ich die Zertifikate in einem KeyStore speichere, erhalte ich mit
getCertificate() immer nur ein einzelnes Zertifikat,
getCertificateChain() liefert null (was ja auch ok ist, da es sich
nicht um einen key entry handelt).
Was tun?

Gruß
Steffi
Stefan Matthias Aust
2005-05-28 07:21:09 UTC
Permalink
Post by Stefanie Wiemann
ich möchte mit bouncycastle mehrere Zertifikate erzeugen, die eine
Zertifikatskette bilden.
[...]
Post by Stefanie Wiemann
Wie speichere ich die so erstellten Zertifikate ab, so daß ich wieder
an die Zertifikatskette komme?
Wenn ich die Zertifikate in einem KeyStore speichere, erhalte ich mit
getCertificate() immer nur ein einzelnes Zertifikat,
getCertificateChain() liefert null (was ja auch ok ist, da es sich
nicht um einen key entry handelt).
Speichere doch einfach das, was bei getEncoded() zurückgegeben wird
(DER-Encoding) in einen Bytestream und lies das dann später mit einer
CertificateFactory wieder ein. Ein KeyStore in der
Default-Implementierung ist auch keine Magie, da wird das selbe gemacht,
wobei glaube ich der Stream mit einem PBE-Cipher verschlüsselt wird.

Was willst du eigentlich mit den Zertifikaten denn machen? Vielleicht
willst du ja lieber gleich mit CertPath-Objekten hantieren?
--
Stefan Matthias Aust
Stefanie Wiemann
2005-05-30 09:26:20 UTC
Permalink
Post by Stefan Matthias Aust
Was willst du eigentlich mit den Zertifikaten denn machen? Vielleicht
willst du ja lieber gleich mit CertPath-Objekten hantieren?
Ich will bei der Kommunikation zwischen Client und Server (Servlet) den
beiden die Möglichkeit geben, zu prüfen, ob der Request/die Response
auch wirklich vom angegebenen Absender kommt (Authentifizierung).
Dafür verpacke ich den Request des Clients in ein
CMSSignedData-Objekt. Dem kann ich die Zertifikate/Zertifikatskette zum
Prüfen der Signatur entweder direkt mit übergeben, oder ich gehe
davon aus, daß der Empfänger alle notwendigen Zertifikate bereits
hat.
Aber egal, was ich tue, entweder der Sender oder der Empfänger muß
die Zertifikatskette zusammenbauen.

Eigentlich wollte ich es so machen, daß sich jeder Client einmalig
beim Server "anmelden" muß, um danach Requests schicken zu dürfen.
Bei dieser Anmeldung schickt der Client sein Zertifikat an den Server
und erhält gleichzeitig das Zertifikat des Servers. In diesem Fall
bräuchte ich die Zertifikate beim Request (im CMSSignedData-Objekt)
doch gar nicht mehr mitzuschicken, oder? Aber dann müßte ich auch bei
der Anmeldung nicht nur die Endzertifikate, sondern die vollständige
Zertifikatskette verschicken, oder?
Wie mache ich das?

Bis jetzt habe ich es nur geschafft, einzelne Zertifikate zu erzeugen
und sie einzeln abzuspeichern. Nach meinem Studium der API-Doku für
KeyStore und CertStore würde ich folgendermaßen vorgehen, um daraus
wieder eine Zertifikatskette zu erstellen:

- Einlesen aller Zertifikate aus dem KeyStore in einen CertStore
- Herausfiltern des Issuers aus dem Anwenderzertifikat
- einen X509CertSelector basteln (wie auch immer), der als Owner
(=Subject?) diesen Issuer enthält und evtl noch die SerialNumber
- damit getCertificates() des CertStores aufrufen und hoffen, daß ich
nur ein Ergebnis bekomme
- aus diesem Zertifikat wieder den Issuer herausfiltern, damit wieder
wie oben den X509CertSelector basteln
- usw
solange, bis ich am root-Zertifikat angekommen bin.
Dann müßte ich doch eigentlich die Zertifikatskette für mein
Anwenderzert zusammenhaben.

CertPath und CertPathBuilder machen doch in etwa das gleiche? Leider
bin ich aus der API-Doku nicht richtig schlau geworden.
Muß ich die PKIX-Varianten von CertPath, CertPathBuilder,
BuilderParameters ... verwenden (für X509Certificates)?

Habe gerade bei bouncycastle die Beispiele für CertPath und co
gefunden. Die werd ich mir jetzt erstmal ansehen.

Gruß
Steffi
Stefan Matthias Aust
2005-05-31 13:19:31 UTC
Permalink
Post by Stefanie Wiemann
Post by Stefan Matthias Aust
Was willst du eigentlich mit den Zertifikaten denn machen? Vielleicht
willst du ja lieber gleich mit CertPath-Objekten hantieren?
Ich will bei der Kommunikation zwischen Client und Server (Servlet) den
beiden die Möglichkeit geben, zu prüfen, ob der Request/die Response
auch wirklich vom angegebenen Absender kommt (Authentifizierung).
Das ist doch eine Eigenheit von (HTTP über) SSL. Musst du das nochmal
selbst implementieren?
Post by Stefanie Wiemann
Dafür verpacke ich den Request des Clients in ein
CMSSignedData-Objekt.
CMS wie Content Management System?
Post by Stefanie Wiemann
Dem kann ich die Zertifikate/Zertifikatskette zum
Prüfen der Signatur entweder direkt mit übergeben, oder ich gehe
davon aus, daß der Empfänger alle notwendigen Zertifikate bereits
hat.
Jepp, erinnert mich irgendwie an das Protokol, das ich für OMA DRM
implementiere :)
Post by Stefanie Wiemann
Aber egal, was ich tue, entweder der Sender oder der Empfänger muß
die Zertifikatskette zusammenbauen.
Eigentlich sollen sich ja beide gegenseitig prüfen können. Idealerweise
wünscht sich ObdA der Server ein Trust Anchor, zu dem dann der Client
eine Zertifikatskette liefern muss und der Client selbst wünscht sich
einen Trust Anchor, für den dann der Server seine Zertifikatskette
liefern muss. Diese Ketten kann man jetzt prüfen, ggf. mit Hilfe eines
OCSP-Responders als neutrale dritte Stelle.
Post by Stefanie Wiemann
Eigentlich wollte ich es so machen, daß sich jeder Client einmalig
beim Server "anmelden" muß, um danach Requests schicken zu dürfen.
Bei dieser Anmeldung schickt der Client sein Zertifikat an den Server
und erhält gleichzeitig das Zertifikat des Servers. In diesem Fall
bräuchte ich die Zertifikate beim Request (im CMSSignedData-Objekt)
doch gar nicht mehr mitzuschicken, oder? Aber dann müßte ich auch bei
der Anmeldung nicht nur die Endzertifikate, sondern die vollständige
Zertifikatskette verschicken, oder?
Wenn du alles tauschen willst, musst du auch alles mitschicken.
Post by Stefanie Wiemann
Wie mache ich das?
Ein X509-Zertifikat kann einfach in ein DER-encodetes byte[] verwandelt
werden. Davon kannst du doch problemlos mehrere verschicken. Die
andere Seite muss aus dem DER-encodeten byte[] wieder ein
X509-Zertifikatsobjekt machen.
Post by Stefanie Wiemann
- Einlesen aller Zertifikate aus dem KeyStore in einen CertStore
- Herausfiltern des Issuers aus dem Anwenderzertifikat
- einen X509CertSelector basteln (wie auch immer), der als Owner
(=Subject?) diesen Issuer enthält und evtl noch die SerialNumber
- damit getCertificates() des CertStores aufrufen und hoffen, daß ich
nur ein Ergebnis bekomme
- aus diesem Zertifikat wieder den Issuer herausfiltern, damit wieder
wie oben den X509CertSelector basteln
- usw
Kingt richtig. Aber schau dir den CertPathBuilder an. Der kann das.
Post by Stefanie Wiemann
CertPath und CertPathBuilder machen doch in etwa das gleiche? Leider
bin ich aus der API-Doku nicht richtig schlau geworden.
Ja.
Post by Stefanie Wiemann
Muß ich die PKIX-Varianten von CertPath, CertPathBuilder,
BuilderParameters ... verwenden (für X509Certificates)?
Ja.
--
Stefan Matthias Aust
Stefanie Wiemann
2005-06-03 08:24:22 UTC
Permalink
Post by Stefan Matthias Aust
Post by Stefanie Wiemann
Ich will bei der Kommunikation zwischen Client und Server (Servlet) den
beiden die Möglichkeit geben, zu prüfen, ob der Request/die Response
auch wirklich vom angegebenen Absender kommt (Authentifizierung).
Das ist doch eine Eigenheit von (HTTP über) SSL. Musst du das nochmal
selbst implementieren?
Hmm. Das ganze ist die Implementierung eines Zeitstempeldienstes.
Der Client fordert einen Zeitstempel vom Server an. Dafür schickt er
einen TimeStampRequest. Der Server antwortet mit einer
TimeStampResponse. Die enthält sowieso schon signierte Daten, die sich
(mit Zertifikat) authentifizieren lassen.
Nur der TimeStampRequest ist noch nicht signiert. Im RFC 3161
(TimeStamp Protocol) wird empfohlen, das über CMS zu tun. Heißt
übrigens hier nicht Content Management System, sondern Cryptographic
Message Syntax.
Da ich also sowieso mit Zertifikaten rumhampeln muß, und bouncycastle
sowohl Zeitstempel als auch CMS unterstützt, dacht ich mir so in
meinem jugendlichen Leichtsinn, dann mach ich das doch einfach.
Post by Stefan Matthias Aust
Post by Stefanie Wiemann
Dafür verpacke ich den Request des Clients in ein
CMSSignedData-Objekt.
CMS wie Content Management System?
s.o. :-)
Post by Stefan Matthias Aust
Post by Stefanie Wiemann
Dem kann ich die Zertifikate/Zertifikatskette zum
Prüfen der Signatur entweder direkt mit übergeben, oder ich gehe
davon aus, daß der Empfänger alle notwendigen Zertifikate bereits
hat.
Jepp, erinnert mich irgendwie an das Protokol, das ich für OMA DRM
implementiere :)
Was ist OMA DRM?
Open Mobile Alliance Digital Rights Management?
(Google ist doch was feines ... ;-)
Post by Stefan Matthias Aust
Post by Stefanie Wiemann
Aber egal, was ich tue, entweder der Sender oder der Empfänger muß
die Zertifikatskette zusammenbauen.
Eigentlich sollen sich ja beide gegenseitig prüfen können. Idealerweise
wünscht sich ObdA der Server ein Trust Anchor, zu dem dann der Client
eine Zertifikatskette liefern muss und der Client selbst wünscht sich
einen Trust Anchor, für den dann der Server seine Zertifikatskette
liefern muss.
D.h. sowohl Client als auch Server haben jeweils das Root-Zertifikat
der "allerobersten" CA (bzw einer, der sie vertrauen) (=Trust Anchor)
in ihrem KeyStore? Und bei jedem Request/Response wird dann die
Zertifikatskette dazu mitgeschickt?
Bzw. wenn ich einmal alles mitschicke und abspeichere (enthält so eine
Kette eigentlich die vollständigen Zertifikate?), brauche ich danach
keine Zertifikate mehr mitzuschicken?
Post by Stefan Matthias Aust
Wenn du alles tauschen willst, musst du auch alles mitschicken.
Aber nur einmal?
Post by Stefan Matthias Aust
Post by Stefanie Wiemann
Wie mache ich das?
Ein X509-Zertifikat kann einfach in ein DER-encodetes byte[] verwandelt
werden. Davon kannst du doch problemlos mehrere verschicken. Die
andere Seite muss aus dem DER-encodeten byte[] wieder ein
X509-Zertifikatsobjekt machen.
Kann man auch mehrere Zerts in ein Objekt (Datei) packen?
CertificateFactory#generateCertificates liest ja aus einem Stream auch
mehrere Zerts ein.
Die API-Doku sagt:
"In the case of a certificate factory for X.509 certificates, inStream
may contain a sequence of DER-encoded certificates in the formats
described for generateCertificate. In addition, inStream may contain a
PKCS#7 certificate chain. This is a PKCS#7 SignedData object, with the
only significant field being certificates. In particular, the signature
and the contents are ignored. This format allows multiple certificates
to be downloaded at once."

Ok, also PKCS#7 SignedData ansehen ...
Post by Stefan Matthias Aust
Post by Stefanie Wiemann
- Einlesen aller Zertifikate aus dem KeyStore in einen CertStore
- Herausfiltern des Issuers aus dem Anwenderzertifikat
- einen X509CertSelector basteln (wie auch immer), der als Owner
(=Subject?) diesen Issuer enthält und evtl noch die SerialNumber
- damit getCertificates() des CertStores aufrufen und hoffen, daß ich
nur ein Ergebnis bekomme
- aus diesem Zertifikat wieder den Issuer herausfiltern, damit wieder
wie oben den X509CertSelector basteln
- usw
Kingt richtig. Aber schau dir den CertPathBuilder an. Der kann das.
Post by Stefanie Wiemann
CertPath und CertPathBuilder machen doch in etwa das gleiche? Leider
bin ich aus der API-Doku nicht richtig schlau geworden.
Ja.
Post by Stefanie Wiemann
Muß ich die PKIX-Varianten von CertPath, CertPathBuilder,
BuilderParameters ... verwenden (für X509Certificates)?
Ja.
... und den CertPathBuilder.

Steffi
Stefan Matthias Aust
2005-06-03 09:03:33 UTC
Permalink
Post by Stefanie Wiemann
Hmm. Das ganze ist die Implementierung eines Zeitstempeldienstes.
Der Client fordert einen Zeitstempel vom Server an. Dafür schickt er
einen TimeStampRequest. Der Server antwortet mit einer
TimeStampResponse. Die enthält sowieso schon signierte Daten, die sich
(mit Zertifikat) authentifizieren lassen.
Nur der TimeStampRequest ist noch nicht signiert. Im RFC 3161
(TimeStamp Protocol) wird empfohlen, das über CMS zu tun. Heißt
übrigens hier nicht Content Management System, sondern Cryptographic
Message Syntax.
Ach so. Ich hasse mehrdeutige Abkürzungen.
Post by Stefanie Wiemann
Was ist OMA DRM?
Open Mobile Alliance Digital Rights Management?
(Google ist doch was feines ... ;-)
Ja (zu beidem)
Post by Stefanie Wiemann
Post by Stefan Matthias Aust
Eigentlich sollen sich ja beide gegenseitig prüfen können. Idealerweise
wünscht sich ObdA der Server ein Trust Anchor, zu dem dann der Client
eine Zertifikatskette liefern muss und der Client selbst wünscht sich
einen Trust Anchor, für den dann der Server seine Zertifikatskette
liefern muss.
D.h. sowohl Client als auch Server haben jeweils das Root-Zertifikat
der "allerobersten" CA (bzw einer, der sie vertrauen) (=Trust Anchor)
in ihrem KeyStore? Und bei jedem Request/Response wird dann die
Zertifikatskette dazu mitgeschickt?
Ja.
Post by Stefanie Wiemann
Bzw. wenn ich einmal alles mitschicke und abspeichere (enthält so eine
Kette eigentlich die vollständigen Zertifikate?), brauche ich danach
keine Zertifikate mehr mitzuschicken?
Genau. Die Frage ist nur, was ist aufwendiger: Einfach immer schicken
oder erstmal aushandeln, ob geschickt werden muss oder nicht.
Post by Stefanie Wiemann
Kann man auch mehrere Zerts in ein Objekt (Datei) packen?
Spätestens, wenn du das Dateiformat unter Kontrolle hast. Das müsste
sogar ASN.1-Kompatibel gehen, indem du einfach nochmal eine Sequenz der
Zertifikate definierst. Ich kenne die Randbedingungen deiner RFCs da
nicht und habe ehrlich gesagt auch keine Lust, diese zu studieren :)
Post by Stefanie Wiemann
Ok, also PKCS#7 SignedData ansehen ...
:) Ich glaube ja, da steckt eine perfide Methode von Schadenfreude der
ursprünglichen Autoren dahinter: Wenn es schon so verdammt schwer war,
sich den ganzen Kram auszudenken, dann soll doch bitte jeder, der sich
da arbeitet, leiden, indem wir ihn von Spec zu Spec zu Spec scheuchen.
--
Stefan Matthias Aust
Loading...