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