Frage

Ist es möglich, ein X509-Zertifikat in Java-Code sanely zu erstellen, ohne die Hüpfburg X509V*CertificateGenerator Klassen?

War es hilfreich?

Lösung

Die Möglichkeit, Zertifikate zu unterzeichnen ist nicht Teil einer Standard-Java-Bibliothek oder Erweiterung.

Eine Menge des Codes, der es selbst zu tun benötigt wird, ist ein Teil des Kerns. Es gibt Klassen zu kodieren und zu dekodieren X.500-Namen, X.509 Zertifikatserweiterungen, Öffentliche Schlüssel für verschiedene Algorithmen, und natürlich für tatsächlich die digitale Signatur durchgeführt wird.

Diese Implementierung selbst ist nicht trivial, aber es ist auf jeden Fall machbar-I wahrscheinlich 4 oder 5 volle Tage zum ersten Mal habe ich einen funktionierenden Prototyp für die Zertifikatsignierungsanforderung gemacht. Es war ein fantastisch Übung für mich zu lernen, aber es ist schwer, diese Kosten zu rechtfertigen, wenn es kostenlos nutzbare Bibliotheken zur Verfügung stehen.

Andere Tipps

Ja, aber nicht mit öffentlich dokumentiert Klassen. Ich habe den Prozess in diesem Artikel dokumentiert.

import sun.security.x509.*;
import java.security.cert.*;
import java.security.*;
import java.math.BigInteger;
import java.util.Date;
import java.io.IOException

/** 
 * Create a self-signed X.509 Certificate
 * @param dn the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
 * @param pair the KeyPair
 * @param days how many days from now the Certificate is valid for
 * @param algorithm the signing algorithm, eg "SHA1withRSA"
 */ 
X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm)
  throws GeneralSecurityException, IOException
{
  PrivateKey privkey = pair.getPrivate();
  X509CertInfo info = new X509CertInfo();
  Date from = new Date();
  Date to = new Date(from.getTime() + days * 86400000l);
  CertificateValidity interval = new CertificateValidity(from, to);
  BigInteger sn = new BigInteger(64, new SecureRandom());
  X500Name owner = new X500Name(dn);
 
  info.set(X509CertInfo.VALIDITY, interval);
  info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
  info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
  info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
  info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
  info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
  AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
  info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));
 
  // Sign the cert to identify the algorithm that's used.
  X509CertImpl cert = new X509CertImpl(info);
  cert.sign(privkey, algorithm);
 
  // Update the algorith, and resign.
  algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG);
  info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
  cert = new X509CertImpl(info);
  cert.sign(privkey, algorithm);
  return cert;
}   
import sun.security.x509.*;

import java.security.cert.*;
import java.security.*;
import java.math.BigInteger;
import java.security.cert.Certificate;
import java.util.Date;
import java.io.IOException;

public class Example {
    /**
     * Create a self-signed X.509 Example
     *
     * @param dn        the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
     * @param pair      the KeyPair
     * @param days      how many days from now the Example is valid for
     * @param algorithm the signing algorithm, eg "SHA1withRSA"
     */
    public X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm)
            throws GeneralSecurityException, IOException {
        PrivateKey privkey = pair.getPrivate();
        X509CertInfo info = new X509CertInfo();
        Date from = new Date();
        Date to = new Date(from.getTime() + days * 86400000l);
        CertificateValidity interval = new CertificateValidity(from, to);
        BigInteger sn = new BigInteger(64, new SecureRandom());
        X500Name owner = new X500Name(dn);

        info.set(X509CertInfo.VALIDITY, interval);
        info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
        info.set(X509CertInfo.SUBJECT, owner);
        info.set(X509CertInfo.ISSUER, owner);
        info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
        info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
        AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
        info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));

        // Sign the cert to identify the algorithm that's used.
        X509CertImpl cert = new X509CertImpl(info);
        cert.sign(privkey, algorithm);

        // Update the algorith, and resign.
        algo = (AlgorithmId) cert.get(X509CertImpl.SIG_ALG);
        info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
        cert = new X509CertImpl(info);
        cert.sign(privkey, algorithm);
        return cert;
    }

    public static void main (String[] argv) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        Example example = new Example();
        String distinguishedName = "CN=Test, L=London, C=GB";
        Certificate certificate = example.generateCertificateOriginal(distinguishedName, keyPair, 365, "SHA256withRSA");
        System.out.println("it worked!");
    }
}

Ich mochte vbence Antwort, aber ich hielt die folgende Ausnahme erhalten:

java.security.cert.CertificateException. Subject Klassentyp ungültig

Nach vielen Versuchen, um herauszufinden, liegt bei einer gültigen Gegenstand Klasse fand ich heraus, dass X509CerInfo eine Instanz X500Name wollte.

1 info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
2 info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
3 info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
4 info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));

So Linien 2 und 3 benötigt, um zu ändern

2 info.set(X509CertInfo.SUBJECT, owner);
3 info.set(X509CertInfo.ISSUER, owner);

Alle grundlegenden Komponenten eines selbstsignierten Zertifikat zu machen (Unterzeichnung, X509 Codierung usw.) sind in JRE zur Verfügung. Im Gegensatz zu BC, hat Sun JCE bieten keine öffentlichen Anrufe ein Zertifikat zu unterzeichnen. Jedoch sind alle Funktionen sind in Keytool zur Verfügung. Sie können einfach den Code aus keytool kopieren, dies zu tun. Die Methode, die Sie kopieren müssen, ist doSelfCert().

Abhängig von was genau wollen Sie tun (und wahrscheinlich Ihre Definition von „sanely“). Wie ZZ Coder wies darauf hin, können Sie ein selbst signiertes Zertifikat direkt durch Kopieren keytool . Aber ich glaube nicht, dass Sie ein PKCS10 Zertifikat Request-Objekt mit dem Standard-JCE erstellen können, die Sie wahrscheinlich tun müssen, wenn Sie Standard-CA-signierten EECs erstellen möchten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top