Clover Coverage Report
Coverage timestamp: Sun Mar 23 2008 08:24:39 GMT
38   169   9   9.5
8   66   0.32   4
4     3  
1    
 
 
  PKCS12Security       Line # 60 38 9 84% 0.84
 
No Tests
 
1    /*
2    * Copyright (c) 2006, University of Kent
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are met:
7    *
8    * Redistributions of source code must retain the above copyright notice, this
9    * list of conditions and the following disclaimer.
10    *
11    * Redistributions in binary form must reproduce the above copyright notice,
12    * this list of conditions and the following disclaimer in the documentation
13    * and/or other materials provided with the distribution.
14    *
15    * 1. Neither the name of the University of Kent nor the names of its
16    * contributors may be used to endorse or promote products derived from this
17    * software without specific prior written permission.
18    *
19    * 2. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20    * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21    * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22    * PURPOSE ARE DISCLAIMED.
23    *
24    * 3. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31    * POSSIBILITY OF SUCH DAMAGE.
32    *
33    * 4. YOU AGREE THAT THE EXCLUSIONS IN PARAGRAPHS 2 AND 3 ABOVE ARE REASONABLE
34    * IN THE CIRCUMSTANCES. IN PARTICULAR, YOU ACKNOWLEDGE (1) THAT THIS
35    * SOFTWARE HAS BEEN MADE AVAILABLE TO YOU FREE OF CHARGE, (2) THAT THIS
36    * SOFTWARE IS NOT "PRODUCT" QUALITY, BUT HAS BEEN PRODUCED BY A RESEARCH
37    * GROUP WHO DESIRE TO MAKE THIS SOFTWARE FREELY AVAILABLE TO PEOPLE WHO WISH
38    * TO USE IT, AND (3) THAT BECAUSE THIS SOFTWARE IS NOT OF "PRODUCT" QUALITY
39    * IT IS INEVITABLE THAT THERE WILL BE BUGS AND ERRORS, AND POSSIBLY MORE
40    * SERIOUS FAULTS, IN THIS SOFTWARE.
41    *
42    * 5. This license is governed, except to the extent that local laws
43    * necessarily apply, by the laws of England and Wales.
44    */
45    package issrg.security;
46   
47    import java.security.cert.X509Certificate;
48    import java.security.PrivateKey;
49   
50    import java.io.File;
51    import java.io.FileNotFoundException;
52   
53    /**
54    * This class implements a security that uses a PKCS#12 file to authenticate
55    * the user and obtain the signing and signature verification keys. The user
56    * interaction is inherited from DefaultSecurity. Only the key methods are
57    * overridden to log the user in using a known PKCS#12 file name, and
58    * a method to construct a FilenameCallback.
59    */
 
60    public class PKCS12Security extends DefaultSecurity {
61    private static final byte [] checkbytes=new byte[256];
62   
 
63  2 toggle static{
64  514 for (int i=0; i<checkbytes.length; i++) checkbytes[i]=(byte)i;
65   
66  2 iaik.security.provider.IAIK.addAsJDK14Provider();
67    }
68   
 
69  4 toggle public PKCS12Security() throws SecurityException {
70  4 super();
71    }
72   
73    /**
74    * The method for logging the user in without GUI. The method attempts to
75    * decrypt the private key, then signs and verifies a signature on an
76    * arbitrary
77    * byte array to ensure that the private key and the PKC match. Note that for
78    * signing purposes it is necessary to know the DN of the signer, which is
79    * not included
80    * in the private key.
81    *
82    * <p>After logging the user in the Root CAs are set to the collection of PKCs
83    * in the PKCS#12 file, including the user's signature verification PKC. The
84    * first PKC to match the signing key is used as the user's signature
85    * verification key.
86    *
87    * @param pkcFile is the filename of the PKCS#12 construct
88    * @param password is the password for decrypting the PKCS#12 file
89    */
 
90  3 toggle public void login(String pkcFile, char[] password) throws SecurityException {
91  3 X509Certificate [] x509=getRootCAs();
92  3 X509Certificate [] rootCA;
93  3 PrivateKey pk=getPrivateKey();
94  3 java.security.Signature signature=getSignature();
95   
96  3 try{
97  3 java.io.FileInputStream fin=new java.io.FileInputStream(pkcFile);
98  3 iaik.pkcs.pkcs12.PKCS12 epki = new iaik.pkcs.pkcs12.PKCS12(fin);
99  3 epki.decrypt(password);
100   
101    // here the PKCS12 file should have been decrypted ok
102   
103  3 secretKey=epki.getKeyBag().getPrivateKey();
104  3 rootCA=iaik.pkcs.pkcs12.CertificateBag.getCertificates(epki.getCertificateBags());
105   
106    // here both x509 and pk are fine
107    // lets check if they match each other
108   
109  3 String sigAlg = getDigestAlgorithm()+"with"+secretKey.getAlgorithm();
110  3 setSignature(java.security.Signature.getInstance(sigAlg));
111   
112  3 byte [] sig=sign(checkbytes);
113    // the use of rootCA.getSigAlgOID() is not always correct. This value shows what algorithm was used to sign rootCA certificate
114    // we can reuse this algorithm only if rootCA is really a self-signed PKC, which usually it is, but in a simplistic "PKI"
115    // non-selfsigned PKCs may be allowed
116  3 boolean verified=false;
117  5 for (int i=0; i<rootCA.length; i++){
118  5 try{
119  5 if (verify(checkbytes, sig, sigAlg, new X509Certificate[]{rootCA[i]})){
120  3 X509Certificate c=rootCA[0]; // reorder them so that the entity PKC is the first in the array
121  3 rootCA[0]=rootCA[i];
122  3 rootCA[i]=c;
123  3 verified=true;
124  3 break;
125    }
126    }catch(Exception ex){
127    // ignore - this is not the key of the holder; try another
128    }
129    }
130  3 if (verified){ // the signature verifies
131  3 x509=rootCA; // note that the finally statement requires such substitution, so the keys will be properly remembered
132  3 pk=secretKey;
133  3 signature=getSignature();
134    }else{
135  0 throw new SecurityException ("The PKC does not match the Private Key. Use another key-pair.");
136    }
137   
138    }catch (SecurityException se){
139  0 throw se;
140    }catch (FileNotFoundException fnfe) {
141  0 throw new SecurityException("Could not find the P12 file", fnfe);
142    }catch(Exception e){
143  0 throw new SecurityException("Failed to log into the specified PKCS#12", e);
144    }finally{ // restore the private key and PKC as they were before executing the method
145    // unless the values of the x509 and pk have been updated due to successful signature verification
146  3 setRootCAs(x509);
147  3 setPrivateKey(pk);
148  3 setSignature(signature);
149    }
150    }
151   
152    final public static String PKC_EXTENSION=".p12";
153    final public static String PFX_EXTENSION=".pfx";
154    final public static String exts[] = new String[]{PKC_EXTENSION, PFX_EXTENSION};
155   
156    /**
157    * This method constructs a FilenameCallback that will filter out all but
158    * PKCS#12 files with the extensions PKC_EXTENSION (".p12") and PFX_EXTENSION
159    * (".pfx").
160    *
161    * @param defaultFile - the default file to use if the user doesn't make any
162    * selection
163    *
164    * @return FilenameCallback configured to display PKCS#12 files only
165    */
 
166  0 toggle public FilenameCallback getFilenameCallback(String defaultFile){
167  0 return new FilenameCallback("PKCS#12 file", defaultFile, "PKCS#12 Files", exts);
168    }
169    }