summaryrefslogtreecommitdiffstats
path: root/base/util/src/netscape/security/x509/CertAndKeyGen.java
diff options
context:
space:
mode:
Diffstat (limited to 'base/util/src/netscape/security/x509/CertAndKeyGen.java')
-rw-r--r--base/util/src/netscape/security/x509/CertAndKeyGen.java290
1 files changed, 290 insertions, 0 deletions
diff --git a/base/util/src/netscape/security/x509/CertAndKeyGen.java b/base/util/src/netscape/security/x509/CertAndKeyGen.java
new file mode 100644
index 000000000..1579d46bf
--- /dev/null
+++ b/base/util/src/netscape/security/x509/CertAndKeyGen.java
@@ -0,0 +1,290 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package netscape.security.x509;
+
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+import netscape.security.pkcs.PKCS10;
+
+/**
+ * Generate a pair of keys, and provide access to them. This class is
+ * provided primarily for ease of use.
+ *
+ * <P>
+ * This provides some simple certificate management functionality. Specifically, it allows you to create self-signed
+ * X.509 certificates as well as PKCS 10 based certificate signing requests.
+ *
+ * <P>
+ * Keys for some public key signature algorithms have algorithm parameters, such as DSS/DSA. Some sites' Certificate
+ * Authorities adopt fixed algorithm parameters, which speeds up some operations including key generation and signing.
+ * <em>At this time, this interface
+ * does not provide a way to provide such algorithm parameters, e.g.
+ * by providing the CA certificate which includes those parameters.</em>
+ *
+ * <P>
+ * Also, note that at this time only signature-capable keys may be acquired through this interface. Diffie-Hellman keys,
+ * used for secure key exchange, may be supported later.
+ *
+ * @author David Brownell
+ * @author Hemma Prafullchandra
+ * @version 1.44
+ * @see PKCS10
+ * @see X509CertImpl
+ */
+public final class CertAndKeyGen {
+ /**
+ * Creates a CertAndKeyGen object for a particular key type
+ * and signature algorithm.
+ *
+ * @param keyType type of key, e.g. "RSA", "DSA"
+ * @param sigAlg name of the signature algorithm, e.g. "MD5WithRSA",
+ * "MD2WithRSA", "SHAwithDSA".
+ * @exception NoSuchAlgorithmException on unrecognized algorithms.
+ */
+ public CertAndKeyGen(String keyType, String sigAlg)
+ throws NoSuchAlgorithmException {
+ keyGen = KeyPairGenerator.getInstance(keyType);
+ this.sigAlg = sigAlg;
+ }
+
+ /**
+ * Sets the source of random numbers used when generating keys.
+ * If you do not provide one, a system default facility is used.
+ * You may wish to provide your own source of random numbers
+ * to get a reproducible sequence of keys and signatures, or
+ * because you may be able to take advantage of strong sources
+ * of randomness/entropy in your environment.
+ *
+ * @deprecated All random numbers come from PKCS #11 now.
+ */
+ public void setRandom(SecureRandom generator) {
+ }
+
+ // want "public void generate (X509Certificate)" ... inherit DSA/D-H param
+
+ /**
+ * Generates a random public/private key pair, with a given key
+ * size. Different algorithms provide different degrees of security
+ * for the same key size, because of the "work factor" involved in
+ * brute force attacks. As computers become faster, it becomes
+ * easier to perform such attacks. Small keys are to be avoided.
+ *
+ * <P>
+ * Note that not all values of "keyBits" are valid for all algorithms, and not all public key algorithms are
+ * currently supported for use in X.509 certificates. If the algorithm you specified does not produce X.509
+ * compatible keys, an invalid key exception is thrown.
+ *
+ * @param keyBits the number of bits in the keys.
+ * @exception InvalidKeyException if the environment does not
+ * provide X.509 public keys for this signature algorithm.
+ */
+ public void generate(int keyBits)
+ throws InvalidKeyException {
+ KeyPair pair;
+
+ try {
+ keyGen.initialize(keyBits);
+ pair = keyGen.generateKeyPair();
+
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e.getMessage());
+ }
+
+ PublicKey publicKey = pair.getPublic();
+
+ if (publicKey instanceof X509Key) {
+ this.publicKey = (X509Key) publicKey;
+
+ } else {
+ throw new InvalidKeyException("public key " + publicKey +
+ " not an X509Key.");
+ }
+ privateKey = pair.getPrivate();
+ }
+
+ /**
+ * Returns the public key of the generated key pair.
+ */
+ public X509Key getPublicKey() {
+ return publicKey;
+ }
+
+ /**
+ * Returns the private key of the generated key pair.
+ *
+ * <P>
+ * <STRONG><em>Be extremely careful when handling private keys.
+ * When private keys are not kept secret, they lose their ability
+ * to securely authenticate specific entities ... that is a huge
+ * security risk!</em></STRONG>
+ */
+ public PrivateKey getPrivateKey() {
+ return privateKey;
+ }
+
+ /**
+ * Returns a self-signed X.509v1 certificate for the public key.
+ * The certificate is immediately valid.
+ *
+ * <P>
+ * Such certificates normally are used to identify a "Certificate Authority" (CA). Accordingly, they will not always
+ * be accepted by other parties. However, such certificates are also useful when you are bootstrapping your security
+ * infrastructure, or deploying system prototypes.
+ *
+ * @deprecated Use the new <a href =
+ * "#getSelfCertificate(netscape.security.x509.X500Name, long)">
+ *
+ * @param myname X.500 name of the subject (who is also the issuer)
+ * @param validity how long the certificate should be valid, in seconds
+ */
+ public X509Cert getSelfCert(X500Name myname, long validity)
+ throws InvalidKeyException, SignatureException, NoSuchAlgorithmException {
+ X509Certificate cert;
+
+ try {
+ cert = getSelfCertificate(myname, validity);
+ return new X509Cert(cert.getEncoded());
+ } catch (CertificateException e) {
+ throw new SignatureException(e.getMessage());
+ } catch (NoSuchProviderException e) {
+ throw new NoSuchAlgorithmException(e.getMessage());
+ } catch (IOException e) {
+ throw new SignatureException(e.getMessage());
+ }
+ }
+
+ /**
+ * Returns a self-signed X.509v3 certificate for the public key.
+ * The certificate is immediately valid. No extensions.
+ *
+ * <P>
+ * Such certificates normally are used to identify a "Certificate Authority" (CA). Accordingly, they will not always
+ * be accepted by other parties. However, such certificates are also useful when you are bootstrapping your security
+ * infrastructure, or deploying system prototypes.
+ *
+ * @param myname X.500 name of the subject (who is also the issuer)
+ * @param validity how long the certificate should be valid, in seconds
+ * @exception CertificateException on certificate handling errors.
+ * @exception InvalidKeyException on key handling errors.
+ * @exception SignatureException on signature handling errors.
+ * @exception NoSuchAlgorithmException on unrecognized algorithms.
+ * @exception NoSuchProviderException on unrecognized providers.
+ */
+ public X509Certificate getSelfCertificate(X500Name myname, long validity)
+ throws CertificateException, InvalidKeyException, SignatureException,
+ NoSuchAlgorithmException, NoSuchProviderException {
+ X500Signer issuer;
+ X509CertImpl cert;
+ Date firstDate, lastDate;
+
+ try {
+ issuer = getSigner(myname);
+
+ firstDate = new Date();
+ lastDate = new Date();
+ lastDate.setTime(lastDate.getTime() + validity * 1000);
+
+ CertificateValidity interval =
+ new CertificateValidity(firstDate, lastDate);
+
+ X509CertInfo info = new X509CertInfo();
+ // Add all mandatory attributes
+ info.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V1));
+ info.set(X509CertInfo.SERIAL_NUMBER,
+ new CertificateSerialNumber((int) (firstDate.getTime() / 1000)));
+ AlgorithmId algID = issuer.getAlgorithmId();
+ info.set(X509CertInfo.ALGORITHM_ID,
+ new CertificateAlgorithmId(algID));
+ info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(myname));
+ info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
+ info.set(X509CertInfo.VALIDITY, interval);
+ info.set(X509CertInfo.ISSUER,
+ new CertificateIssuerName(issuer.getSigner()));
+
+ cert = new X509CertImpl(info);
+ cert.sign(privateKey, algID.getName());
+
+ return (X509Certificate) cert;
+
+ } catch (IOException e) {
+ throw new CertificateEncodingException("getSelfCert: " +
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Returns a PKCS #10 certificate request. The caller uses either <code>PKCS10.print</code> or
+ * <code>PKCS10.toByteArray</code> operations on the result, to get the request in an appropriate
+ * transmission format.
+ *
+ * <P>
+ * PKCS #10 certificate requests are sent, along with some proof of identity, to Certificate Authorities (CAs) which
+ * then issue X.509 public key certificates.
+ *
+ * @param myname X.500 name of the subject
+ * @exception InvalidKeyException on key handling errors.
+ * @exception SignatureException on signature handling errors.
+ */
+ public PKCS10 getCertRequest(X500Name myname)
+ throws InvalidKeyException, SignatureException {
+ PKCS10 req = new PKCS10(publicKey);
+
+ try {
+ req.encodeAndSign(getSigner(myname));
+
+ } catch (CertificateException e) {
+ throw new SignatureException(sigAlg + " CertificateException");
+
+ } catch (IOException e) {
+ throw new SignatureException(sigAlg + " IOException");
+
+ } catch (NoSuchAlgorithmException e) {
+ // "can't happen"
+ throw new SignatureException(sigAlg + " unavailable?");
+ }
+ return req;
+ }
+
+ private X500Signer getSigner(X500Name me)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+ Signature signature = Signature.getInstance(sigAlg);
+
+ signature.initSign(privateKey);
+ return new X500Signer(signature, me);
+ }
+
+ private String sigAlg;
+ private KeyPairGenerator keyGen;
+ private X509Key publicKey;
+ private PrivateKey privateKey;
+}