Source Code Cross Referenced for AppDescriptor.java in  » 6.0-JDK-Modules » j2me » com » sun » midp » jadtool » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » com.sun.midp.jadtool 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *   
003:         *
004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006:         * 
007:         * This program is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU General Public License version
009:         * 2 only, as published by the Free Software Foundation.
010:         * 
011:         * This program is distributed in the hope that it will be useful, but
012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014:         * General Public License version 2 for more details (a copy is
015:         * included at /legal/license.txt).
016:         * 
017:         * You should have received a copy of the GNU General Public License
018:         * version 2 along with this work; if not, write to the Free Software
019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020:         * 02110-1301 USA
021:         * 
022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023:         * Clara, CA 95054 or visit www.sun.com if you need additional
024:         * information or have any questions.
025:         */
026:
027:        package com.sun.midp.jadtool;
028:
029:        /*
030:         * Web proxy  - The URL retrieval mechanism in AppDescriptor does not
031:         *              work through a proxy server at this time.
032:         */
033:
034:        import java.io.*;
035:        import java.util.*;
036:        import java.net.URL;
037:        import java.net.MalformedURLException;
038:
039:        import java.security.KeyStore;
040:        import java.security.MessageDigest;
041:        import java.security.DigestInputStream;
042:        import java.security.NoSuchAlgorithmException;
043:        import java.security.KeyStoreException;
044:        import java.security.Key;
045:        import java.security.PrivateKey;
046:        import java.security.Signature;
047:
048:        import java.security.SignatureException;
049:        import java.security.InvalidKeyException;
050:        import java.security.NoSuchProviderException;
051:        import java.security.UnrecoverableKeyException;
052:
053:        import java.security.cert.Certificate;
054:        import java.security.cert.X509Certificate;
055:        import java.security.cert.CertificateFactory;
056:
057:        import java.security.cert.CertificateException;
058:        import java.security.cert.CertificateEncodingException;
059:        import java.security.cert.CertificateExpiredException;
060:        import java.security.cert.CertificateNotYetValidException;
061:
062:        import com.sun.midp.jadtool.AppDescriptorException;
063:
064:        import com.sun.midp.installer.*;
065:
066:        /**
067:         * Java API for signing MIDletSuites.
068:         * <p>
069:         * AppDescriptor is an extension of the Properties class which provides
070:         * additional methods for adding message digest and certificate 
071:         * properties as well as signing the app descriptor file and verifying
072:         * a signed app descriptor file.
073:         */
074:        public class AppDescriptor extends JadProperties {
075:
076:            /** Index of the key in arrays returned by getAllCerts. */
077:            public static int KEY = 0;
078:
079:            /** Index of the cert in arrays returned by getAllCerts. */
080:            public static int CERT = 1;
081:
082:            /** App Descriptor key for . */
083:            public static final String JAR_SIGNATURE = "MIDlet-Jar-RSA-SHA1";
084:            /** App Descriptor key for . */
085:            public static final String CP_ATTR = "MIDlet-Certificate-";
086:            /** App Descriptor key for . */
087:            public static final String JAR_URL = "MIDlet-Jar-URL";
088:            /** App Descriptor key for . */
089:            public static final String JAR_SIZE = "MIDlet-Jar-Size";
090:            /** App Descriptor key for . */
091:            public static final String SEP_ATTR = ": ";
092:
093:            /** SHA1 with RSA constant. */
094:            public static final String SIGN_ALG = "SHA1withRSA";
095:
096:            /** KeyStore to get certificates and keys from. */
097:            private KeyStore keystore = null;
098:
099:            /**
100:             * Default constructor
101:             */
102:            public AppDescriptor() {
103:                super ();
104:            }
105:
106:            /**
107:             * Used to input a stored app descriptor into an AppDescriptor
108:             * instance from a stream.  The input stream will be converted 
109:             * to Unicode using <code>encoding</code> if it is specified.
110:             * If <code>encoding</code> is not specified, a default 
111:             * encoding of type "UTF8" escapes will be used.
112:             *
113:             * Overrides <code>Properties.load</code>
114:             *
115:             * @param inputJad App descriptor input stream.
116:             * @param encoding Encoding of the inputJad stream.
117:             *
118:             * @exception IOException If an error occurs while loading the 
119:             *            inputJad stream.
120:             * @exception UnsupportedEncodingException If the given encoding
121:             *            type is not supported.
122:             * @exception InvalidJadException If the JAD has a format error
123:             */
124:            public synchronized void load(InputStream inputJad, String encoding)
125:                    throws UnsupportedEncodingException, IOException,
126:                    InvalidJadException {
127:                super .load(inputJad, encoding);
128:            }
129:
130:            /**
131:             * Used to store an app descriptor instance into a jad file 
132:             * through an output stream.  The internal Unicode stream 
133:             * will be converted to an output format using
134:             * <code>encoding</code> if it is specified.
135:             * If <code>encoding</code> is not specified, a default 
136:             * encoding of type Ascii with Unicode escapes will be used.
137:             *
138:             * Overrides <code>Properties.store</code>
139:             *
140:             * @param outputJad App descriptor output stream.
141:             * @param encoding Encoding of the outputJad stream.
142:             *
143:             * @exception IOException If an error occurs while writing the 
144:             *            inputJad stream.
145:             * @exception UnsupportedEncodingException If the given encoding
146:             *            type is not supported.
147:             */
148:            public synchronized void store(OutputStream outputJad,
149:                    String encoding) throws UnsupportedEncodingException,
150:                    IOException {
151:
152:                if (encoding != null) {
153:                    JadWriter.write(this , outputJad, encoding);
154:                } else {
155:                    JadWriter.write(this , outputJad);
156:                }
157:            }
158:
159:            /**
160:             * Provides a KeyStore instance for use by this AppDescriptor
161:             * object.  (The default KeyStore type from the Java security
162:             * properties file is used.  This should be type "JKS", and is
163:             * the only supported keystore format.)
164:             * <p>
165:             * This KeyStore is required by the <code>addcert</code>,
166:             * <code>sign</code>, <code>signcert</code>, and <code>verify</code> 
167:             * methods.  If any of these methods is called before 
168:             * <code>loadKeyStore</code> an exception will be thrown. 
169:             *
170:             * @param ksfile The input stream stream to load a KeyStore from.
171:             * @param storepass The password to unlock the KeyStore, can be null.
172:             * @exception KeyStoreException The default keystore provider type
173:             *            is not available in any of the provider packages 
174:             *            searched.  
175:             * @exception IOException Thrown if there is a problem parsing 
176:             *            the input stream or loading its data.
177:             * @exception CertificateException Thrown if there is trouble loading
178:             *            certificates into the KeyStore
179:             * @exception NoSuchAlgorithmException Thrown if the algorithm
180:             *            needed to verify the KeyStore cannot be found.
181:             */
182:            public synchronized void loadKeyStore(InputStream ksfile,
183:                    char[] storepass) throws KeyStoreException, IOException,
184:                    NoSuchAlgorithmException, CertificateException, Exception {
185:                try {
186:                    keystore = KeyStore.getInstance(KeyStore.getDefaultType());
187:                    keystore.load(ksfile, storepass);
188:                } catch (Exception e) {
189:                    throw new Exception("loadKeyStore failed");
190:                }
191:            }
192:
193:            /**
194:             * Store a the keystore in the descriptor in a file.
195:             *
196:             * @param ksfname file to use
197:             * @param storepass password of keystore
198:             */
199:            public synchronized void storeKeyStore(String ksfname,
200:                    char[] storepass) throws IOException, KeyStoreException,
201:                    NoSuchAlgorithmException, CertificateException {
202:
203:                FileOutputStream fout = new FileOutputStream(ksfname);
204:                keystore.store(fout, storepass);
205:                fout.close();
206:            }
207:
208:            /**
209:             * Adds a Base64 encoded signature of the jar file at the URL 
210:             * specified by the MIDlet-Jar-URL key in the app descriptor.
211:             * <code>load</code> and <code>loadKeyStore</code> must be
212:             * call before this method.
213:             * <p>
214:             * The line in the app descriptor corresponding to this
215:             * insertion will look like this:
216:             * <p>
217:             *   MIDlet-Jar-RSA-SHA1:j3zKCv6eud2Ubkw80XjpNb7tk5s...
218:             *
219:             * If a MIDlet-Jar-RSA-SHA1 property already exists it will
220:             * be replaced.
221:             *
222:             * @param alias  Alias of the signing key in the keystore.
223:             * @param keypass Password to access the signing (private) key.
224:             *
225:             * @exception AppDescriptorException JAR URL or content provider
226:             *            certificate was
227:             *            not found in the app descriptor.
228:             * @exception MalformedURLException The URL corresponding to 
229:             *            the MIDlet-Jar-URL key could not be parsed.
230:             * @exception IOException error reading the JAR
231:             * @exception NoSuchAlgorithmException If SHA1 or RSA need by
232:             *            getEncodedSig could not be found in an
233:             *            installed JCA provider.    
234:             * @exception KeyStoreException
235:             * @exception InvalidKeyException
236:             * @exception SignatureException
237:             * @exception UnrecoverableKeyException
238:             */
239:            public void addJarSignature(String alias, char[] keypass)
240:                    throws AppDescriptorException, MalformedURLException,
241:                    IOException, KeyStoreException, InvalidKeyException,
242:                    SignatureException, NoSuchAlgorithmException,
243:                    UnrecoverableKeyException {
244:
245:                String urlStr = getProperty(JAR_URL);
246:
247:                if (urlStr == null) {
248:                    throw new AppDescriptorException(JAR_URL
249:                            + " not in descriptor");
250:                }
251:
252:                URL url = new URL(urlStr);
253:                InputStream jarStream = url.openStream();
254:                addJarSignature(alias, keypass, jarStream);
255:            }
256:
257:            /**
258:             * Adds a Base64 encoded signature of the jar file provided in
259:             * an input stream to the app descriptor.
260:             * <p>
261:             * The line in the app descriptor corresponding to this
262:             * insertion will look like this:
263:             *
264:             *   MIDlet-Jar-RSA-SHA1:j3zKCv6eud2Ubkw80XjpNb7tk5s...
265:             *
266:             * If a MIDlet-Jar-RSA-SHA1 property already exists it will
267:             * be replaced.
268:             *
269:             * @param alias  Alias of the signing key in the keystore.
270:             * @param keypass Password to access the signing (private) key.
271:             * @param jarStream stream to read the jar file from
272:             *
273:             * @exception IOException If there is a problem reading the 
274:             *            input stream.
275:             * @exception NoSuchAlgorithmException If SHA1 or RSA need by
276:             *            getEncodedSig could not be found in an
277:             *            installed JCA provider.    
278:             * @exception KeyStoreException
279:             * @exception InvalidKeyException
280:             * @exception SignatureException
281:             * @exception UnrecoverableKeyException
282:             */
283:            public void addJarSignature(String alias, char[] keypass,
284:                    InputStream jarStream) throws IOException,
285:                    NoSuchAlgorithmException, KeyStoreException,
286:                    InvalidKeyException, SignatureException,
287:                    NoSuchAlgorithmException, UnrecoverableKeyException {
288:
289:                setProperty(JAR_SIGNATURE, getEncodedSig(alias, keypass,
290:                        jarStream));
291:            }
292:
293:            /**
294:             * Retrieves a certificate out of a KeyStore and adds it 
295:             * to the app descriptor as:
296:             * <p>
297:             *   content_provider.certificate-1-1:<Base64 encoded newcert>
298:             * <p>
299:             * Instance variable <code>keystore</code> must not be null, 
300:             * and should have been set by <code>loadKeyStore</code>
301:             * before this method is called.
302:             *
303:             * @param alias Alias of the chosen certificate in the keystore
304:             * @param chainNum number of the chain to add certificate to
305:             * @param certNum number of the certificate in the chain to replace it,
306:             *        or 0 to add the certificate at the end of the chain
307:             *
308:             * @exception KeyStoreException If there is an error with the keystore.
309:             * @exception CertificateException If there is a problem with the
310:             *            encoding of the certificate.
311:             * @exception AppDescriptorException If the KeyStore has not been 
312:             *            initialized (keystore is null)
313:             */
314:            public void addCert(String alias, int chainNum, int certNum)
315:                    throws CertificateException, KeyStoreException,
316:                    AppDescriptorException {
317:                Certificate[] chain = getCertificatesFromKeyStore(alias);
318:                if (certNum == 0) {
319:                    // find next number after the highest existing certificate number
320:                    for (certNum = 1; getProperty(CP_ATTR + chainNum + "-"
321:                            + certNum) != null; certNum++)
322:                        ;
323:
324:                    for (int i = 0; i < chain.length; i++) {
325:                        addEncodedCertificate(chain[i], chainNum, certNum + i);
326:                    }
327:                } else {
328:                    addEncodedCertificate(chain[certNum - 1], chainNum, certNum);
329:                }
330:            }
331:
332:            /**
333:             * Returns an X509Certificate object from the app descriptor property
334:             * chosen by <code>certnum</code>, or 
335:             * null if that certificate does not exist in the descriptor.
336:             * <p>
337:             * After finding the chosen property in the app descriptor, 
338:             * decodes it from Base64 into a byte-encoded certificate and then
339:             * creates the X509 format certificate from that opaque data.
340:             *
341:             * @param chainNum number of the certificate chain
342:             * @param certNum number of the certificate in the chain
343:             *
344:             * @return an X509Certificate object or null if the certificate is
345:             * not in the JAD
346:             *
347:             * @exception CertificateException If there is a format problem with
348:             *            the certificate
349:             */
350:            public X509Certificate getCert(int chainNum, int certNum)
351:                    throws CertificateException {
352:
353:                X509Certificate c = null;
354:
355:                String base64 = getProperty(CP_ATTR + chainNum + "-" + certNum);
356:                if (base64 != null) {
357:                    c = base64CertToX509Cert(base64);
358:                }
359:
360:                return c;
361:            }
362:
363:            /**
364:             * Returns an X509Certificate object from the app descriptor property
365:             * chosen by <code>certnum</code>, or 
366:             * null if that certificate does not exist in the descriptor.
367:             * <p>
368:             * After finding the chosen property in the app descriptor, 
369:             * decodes it from Base64 into a byte-encoded certificate and then
370:             * creates the X509 format certificate from that opaque data.
371:             *
372:             * @param chainNum number of the certificate chain
373:             * @param certNum number of the certificate in the chain
374:             *
375:             * @return an X509Certificate object or null if the certificate is
376:             * not in the JAD
377:             *
378:             * @exception CertificateException If there is a format problem with
379:             *            the certificate
380:             */
381:            public X509Certificate getCertAttribute(int chainNum, int certNum)
382:                    throws CertificateException {
383:
384:                X509Certificate c = null;
385:
386:                String base64 = getProperty(CP_ATTR + chainNum + "-" + certNum);
387:                if (base64 != null) {
388:                    c = base64CertToX509Cert(base64);
389:                }
390:
391:                return c;
392:            }
393:
394:            /**
395:             * Returns all X509Certificate objects from the app descriptor.
396:             * <p>
397:             * After finding a certificate property in the app descriptor, 
398:             * decodes it from Base64 into a byte-encoded certificate and then
399:             * creates the X509 format certificate from that opaque data.
400:             *
401:             * @return Vector of object arrays, each containing key, and a
402:             * X509Certificate object
403:             */
404:            public Vector getAllCerts() throws CertificateException {
405:                Vector certs = new Vector();
406:
407:                for (int idx = 0; idx < size(); idx++) {
408:                    String key = getKeyAt(idx);
409:                    String base64 = getValueAt(idx);
410:
411:                    if (key.startsWith(CP_ATTR)) {
412:                        X509Certificate c = base64CertToX509Cert(base64);
413:                        Object[] temp = new Object[2];
414:
415:                        temp[KEY] = key;
416:                        temp[CERT] = c;
417:                        certs.addElement(temp);
418:                    }
419:                }
420:
421:                return certs;
422:            }
423:
424:            /**
425:             * Returns a message digest of a certificate in "human readable" 
426:             * from from the app descriptor property
427:             * chosen by <code>certnum</code>, or 
428:             * null if that certificate does not exist in the descriptor.
429:             * <p>
430:             * After finding the chosen property in the app descriptor, 
431:             * decodes it from Base64 into a byte-encoded certificate and then
432:             * creates a readable digest String based on that data.
433:             *
434:             * @param chainNum number of the certificate chain
435:             * @param certNum number of the certificate in the chain
436:             * @param alg A Digest algorithm to use, e.g. "SHA1" or "MD5".
437:             *
438:             * @return A message digest of a certificate in hex as a String or
439:             *    null if the certificate is not in the JAD.
440:             *
441:             * @exception NoSuchAlgorithmException Thrown if the digest
442:             *            <code>algorithm</code> could not be found.
443:             */
444:            public String getCertDigest(int chainNum, int certNum, String alg)
445:                    throws NoSuchAlgorithmException {
446:
447:                String digest = null;
448:
449:                String base64 = getProperty(CP_ATTR + chainNum + "-" + certNum);
450:                if (base64 != null) {
451:                    byte[] certificateData = Base64.decode(base64);
452:                    digest = createFingerprint(certificateData, alg);
453:                }
454:
455:                return digest;
456:            }
457:
458:            /* ************ PRIVATE METHODS ************* */
459:
460:            /**
461:             * Retrieves a certificate chain out of a KeyStore.
462:             * Instance variable <code>keystore</code> must not be null,
463:             * and should have been set by <code>loadKeyStore</code>
464:             * before this method is called.
465:             *
466:             * @param alias Alias of the chosen certificate in the keystore
467:             * @return all certificates in the chain
468:             * @exception KeyStoreException If there is an error with the keystore.
469:             * @exception CertificateException If there is a problem with the
470:             *            encoding of the certificate.
471:             * @exception AppDescriptorException If the KeyStore has not been 
472:             *            initialized (keystore is null);
473:             */
474:            private Certificate[] getCertificatesFromKeyStore(String alias)
475:                    throws AppDescriptorException, CertificateException,
476:                    KeyStoreException {
477:
478:                if (keystore == null) {
479:                    throw new AppDescriptorException(
480:                            AppDescriptorException.KEYSTORE_NOT_INITIALIZED);
481:                }
482:
483:                // Return a certifcate chain if we can get it.
484:                Certificate[] chain = keystore.getCertificateChain(alias);
485:                if (chain == null) {
486:                    // Otherwise try for a certificate.
487:                    Certificate cert = keystore.getCertificate(alias);
488:                    if (cert == null) {
489:                        throw new CertificateException("Certificate not found");
490:                    }
491:                    chain = new Certificate[] { cert };
492:                }
493:
494:                return chain;
495:            }
496:
497:            /**
498:             * Add a certificate to the app descriptor as:
499:             * <p>
500:             *   content_provider.certificate-1-1:<Base64 encoded newcert>
501:             * <p>
502:             * Instance variable <code>keystore</code> must not be null, 
503:             * and should have been set by <code>loadKeyStore</code>
504:             * before this method is called.
505:             *
506:             * @param cert the certificate to add
507:             * @param chainNum number of the chain to add certificate to
508:             * @param certNum number of the certificate in the chain to replace it,
509:             *        or 0 to add the certificate at the end of the chain
510:             *
511:             * @exception CertificateEncodingException If there is a problem with the
512:             *            encoding of the certificate.
513:             */
514:            private void addEncodedCertificate(Certificate cert, int chainNum,
515:                    int certNum) throws CertificateEncodingException {
516:
517:                // encode the (x.509?) cert in base64
518:                byte[] certbytes = cert.getEncoded();
519:                String certtoadd = Base64.encode(certbytes);
520:                // replace any existing certificate
521:                setProperty(CP_ATTR + chainNum + "-" + certNum, certtoadd);
522:            }
523:
524:            /**
525:             * <code>getEncodedCertificate</code> - A helper function used
526:             * by <code>addCert</code>.
527:             *
528:             * Retrieves a certificate out of a KeyStore and returns it 
529:             * as a Base64 encoded String.  Instance variable <code>keystore</code>
530:             * must not be null, and should have been set by <code>loadKeyStore</code>
531:             * before this method is called.
532:             *
533:             * @param alias Alias of the chosen certificate in the keystore
534:             * @return Base64 encoded certificate as a String
535:             * @exception KeyStoreException If there is an error with the keystore.
536:             * @exception CertificateException If there is a problem with the
537:             *            encoding of the certificate.
538:             * @exception AppDescriptorException If the KeyStore has not been 
539:             *            initialized (keystore is null);
540:             */
541:            private String getEncodedCertificate(String alias)
542:                    throws KeyStoreException, CertificateException,
543:                    AppDescriptorException {
544:
545:                Certificate cert;
546:
547:                if (keystore == null) {
548:                    throw new AppDescriptorException(
549:                            AppDescriptorException.KEYSTORE_NOT_INITIALIZED);
550:                }
551:
552:                // Load a keystore data structure to get keys from      
553:                cert = keystore.getCertificate(alias);
554:                if (cert == null) {
555:                    throw new CertificateException("Certificate not found");
556:                }
557:
558:                byte[] certbytes = cert.getEncoded();
559:
560:                // return the (x.509?) encoded cert in base64
561:                return Base64.encode(certbytes);
562:            }
563:
564:            /**
565:             * <code>getNextCertIndex</code> - A helper function used by
566:             * <code>addcert</code>.
567:             *
568:             * Iterates through the current properties data returns the 
569:             * index of the first unused key index for either a content-provider
570:             * (cp) or https certificate. 
571:             *
572:             * @param key What cert key should be used...CP_ATTR or HTTPS_ATTR
573:             * @return The first unused index for a particular certificate type.
574:             */
575:            private int getNextCertIndex(String key) {
576:                int idx = 1;
577:
578:                while (idx > 0) {
579:                    String value = getProperty(key + idx);
580:                    if (value == null) {
581:                        break;
582:                    }
583:
584:                    idx++;
585:                }
586:
587:                return idx;
588:            }
589:
590:            /** 
591:             * <code>createFingerprint</code> - A helper function used by
592:             * <code>getdigest</code>.
593:             *
594:             * <code>createFingerprint</code>, given a certificated encoded 
595:             * as a byte array will compute a "fingerprint", or Message 
596:             * Digest of the certificate using the selected <code>algorithm</code>
597:             * type.
598:             *
599:             * A fingerprint is meant to be human readable, and is thus
600:             * returned as a hex string separated at byte boundaries by
601:             * a delimiter ":".
602:             *
603:             * @param certificateBytes - a certificate encoded as a byte array
604:             * @param algorithm - The name of a digest algorithm to use, 
605:             *                    e.g. "SHA1" or "MD5"
606:             * @return the fingerprint in String form.
607:             * @exception NoSuchAlgorithmException Thrown if the digest
608:             *            <code>algorithm</code> could not be found.
609:             */
610:            static String createFingerprint(byte[] certificateBytes,
611:                    String algorithm) throws NoSuchAlgorithmException {
612:                MessageDigest md = MessageDigest.getInstance(algorithm);
613:                md.update(certificateBytes);
614:                byte[] digest = md.digest();
615:                StringBuffer sb = new StringBuffer();
616:
617:                for (int i = 0; i < digest.length; i++) {
618:                    int b = digest[i] & 0xff;
619:                    String hex = Integer.toHexString(b);
620:
621:                    if (i != 0) {
622:                        sb.append(":");
623:                    }
624:
625:                    if (hex.length() == 1) {
626:                        sb.append("0");
627:                    }
628:
629:                    sb.append(hex);
630:                }
631:
632:                return sb.toString();
633:            }
634:
635:            /**
636:             * A helper function used by <code>sign</code>.
637:             * Produces a base64 encoded signature for the given buffer.
638:             *
639:             * @param alias  Alias of the signing key in the keystore.
640:             * @param keypass Password to access the signing (private) key.
641:             * @param stream stream to read the bytes from
642:             *
643:             * @return Base64 encoded signature of bits in the buffer
644:             *
645:             * @exception IOException If there is a problem reading the 
646:             *            input stream.
647:             * @exception KeyStoreException
648:             * @exception InvalidKeyException
649:             * @exception SignatureException
650:             * @exception NoSuchAlgorithmException
651:             * @exception UnrecoverableKeyException
652:             */
653:            private String getEncodedSig(String alias, char[] keypass,
654:                    InputStream stream) throws KeyStoreException,
655:                    InvalidKeyException, SignatureException,
656:                    NoSuchAlgorithmException, UnrecoverableKeyException,
657:                    IOException {
658:                int bytesRead;
659:                byte[] buffer = new byte[10240];
660:
661:                // get a signature object
662:                Signature signature = Signature.getInstance(SIGN_ALG);
663:
664:                // init the signature with a private key for signing
665:                Key pk = keystore.getKey(alias, keypass);
666:                signature.initSign((PrivateKey) pk);
667:
668:                for (;;) {
669:                    bytesRead = stream.read(buffer);
670:                    if (bytesRead == -1) {
671:                        break;
672:                    }
673:
674:                    signature.update(buffer, 0, bytesRead);
675:                }
676:
677:                // return the signature
678:                byte[] raw = signature.sign();
679:                return Base64.encode(raw);
680:            }
681:
682:            /**
683:             * <code>getVerifyCert</code> - A helper function used by
684:             * <code>verify</code>.
685:             *
686:             * Outputs an app descriptor file to the caller provided 
687:             * ByteArrayOutputStream <code>baos</code> and returns a
688:             * base64 encoded signature for those bits.  The signature
689:             * is valid only for exactly the returned bits.  If 
690:             * <code>encoding</code> is not specified, a default encoding
691:             * type of Ascii with Unicode escapes is used.
692:             *
693:             * @param alias  Alias of the verify key in the keystore. 
694:             * @return Verified X509Certificate containing the public key
695:             *         with which this app descriptor file's signature should
696:             *         be verified.
697:             * @exception AppDescriptorException
698:             * @exception NoSuchAlgorithmException
699:             * @exception KeyStoreException
700:             * @exception CertificateException
701:             * @exception UnrecoverableKeyException
702:             * @exception InvalidKeyException
703:             * @exception NoSuchProviderException
704:             * @exception SignatureException
705:             */
706:
707:            private X509Certificate getVerifyCert(String alias)
708:                    throws AppDescriptorException, NoSuchAlgorithmException,
709:                    KeyStoreException, CertificateException,
710:                    UnrecoverableKeyException, InvalidKeyException,
711:                    NoSuchProviderException, SignatureException {
712:                X509Certificate returncert = null;
713:                X509Certificate current = null;
714:                X509Certificate operatorXcert = null;
715:                Certificate operatorcert = null;
716:                byte[] operatordata;
717:                String operatordn = null;
718:                String currentdn = null;
719:                String rv = null;
720:
721:                // get the operator verification cert from the keystore
722:                operatorcert = keystore.getCertificate(alias);
723:
724:                // convert opaque operator cert into X509 encoding so we
725:                // can use it.
726:                operatordata = operatorcert.getEncoded();
727:                CertificateFactory cf = CertificateFactory.getInstance("X.509");
728:                ByteArrayInputStream bais = new ByteArrayInputStream(
729:                        operatordata);
730:                while (bais.available() > 0) {
731:                    operatorXcert = (X509Certificate) cf
732:                            .generateCertificate(bais);
733:                }
734:
735:                try {
736:                    bais.close();
737:                } catch (IOException ioe) {
738:                }
739:
740:                // Get the operator's distinguished name
741:                operatordn = (operatorXcert.getSubjectDN()).getName();
742:
743:                /*
744:                 * Now we search for a CP_ATTR type certificate 
745:                 * who's issuer DN matches "operatordn."
746:                 * It is the certificate that should verify the
747:                 * signature on this app descriptor.
748:                 *
749:                 * Before it can do that, it must be trusted by being
750:                 * verified by the "operator" certificate.
751:                 * The calls to verify() and checkValidity() do this.
752:                 */
753:                int count = 1;
754:                while ((current = getCert(1, count)) != null) {
755:                    currentdn = (current.getIssuerDN()).getName();
756:                    if (operatordn.equals(currentdn)) {
757:                        // verify cert sig with operator public key
758:                        current.verify(operatorcert.getPublicKey());
759:                        // check cert validity dates
760:                        current.checkValidity();
761:                        returncert = current;
762:                        break;
763:                    }
764:
765:                    count++;
766:                }
767:
768:                return returncert;
769:            }
770:
771:            /**
772:             * <code>base64CertToX509Cert</code> - A helper function used by
773:             * <code>verify</code>
774:             *
775:             * @param b64str A certificate encoded as Base64 String
776:             * @return An X509Certificate object.                              
777:             * @exception CertificateException Thrown if there is an error
778:             *            converting the <code>b64str</code> certificate
779:             *            into X509 format.
780:             */
781:            private X509Certificate base64CertToX509Cert(String b64str)
782:                    throws CertificateException {
783:                X509Certificate c = null;
784:
785:                byte[] certificateData = Base64.decode(b64str);
786:
787:                CertificateFactory cf = CertificateFactory.getInstance("X.509");
788:                ByteArrayInputStream bais = new ByteArrayInputStream(
789:                        certificateData);
790:
791:                while (bais.available() > 0) {
792:                    c = (X509Certificate) cf.generateCertificate(bais);
793:                }
794:
795:                try {
796:                    bais.close();
797:                } catch (IOException ioe) {
798:                }
799:
800:                return c;
801:            }
802:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.