KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > oyster > util > PFXUtils


1 /*
2  * Title: Oyster Project
3  * Description: S/MIME email sending capabilities
4  * @Author Vladimir Radisic
5  * @Version 2.1.5
6  */

7
8 package org.enhydra.oyster.util;
9
10 import java.security.KeyStore JavaDoc;
11 import java.security.Signature JavaDoc;
12 import java.security.PrivateKey JavaDoc;
13 import java.security.cert.X509Certificate JavaDoc;
14 import java.util.Vector JavaDoc;
15 import java.util.Enumeration JavaDoc;
16 import org.enhydra.oyster.exception.SMIMEException;
17 import org.enhydra.oyster.exception.ErrorStorage;
18 import org.bouncycastle.jce.provider.JDKDigestSignature;
19
20 import java.security.cert.Certificate JavaDoc;
21
22 /**
23  * PFXUtils class has static methods which are dealing with .pfx, or .p12
24  * files. The file (of this types) presents storage for keeping certificate
25  * chain and private key. Information from this files are being transported
26  * through programs via instance of the Java class KeyStore.
27  */

28 public class PFXUtils {
29
30 /**
31  * Returns the owner's Certificate from his .pfx or .p12 file (KeyStore)
32  * @param ks0 container for information from .pfx or .p12 file
33  * @return Owner's Certificate
34  * @exception SMIMEException if problem with extracting certificate
35  * chain from .pfx or .p12 file or with aliases in pfx or p12 file arrises.
36  * Also, it can be caused by non SMIMEException which is KeyStoreException.
37  */

38   public static X509Certificate JavaDoc getPFXOwnerX509Certificate (KeyStore JavaDoc ks0) throws SMIMEException {
39     X509Certificate JavaDoc[] certChain = PFXUtils.getCertificateChain(ks0);
40     if (certChain != null)
41       return certChain[0];
42
43     return PFXUtils.getAllX509Certificate(ks0)[0];
44   }
45
46 /**
47  * Returns the Private key of the certificate's owner from .pfx or .p12
48  * file (pkcs12 format)
49  * @param ks0 container for information from .pfx or .p12 file
50  * @return Owners private key
51  * @exception SMIMEException caused by non SMIMEException which can be one of
52  * the following: KeyStoreException, UnrecoverableKeyException or
53  * NoSuchAlgorithmException.
54  */

55   public static PrivateKey JavaDoc getPrivateKey (KeyStore JavaDoc ks0) throws SMIMEException{
56     String JavaDoc keyAlias = null; // Alias for public key certificate corresponding to private key
57
PrivateKey JavaDoc returnPrivateKey = null;
58     try {
59       Enumeration JavaDoc en = ks0.aliases();
60       while (en.hasMoreElements()) {
61         String JavaDoc temp = (String JavaDoc)en.nextElement();
62         if (ks0.isKeyEntry(temp))
63           keyAlias = temp;
64       }
65       returnPrivateKey = (PrivateKey JavaDoc)ks0.getKey(keyAlias, null); // Obtaining private key as PrivateKey class
66
}
67     catch(Exception JavaDoc e) {
68       throw SMIMEException.getInstance("org.enhydra.oyster.util.PFXUtils",
69                                         e, "getPrivateKey" );
70     }
71     return returnPrivateKey;
72   }
73
74 /**
75  * Returns all X509 Certificates stored in .pfx, or .p12 files
76  * (KeyStore). This method performs same task as method getCertificateChain() but
77  * on less elegant way. In the future project version, it will be completely
78  * replaced with the getCertificateChain() method.
79  * @param ks0 container for information from .pfx or .p12 file
80  * @return Certificate chain represented as array of X509Certificate objects
81  * with the owner's certificate at the first place.
82  * @exception SMIMEException if problem with extracting certificate
83  * chain from .pfx or .p12 file or with aliases in pfx or p12 file arrises.
84  * Also, it can be caused by non SMIMEException which is KeyStoreException.
85  */

86   public static X509Certificate JavaDoc[] getAllX509Certificate (KeyStore JavaDoc ks0) throws SMIMEException {
87
88     Vector JavaDoc v = new Vector JavaDoc(0, 1); // Collection of certificates from pfx file
89
String JavaDoc certAlias = null; // Alias for public key certificate corresponding to certificate
90
X509Certificate JavaDoc keyEntryCert = null;
91     int numberOfAlias = 0;
92     int numberOfCert = 0;
93     int numberOfKeyEntry = 0;
94     try {
95       Enumeration JavaDoc en = ks0.aliases();
96       while (en.hasMoreElements()) {
97         String JavaDoc temp = (String JavaDoc)en.nextElement();
98         numberOfAlias++;
99         if (ks0.isKeyEntry(temp)) { // owner
100
numberOfKeyEntry++;
101           keyEntryCert = (X509Certificate JavaDoc)ks0.getCertificate(temp);
102         }
103         if (ks0.isCertificateEntry(temp)) {
104           X509Certificate JavaDoc cerCert;
105           cerCert = (X509Certificate JavaDoc)ks0.getCertificate(temp); // Getting certificate
106
v.add(cerCert);
107           numberOfCert++;
108         }
109       }
110       if ((numberOfAlias == numberOfCert + numberOfKeyEntry) & (numberOfKeyEntry == 1)) {
111         if (keyEntryCert != null) {
112           v.add(0, keyEntryCert); // is owners certificate is asociated with "key entry" alias
113
}
114       }
115       else
116         throw new SMIMEException("org.enhydra.oyster.util.PFXUtils", 1037);
117      }
118     catch(Exception JavaDoc e) {
119       throw SMIMEException.getInstance("org.enhydra.oyster.util.PFXUtils",
120                                         e, "getAllX509Certificate" );
121     }
122     if (v.size() != 1)
123       v = getOwnersCertOnTop(v);
124     X509Certificate JavaDoc[] certChain = new X509Certificate JavaDoc[v.size()];
125     for(int i=0; i!=v.size(); i++)
126       certChain[i] = (X509Certificate JavaDoc)v.elementAt(i);
127     return certChain;
128   }
129
130 /**
131  * Returns all X509 Certificates stored in .pfx, or .p12 files (KeyStore). This
132  * method performs same task as method getAllX509Certificate() but on more elegant
133  * way.
134  * @param ks0 container for information from .pfx or .p12 file
135  * @return Certificate chain represented as array of X509Certificate objects
136  * with the owner's certificate at the first place.
137  * @exception SMIMEException caused by non SMIMEException which is
138  * KeyStoreException.
139  */

140   public static X509Certificate JavaDoc[] getCertificateChain (KeyStore JavaDoc ks0) throws SMIMEException{
141
142     boolean errorInChainReading = true;
143     int numberOfCert = 0;
144     Certificate JavaDoc[] certChain = new Certificate JavaDoc[0];
145
146     try {
147       Enumeration JavaDoc en = ks0.aliases();
148
149       while (en.hasMoreElements()) {
150         try {
151           String JavaDoc tempAlias = (String JavaDoc)en.nextElement();
152           Certificate JavaDoc[] tempCertChain = (Certificate JavaDoc[])ks0.getCertificateChain(tempAlias);
153           if(tempCertChain != null && tempCertChain.length == certChain.length) {
154             errorInChainReading = true;
155           }
156           if(tempCertChain != null && tempCertChain.length > certChain.length) {
157             errorInChainReading = false;
158             certChain = tempCertChain;
159           }
160           if(ks0.isCertificateEntry(tempAlias))
161             numberOfCert++;
162         }
163         catch(Exception JavaDoc e) {
164           continue;
165         }
166       }
167     }
168     catch(Exception JavaDoc e) {
169       throw SMIMEException.getInstance("org.enhydra.oyster.util.PFXUtils",
170                                         e, "getCertificateChain");
171     }
172
173     if ( certChain == null || certChain.length == 0 || errorInChainReading ||
174          certChain.length != numberOfCert)
175       return null;
176     else {
177       X509Certificate JavaDoc[] returnCertChain = new X509Certificate JavaDoc[certChain.length];
178       for(int i=0; i!=certChain.length; i++) {
179         returnCertChain[i] = (X509Certificate JavaDoc)certChain[i];
180       }
181       return returnCertChain;
182     }
183
184
185   }
186
187 /**
188  * Orders certificates in certificate chain with owner's certificate at the
189  * first position, in Vector representation, and root CA at the last position.
190  * @param v0 all certificates from .pfx or .p12 file
191  * @return Ordered certificates in Vector. Starts from owner's certificate (at
192  * first position) and ends with root CA certificate (at last position).
193  * @exception SMIMEException if problem with extracting certificate
194  * chain from .pfx or .p12 file arrises.
195  */

196   private static Vector JavaDoc getOwnersCertOnTop (Vector JavaDoc v0) throws SMIMEException {
197     Vector JavaDoc inOrder = new Vector JavaDoc(0, 1); // Storage for certificate chain
198
boolean ver = false;
199     int j = 0;
200     while (inOrder.size() == 0) {
201       if (j == v0.size())
202         throw new SMIMEException("org.enhydra.oyster.util.PFXUtils", 1038);
203       for (int i = 0; i != v0.size(); i++) {
204         if (i != j) {
205           ver = verification((X509Certificate JavaDoc)v0.elementAt(j), (X509Certificate JavaDoc)v0.elementAt(i));
206           if (ver) {
207             inOrder.add(v0.elementAt(j));
208             inOrder.add(v0.elementAt(i));
209             if (i > j) {
210               v0.removeElementAt(i);
211               v0.removeElementAt(j);
212             }
213             else {
214               v0.removeElementAt(j);
215               v0.removeElementAt(i);
216             }
217             break;
218           }
219         }
220       }
221       if (ver)
222         break;
223       j++;
224     }
225     j = 0;
226     int lenBefore = v0.size();
227     while (v0.size() != 0) {
228       if (j > lenBefore)
229         throw new SMIMEException("org.enhydra.oyster.util.PFXUtils", 1038);
230       for (int i = 0; i != v0.size(); i++) {
231         ver = verification((X509Certificate JavaDoc)v0.elementAt(i), (X509Certificate JavaDoc)inOrder.firstElement());
232         if (ver) {
233           inOrder.add(0, v0.elementAt(i));
234           v0.removeElementAt(i);
235           break;
236         }
237         ver = verification((X509Certificate JavaDoc)inOrder.lastElement(), (X509Certificate JavaDoc)v0.elementAt(i));
238         if (ver) {
239           inOrder.add(v0.elementAt(i));
240           v0.removeElementAt(i);
241           break;
242         }
243       }
244       j++;
245     }
246     return inOrder;
247   }
248
249 /**
250  * Checks the relations between two certificates: if one of them is signer
251  * of another one.
252  * @param cerOwner certificate for check
253  * @param cerIssuer certificate for check
254  * @return true or false information about signing informatin between certificates
255  */

256   private static boolean verification (X509Certificate JavaDoc cerOwner, X509Certificate JavaDoc cerIssuer) {
257     boolean ret = false;
258     try {
259       if (cerOwner.getSigAlgOID().equalsIgnoreCase("1.2.840.113549.1.1.5")) {
260         JDKDigestSignature.SHA1WithRSAEncryption jd = new JDKDigestSignature.SHA1WithRSAEncryption();
261         jd.initVerify(cerIssuer.getPublicKey());
262         jd.update(cerOwner.getTBSCertificate());
263         ret = jd.verify(cerOwner.getSignature());
264       }
265       else if (cerOwner.getSigAlgOID().equalsIgnoreCase("1.2.840.10040.4.3")) {
266         Signature JavaDoc sig = Signature.getInstance("SHA1withDSA", "SUN");
267         sig.initVerify(cerIssuer.getPublicKey());
268         sig.update(cerOwner.getTBSCertificate());
269         ret = sig.verify(cerOwner.getSignature());
270       }
271       else if (cerOwner.getSigAlgOID().equalsIgnoreCase("1.2.840.113549.1.1.2")) {
272         JDKDigestSignature.MD2WithRSAEncryption jd = new JDKDigestSignature.MD2WithRSAEncryption();
273         jd.initVerify(cerIssuer.getPublicKey());
274         jd.update(cerOwner.getTBSCertificate());
275         ret = jd.verify(cerOwner.getSignature());
276       }
277       else if (cerOwner.getSigAlgOID().equalsIgnoreCase("1.2.840.113549.1.1.4")) {
278         JDKDigestSignature.MD5WithRSAEncryption jd = new JDKDigestSignature.MD5WithRSAEncryption();
279         jd.initVerify(cerIssuer.getPublicKey());
280         jd.update(cerOwner.getTBSCertificate());
281         ret = jd.verify(cerOwner.getSignature());
282       }
283     } catch (Exception JavaDoc e) {
284       ret = false;
285     }
286     return ret;
287   }
288
289 }
290
291
292
293
Popular Tags