001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    
018    package org.apache.geronimo.util.jce;
019    
020    import java.io.ByteArrayInputStream;
021    import java.io.ByteArrayOutputStream;
022    import java.math.BigInteger;
023    import java.security.InvalidKeyException;
024    import java.security.NoSuchAlgorithmException;
025    import java.security.NoSuchProviderException;
026    import java.security.PrivateKey;
027    import java.security.PublicKey;
028    import java.security.SecureRandom;
029    import java.security.Signature;
030    import java.security.SignatureException;
031    import java.security.cert.X509Certificate;
032    import java.util.Date;
033    import java.util.Hashtable;
034    
035    import org.apache.geronimo.util.asn1.ASN1EncodableVector;
036    import org.apache.geronimo.util.asn1.ASN1InputStream;
037    import org.apache.geronimo.util.asn1.ASN1Sequence;
038    import org.apache.geronimo.util.asn1.DERBitString;
039    import org.apache.geronimo.util.asn1.DERInteger;
040    import org.apache.geronimo.util.asn1.DERNull;
041    import org.apache.geronimo.util.asn1.DERObjectIdentifier;
042    import org.apache.geronimo.util.asn1.DEROutputStream;
043    import org.apache.geronimo.util.asn1.DERSequence;
044    import org.apache.geronimo.util.asn1.x509.AlgorithmIdentifier;
045    import org.apache.geronimo.util.asn1.x509.SubjectPublicKeyInfo;
046    import org.apache.geronimo.util.asn1.x509.TBSCertificateStructure;
047    import org.apache.geronimo.util.asn1.x509.Time;
048    import org.apache.geronimo.util.asn1.x509.V1TBSCertificateGenerator;
049    import org.apache.geronimo.util.asn1.x509.X509CertificateStructure;
050    import org.apache.geronimo.util.asn1.x509.X509Name;
051    import org.apache.geronimo.util.jce.provider.X509CertificateObject;
052    
053    /**
054     * class to produce an X.509 Version 1 certificate.
055     *
056     * @deprecated use the equivalent class in org.apache.geronimo.util.x509
057     */
058    public class X509V1CertificateGenerator
059    {
060        private V1TBSCertificateGenerator   tbsGen;
061        private DERObjectIdentifier         sigOID;
062        private AlgorithmIdentifier         sigAlgId;
063        private String                      signatureAlgorithm;
064    
065        private static Hashtable            algorithms = new Hashtable();
066    
067        static
068        {
069            algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
070            algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
071            algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
072            algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
073            algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
074            algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
075            algorithms.put("RIPEMD160WITHRSAENCRYPTION", new DERObjectIdentifier("1.3.36.3.3.1.2"));
076            algorithms.put("RIPEMD160WITHRSA", new DERObjectIdentifier("1.3.36.3.3.1.2"));
077            algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3"));
078            algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3"));
079            algorithms.put("SHA1WITHECDSA", new DERObjectIdentifier("1.2.840.10045.4.1"));
080            algorithms.put("ECDSAWITHSHA1", new DERObjectIdentifier("1.2.840.10045.4.1"));
081        }
082    
083        public X509V1CertificateGenerator()
084        {
085            tbsGen = new V1TBSCertificateGenerator();
086        }
087    
088        /**
089         * reset the generator
090         */
091        public void reset()
092        {
093            tbsGen = new V1TBSCertificateGenerator();
094        }
095    
096        /**
097         * set the serial number for the certificate.
098         */
099        public void setSerialNumber(
100            BigInteger      serialNumber)
101        {
102            tbsGen.setSerialNumber(new DERInteger(serialNumber));
103        }
104    
105        /**
106         * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
107         * certificate.
108         */
109        public void setIssuerDN(
110            X509Name   issuer)
111        {
112            tbsGen.setIssuer(issuer);
113        }
114    
115        public void setNotBefore(
116            Date    date)
117        {
118            tbsGen.setStartDate(new Time(date));
119        }
120    
121        public void setNotAfter(
122            Date    date)
123        {
124            tbsGen.setEndDate(new Time(date));
125        }
126    
127        /**
128         * Set the subject distinguished name. The subject describes the entity associated with the public key.
129         */
130        public void setSubjectDN(
131            X509Name   subject)
132        {
133            tbsGen.setSubject(subject);
134        }
135    
136        public void setPublicKey(
137            PublicKey       key)
138        {
139            try
140            {
141                tbsGen.setSubjectPublicKeyInfo(new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
142                                    new ByteArrayInputStream(key.getEncoded())).readObject()));
143            }
144            catch (Exception e)
145            {
146                throw new IllegalArgumentException("unable to process key - " + e.getMessage(), e);
147            }
148        }
149    
150        public void setSignatureAlgorithm(
151            String  signatureAlgorithm)
152        {
153            this.signatureAlgorithm = signatureAlgorithm;
154    
155            sigOID = (DERObjectIdentifier)algorithms.get(signatureAlgorithm.toUpperCase());
156    
157            if (sigOID == null)
158            {
159                throw new IllegalArgumentException("Unknown signature type requested");
160            }
161    
162            sigAlgId = new AlgorithmIdentifier(this.sigOID, new DERNull());
163    
164            tbsGen.setSignature(sigAlgId);
165        }
166    
167        /**
168         * generate an X509 certificate, based on the current issuer and subject
169         * using the default provider "BC".
170         */
171        public X509Certificate generateX509Certificate(
172            PrivateKey      key)
173            throws SecurityException, SignatureException, InvalidKeyException
174        {
175            try
176            {
177                return generateX509Certificate(key, null, null);
178            }
179            catch (NoSuchProviderException e)
180            {
181                throw (SecurityException)new SecurityException("JCE provider not installed!").initCause(e);
182            }
183        }
184    
185        /**
186         * generate an X509 certificate, based on the current issuer and subject
187         * using the default provider and the passed in source of randomness
188         */
189        public X509Certificate generateX509Certificate(
190            PrivateKey      key,
191            SecureRandom    random)
192            throws SecurityException, SignatureException, InvalidKeyException
193        {
194            try
195            {
196                return generateX509Certificate(key, null, random);
197            }
198            catch (NoSuchProviderException e)
199            {
200                throw (SecurityException)new SecurityException("JCE provider not installed!").initCause(e);
201            }
202        }
203    
204        /**
205         * generate an X509 certificate, based on the current issuer and subject,
206         * using the passed in provider for the signing, and the passed in source
207         * of randomness (if required).
208         */
209        public X509Certificate generateX509Certificate(
210            PrivateKey      key,
211            String          provider)
212            throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
213        {
214            return generateX509Certificate(key, provider, null);
215        }
216    
217        /**
218         * generate an X509 certificate, based on the current issuer and subject,
219         * using the passed in provider for the signing, and the passed in source
220         * of randomness (if required).
221         */
222        public X509Certificate generateX509Certificate(
223            PrivateKey      key,
224            String          provider,
225            SecureRandom    random)
226            throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
227        {
228            Signature sig = null;
229    
230            try
231            {
232                if (provider == null) {
233                    sig = Signature.getInstance(sigOID.getId());
234                }
235                else {
236                    sig = Signature.getInstance(sigOID.getId(), provider);
237                }
238            }
239            catch (NoSuchAlgorithmException ex)
240            {
241                try
242                {
243                    if (provider == null) {
244                        sig = Signature.getInstance(signatureAlgorithm);
245                    }
246                    else {
247                        sig = Signature.getInstance(signatureAlgorithm, provider);
248                    }
249                }
250                catch (NoSuchAlgorithmException e)
251                {
252                    throw (SecurityException)new SecurityException("exception creating signature: " + e.getMessage()).initCause(e);
253                }
254            }
255    
256            if (random != null)
257            {
258                sig.initSign(key, random);
259            }
260            else
261            {
262                sig.initSign(key);
263            }
264    
265            TBSCertificateStructure tbsCert = tbsGen.generateTBSCertificate();
266    
267            try
268            {
269                ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
270                DEROutputStream         dOut = new DEROutputStream(bOut);
271    
272                dOut.writeObject(tbsCert);
273    
274                sig.update(bOut.toByteArray());
275            }
276            catch (Exception e)
277            {
278                throw (SecurityException)new SecurityException("exception encoding TBS cert - " + e.getMessage()).initCause(e);
279            }
280    
281            ASN1EncodableVector  v = new ASN1EncodableVector();
282    
283            v.add(tbsCert);
284            v.add(sigAlgId);
285            v.add(new DERBitString(sig.sign()));
286    
287            return new X509CertificateObject(new X509CertificateStructure(new DERSequence(v)));
288        }
289    }