Source Code Cross Referenced for DerValue.java in  » 6.0-JDK-Modules-sun » security » sun » security » util » 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 sun » security » sun.security.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004:         *
005:         * This code is free software; you can redistribute it and/or modify it
006:         * under the terms of the GNU General Public License version 2 only, as
007:         * published by the Free Software Foundation.  Sun designates this
008:         * particular file as subject to the "Classpath" exception as provided
009:         * by Sun in the LICENSE file that accompanied this code.
010:         *
011:         * This code is distributed in the hope that it will be useful, but WITHOUT
012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014:         * version 2 for more details (a copy is included in the LICENSE file that
015:         * accompanied this code).
016:         *
017:         * You should have received a copy of the GNU General Public License version
018:         * 2 along with this work; if not, write to the Free Software Foundation,
019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020:         *
021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022:         * CA 95054 USA or visit www.sun.com if you need additional information or
023:         * have any questions.
024:         */
025:
026:        package sun.security.util;
027:
028:        import java.io.*;
029:        import java.math.BigInteger;
030:        import java.util.Date;
031:
032:        /**
033:         * Represents a single DER-encoded value.  DER encoding rules are a subset
034:         * of the "Basic" Encoding Rules (BER), but they only support a single way
035:         * ("Definite" encoding) to encode any given value.
036:         *
037:         * <P>All DER-encoded data are triples <em>{type, length, data}</em>.  This
038:         * class represents such tagged values as they have been read (or constructed),
039:         * and provides structured access to the encoded data.
040:         *
041:         * <P>At this time, this class supports only a subset of the types of DER
042:         * data encodings which are defined.  That subset is sufficient for parsing
043:         * most X.509 certificates, and working with selected additional formats
044:         * (such as PKCS #10 certificate requests, and some kinds of PKCS #7 data).
045:         *
046:         * A note with respect to T61/Teletex strings: From RFC 1617, section 4.1.3
047:         * and RFC 3280, section 4.1.2.4., we assume that this kind of string will
048:         * contain ISO-8859-1 characters only.
049:         *
050:         * @version 1.76, 05/05/07
051:         *
052:         * @author David Brownell
053:         * @author Amit Kapoor
054:         * @author Hemma Prafullchandra
055:         */
056:        public class DerValue {
057:            /** The tag class types */
058:            public static final byte TAG_UNIVERSAL = (byte) 0x000;
059:            public static final byte TAG_APPLICATION = (byte) 0x040;
060:            public static final byte TAG_CONTEXT = (byte) 0x080;
061:            public static final byte TAG_PRIVATE = (byte) 0x0c0;
062:
063:            /** The DER tag of the value; one of the tag_ constants. */
064:            public byte tag;
065:
066:            protected DerInputBuffer buffer;
067:
068:            /**
069:             * The DER-encoded data of the value.
070:             */
071:            public final DerInputStream data;
072:
073:            private int length;
074:
075:            /*
076:             * The type starts at the first byte of the encoding, and
077:             * is one of these tag_* values.  That may be all the type
078:             * data that is needed.
079:             */
080:
081:            /*
082:             * These tags are the "universal" tags ... they mean the same
083:             * in all contexts.  (Mask with 0x1f -- five bits.)
084:             */
085:
086:            /** Tag value indicating an ASN.1 "BOOLEAN" value. */
087:            public final static byte tag_Boolean = 0x01;
088:
089:            /** Tag value indicating an ASN.1 "INTEGER" value. */
090:            public final static byte tag_Integer = 0x02;
091:
092:            /** Tag value indicating an ASN.1 "BIT STRING" value. */
093:            public final static byte tag_BitString = 0x03;
094:
095:            /** Tag value indicating an ASN.1 "OCTET STRING" value. */
096:            public final static byte tag_OctetString = 0x04;
097:
098:            /** Tag value indicating an ASN.1 "NULL" value. */
099:            public final static byte tag_Null = 0x05;
100:
101:            /** Tag value indicating an ASN.1 "OBJECT IDENTIFIER" value. */
102:            public final static byte tag_ObjectId = 0x06;
103:
104:            /** Tag value including an ASN.1 "ENUMERATED" value */
105:            public final static byte tag_Enumerated = 0x0A;
106:
107:            /** Tag value indicating an ASN.1 "UTF8String" value. */
108:            public final static byte tag_UTF8String = 0x0C;
109:
110:            /** Tag value including a "printable" string */
111:            public final static byte tag_PrintableString = 0x13;
112:
113:            /** Tag value including a "teletype" string */
114:            public final static byte tag_T61String = 0x14;
115:
116:            /** Tag value including an ASCII string */
117:            public final static byte tag_IA5String = 0x16;
118:
119:            /** Tag value indicating an ASN.1 "UTCTime" value. */
120:            public final static byte tag_UtcTime = 0x17;
121:
122:            /** Tag value indicating an ASN.1 "GeneralizedTime" value. */
123:            public final static byte tag_GeneralizedTime = 0x18;
124:
125:            /** Tag value indicating an ASN.1 "GenerallString" value. */
126:            public final static byte tag_GeneralString = 0x1B;
127:
128:            /** Tag value indicating an ASN.1 "UniversalString" value. */
129:            public final static byte tag_UniversalString = 0x1C;
130:
131:            /** Tag value indicating an ASN.1 "BMPString" value. */
132:            public final static byte tag_BMPString = 0x1E;
133:
134:            // CONSTRUCTED seq/set
135:
136:            /** 
137:             * Tag value indicating an ASN.1
138:             * "SEQUENCE" (zero to N elements, order is significant). 
139:             */
140:            public final static byte tag_Sequence = 0x30;
141:
142:            /**
143:             * Tag value indicating an ASN.1
144:             * "SEQUENCE OF" (one to N elements, order is significant).
145:             */
146:            public final static byte tag_SequenceOf = 0x30;
147:
148:            /** 
149:             * Tag value indicating an ASN.1
150:             * "SET" (zero to N members, order does not matter).
151:             */
152:            public final static byte tag_Set = 0x31;
153:
154:            /** 
155:             * Tag value indicating an ASN.1
156:             * "SET OF" (one to N members, order does not matter).
157:             */
158:            public final static byte tag_SetOf = 0x31;
159:
160:            /*
161:             * These values are the high order bits for the other kinds of tags.
162:             */
163:
164:            /**
165:             * Returns true if the tag class is UNIVERSAL.
166:             */
167:            public boolean isUniversal() {
168:                return ((tag & 0x0c0) == 0x000);
169:            }
170:
171:            /**
172:             * Returns true if the tag class is APPLICATION.
173:             */
174:            public boolean isApplication() {
175:                return ((tag & 0x0c0) == 0x040);
176:            }
177:
178:            /**
179:             * Returns true iff the CONTEXT SPECIFIC bit is set in the type tag.
180:             * This is associated with the ASN.1 "DEFINED BY" syntax.
181:             */
182:            public boolean isContextSpecific() {
183:                return ((tag & 0x0c0) == 0x080);
184:            }
185:
186:            /**
187:             * Returns true iff the CONTEXT SPECIFIC TAG matches the passed tag.
188:             */
189:            public boolean isContextSpecific(byte cntxtTag) {
190:                if (!isContextSpecific()) {
191:                    return false;
192:                }
193:                return ((tag & 0x01f) == cntxtTag);
194:            }
195:
196:            boolean isPrivate() {
197:                return ((tag & 0x0c0) == 0x0c0);
198:            }
199:
200:            /** Returns true iff the CONSTRUCTED bit is set in the type tag. */
201:            public boolean isConstructed() {
202:                return ((tag & 0x020) == 0x020);
203:            }
204:
205:            /**
206:             * Returns true iff the CONSTRUCTED TAG matches the passed tag.
207:             */
208:            public boolean isConstructed(byte constructedTag) {
209:                if (!isConstructed()) {
210:                    return false;
211:                }
212:                return ((tag & 0x01f) == constructedTag);
213:            }
214:
215:            /**
216:             * Creates a PrintableString or UTF8string DER value from a string
217:             */
218:            public DerValue(String value) throws IOException {
219:                boolean isPrintableString = true;
220:                for (int i = 0; i < value.length(); i++) {
221:                    if (!isPrintableStringChar(value.charAt(i))) {
222:                        isPrintableString = false;
223:                        break;
224:                    }
225:                }
226:
227:                data = init(isPrintableString ? tag_PrintableString
228:                        : tag_UTF8String, value);
229:            }
230:
231:            /**
232:             * Creates a string type DER value from a String object
233:             * @param stringTag the tag for the DER value to create
234:             * @param value the String object to use for the DER value
235:             */
236:            public DerValue(byte stringTag, String value) throws IOException {
237:                data = init(stringTag, value);
238:            }
239:
240:            /**
241:             * Creates a DerValue from a tag and some DER-encoded data.
242:             *
243:             * @param tag the DER type tag
244:             * @param data the DER-encoded data
245:             */
246:            public DerValue(byte tag, byte[] data) {
247:                this .tag = tag;
248:                buffer = new DerInputBuffer(data.clone());
249:                length = data.length;
250:                this .data = new DerInputStream(buffer);
251:                this .data.mark(Integer.MAX_VALUE);
252:            }
253:
254:            /*
255:             * package private
256:             */
257:            DerValue(DerInputBuffer in) throws IOException {
258:                // XXX must also parse BER-encoded constructed
259:                // values such as sequences, sets...
260:
261:                tag = (byte) in.read();
262:                byte lenByte = (byte) in.read();
263:                length = DerInputStream.getLength((lenByte & 0xff), in);
264:                if (length == -1) { // indefinite length encoding found
265:                    DerInputBuffer inbuf = in.dup();
266:                    int readLen = inbuf.available();
267:                    int offset = 2; // for tag and length bytes
268:                    byte[] indefData = new byte[readLen + offset];
269:                    indefData[0] = tag;
270:                    indefData[1] = lenByte;
271:                    DataInputStream dis = new DataInputStream(inbuf);
272:                    dis.readFully(indefData, offset, readLen);
273:                    dis.close();
274:                    DerIndefLenConverter derIn = new DerIndefLenConverter();
275:                    inbuf = new DerInputBuffer(derIn.convert(indefData));
276:                    if (tag != inbuf.read())
277:                        throw new IOException(
278:                                "Indefinite length encoding not supported");
279:                    length = DerInputStream.getLength(inbuf);
280:                    buffer = inbuf.dup();
281:                    buffer.truncate(length);
282:                    data = new DerInputStream(buffer);
283:                    // indefinite form is encoded by sending a length field with a 
284:                    // length of 0. - i.e. [1000|0000].  
285:                    // the object is ended by sending two zero bytes.
286:                    in.skip(length + offset);
287:                } else {
288:
289:                    buffer = in.dup();
290:                    buffer.truncate(length);
291:                    data = new DerInputStream(buffer);
292:
293:                    in.skip(length);
294:                }
295:            }
296:
297:            /**
298:             * Get an ASN.1/DER encoded datum from a buffer.  The
299:             * entire buffer must hold exactly one datum, including
300:             * its tag and length.
301:             *
302:             * @param buf buffer holding a single DER-encoded datum.
303:             */
304:            public DerValue(byte[] buf) throws IOException {
305:                data = init(true, new ByteArrayInputStream(buf));
306:            }
307:
308:            /**
309:             * Get an ASN.1/DER encoded datum from part of a buffer.
310:             * That part of the buffer must hold exactly one datum, including
311:             * its tag and length.
312:             *
313:             * @param buf the buffer
314:             * @param offset start point of the single DER-encoded dataum
315:             * @param length how many bytes are in the encoded datum
316:             */
317:            public DerValue(byte[] buf, int offset, int len) throws IOException {
318:                data = init(true, new ByteArrayInputStream(buf, offset, len));
319:            }
320:
321:            /**
322:             * Get an ASN1/DER encoded datum from an input stream.  The
323:             * stream may have additional data following the encoded datum.
324:             * In case of indefinite length encoded datum, the input stream
325:             * must hold only one datum.
326:             *
327:             * @param in the input stream holding a single DER datum,
328:             *	which may be followed by additional data
329:             */
330:            public DerValue(InputStream in) throws IOException {
331:                data = init(false, in);
332:            }
333:
334:            private DerInputStream init(byte stringTag, String value)
335:                    throws IOException {
336:                String enc = null;
337:
338:                tag = stringTag;
339:
340:                switch (stringTag) {
341:                case tag_PrintableString:
342:                case tag_IA5String:
343:                case tag_GeneralString:
344:                    enc = "ASCII";
345:                    break;
346:                case tag_T61String:
347:                    enc = "ISO-8859-1";
348:                    break;
349:                case tag_BMPString:
350:                    enc = "UnicodeBigUnmarked";
351:                    break;
352:                case tag_UTF8String:
353:                    enc = "UTF8";
354:                    break;
355:                // TBD: Need encoder for UniversalString before it can
356:                // be handled.
357:                default:
358:                    throw new IllegalArgumentException(
359:                            "Unsupported DER string type");
360:                }
361:
362:                byte[] buf = value.getBytes(enc);
363:                length = buf.length;
364:                buffer = new DerInputBuffer(buf);
365:                DerInputStream result = new DerInputStream(buffer);
366:                result.mark(Integer.MAX_VALUE);
367:                return result;
368:            }
369:
370:            /*
371:             * helper routine
372:             */
373:            private DerInputStream init(boolean fullyBuffered, InputStream in)
374:                    throws IOException {
375:
376:                tag = (byte) in.read();
377:                byte lenByte = (byte) in.read();
378:                length = DerInputStream.getLength((lenByte & 0xff), in);
379:                if (length == -1) { // indefinite length encoding found
380:                    int readLen = in.available();
381:                    int offset = 2; // for tag and length bytes
382:                    byte[] indefData = new byte[readLen + offset];
383:                    indefData[0] = tag;
384:                    indefData[1] = lenByte;
385:                    DataInputStream dis = new DataInputStream(in);
386:                    dis.readFully(indefData, offset, readLen);
387:                    dis.close();
388:                    DerIndefLenConverter derIn = new DerIndefLenConverter();
389:                    in = new ByteArrayInputStream(derIn.convert(indefData));
390:                    if (tag != in.read())
391:                        throw new IOException(
392:                                "Indefinite length encoding not supported");
393:                    length = DerInputStream.getLength(in);
394:                }
395:                if (length == 0)
396:                    return null;
397:
398:                if (fullyBuffered && in.available() != length)
399:                    throw new IOException(
400:                            "extra data given to DerValue constructor");
401:
402:                byte[] bytes = new byte[length];
403:
404:                // n.b. readFully not needed in normal fullyBuffered case
405:                DataInputStream dis = new DataInputStream(in);
406:
407:                dis.readFully(bytes);
408:                buffer = new DerInputBuffer(bytes);
409:                return new DerInputStream(buffer);
410:            }
411:
412:            /**
413:             * Encode an ASN1/DER encoded datum onto a DER output stream.
414:             */
415:            public void encode(DerOutputStream out) throws IOException {
416:                out.write(tag);
417:                out.putLength(length);
418:                // XXX yeech, excess copies ... DerInputBuffer.write(OutStream)
419:                if (length > 0) {
420:                    byte[] value = new byte[length];
421:                    // always synchronized on data
422:                    synchronized (data) {
423:                        buffer.reset();
424:                        if (buffer.read(value) != length) {
425:                            throw new IOException(
426:                                    "short DER value read (encode)");
427:                        }
428:                        out.write(value);
429:                    }
430:                }
431:            }
432:
433:            public final DerInputStream getData() {
434:                return data;
435:            }
436:
437:            public final byte getTag() {
438:                return tag;
439:            }
440:
441:            /**
442:             * Returns an ASN.1 BOOLEAN
443:             *
444:             * @return the boolean held in this DER value
445:             */
446:            public boolean getBoolean() throws IOException {
447:                if (tag != tag_Boolean) {
448:                    throw new IOException("DerValue.getBoolean, not a BOOLEAN "
449:                            + tag);
450:                }
451:                if (length != 1) {
452:                    throw new IOException(
453:                            "DerValue.getBoolean, invalid length " + length);
454:                }
455:                if (buffer.read() != 0) {
456:                    return true;
457:                }
458:                return false;
459:            }
460:
461:            /**
462:             * Returns an ASN.1 OBJECT IDENTIFIER.
463:             *
464:             * @return the OID held in this DER value
465:             */
466:            public ObjectIdentifier getOID() throws IOException {
467:                if (tag != tag_ObjectId)
468:                    throw new IOException("DerValue.getOID, not an OID " + tag);
469:                return new ObjectIdentifier(buffer);
470:            }
471:
472:            private byte[] append(byte[] a, byte[] b) {
473:                if (a == null)
474:                    return b;
475:
476:                byte[] ret = new byte[a.length + b.length];
477:                System.arraycopy(a, 0, ret, 0, a.length);
478:                System.arraycopy(b, 0, ret, a.length, b.length);
479:
480:                return ret;
481:            }
482:
483:            /**
484:             * Returns an ASN.1 OCTET STRING
485:             *
486:             * @return the octet string held in this DER value
487:             */
488:            public byte[] getOctetString() throws IOException {
489:                byte[] bytes;
490:
491:                if (tag != tag_OctetString && !isConstructed(tag_OctetString)) {
492:                    throw new IOException(
493:                            "DerValue.getOctetString, not an Octet String: "
494:                                    + tag);
495:                }
496:                bytes = new byte[length];
497:                if (buffer.read(bytes) != length)
498:                    throw new IOException("short read on DerValue buffer");
499:                if (isConstructed()) {
500:                    DerInputStream in = new DerInputStream(bytes);
501:                    bytes = null;
502:                    while (in.available() != 0) {
503:                        bytes = append(bytes, in.getOctetString());
504:                    }
505:                }
506:                return bytes;
507:            }
508:
509:            /**
510:             * Returns an ASN.1 INTEGER value as an integer. 
511:             *
512:             * @return the integer held in this DER value.
513:             */
514:            public int getInteger() throws IOException {
515:                if (tag != tag_Integer) {
516:                    throw new IOException("DerValue.getInteger, not an int "
517:                            + tag);
518:                }
519:                return buffer.getInteger(data.available());
520:            }
521:
522:            /**
523:             * Returns an ASN.1 INTEGER value as a BigInteger.
524:             *
525:             * @return the integer held in this DER value as a BigInteger.
526:             */
527:            public BigInteger getBigInteger() throws IOException {
528:                if (tag != tag_Integer)
529:                    throw new IOException("DerValue.getBigInteger, not an int "
530:                            + tag);
531:                return buffer.getBigInteger(data.available(), false);
532:            }
533:
534:            /**
535:             * Returns an ASN.1 INTEGER value as a positive BigInteger.
536:             * This is just to deal with implementations that incorrectly encode
537:             * some values as negative.
538:             *
539:             * @return the integer held in this DER value as a BigInteger.
540:             */
541:            public BigInteger getPositiveBigInteger() throws IOException {
542:                if (tag != tag_Integer)
543:                    throw new IOException("DerValue.getBigInteger, not an int "
544:                            + tag);
545:                return buffer.getBigInteger(data.available(), true);
546:            }
547:
548:            /**
549:             * Returns an ASN.1 ENUMERATED value.
550:             *
551:             * @return the integer held in this DER value.
552:             */
553:            public int getEnumerated() throws IOException {
554:                if (tag != tag_Enumerated) {
555:                    throw new IOException(
556:                            "DerValue.getEnumerated, incorrect tag: " + tag);
557:                }
558:                return buffer.getInteger(data.available());
559:            }
560:
561:            /**
562:             * Returns an ASN.1 BIT STRING value.  The bit string must be byte-aligned.
563:             *
564:             * @return the bit string held in this value
565:             */
566:            public byte[] getBitString() throws IOException {
567:                if (tag != tag_BitString)
568:                    throw new IOException(
569:                            "DerValue.getBitString, not a bit string " + tag);
570:
571:                return buffer.getBitString();
572:            }
573:
574:            /**
575:             * Returns an ASN.1 BIT STRING value that need not be byte-aligned.
576:             *
577:             * @return a BitArray representing the bit string held in this value
578:             */
579:            public BitArray getUnalignedBitString() throws IOException {
580:                if (tag != tag_BitString)
581:                    throw new IOException(
582:                            "DerValue.getBitString, not a bit string " + tag);
583:
584:                return buffer.getUnalignedBitString();
585:            }
586:
587:            /**
588:             * Returns the name component as a Java string, regardless of its
589:             * encoding restrictions (ASCII, T61, Printable, IA5, BMP, UTF8).
590:             */
591:            // TBD: Need encoder for UniversalString before it can be handled.
592:            public String getAsString() throws IOException {
593:                if (tag == tag_UTF8String)
594:                    return getUTF8String();
595:                else if (tag == tag_PrintableString)
596:                    return getPrintableString();
597:                else if (tag == tag_T61String)
598:                    return getT61String();
599:                else if (tag == tag_IA5String)
600:                    return getIA5String();
601:                /*
602:                  else if (tag == tag_UniversalString)
603:                  return getUniversalString();
604:                 */
605:                else if (tag == tag_BMPString)
606:                    return getBMPString();
607:                else if (tag == tag_GeneralString)
608:                    return getGeneralString();
609:                else
610:                    return null;
611:            }
612:
613:            /**
614:             * Returns an ASN.1 BIT STRING value, with the tag assumed implicit
615:             * based on the parameter.  The bit string must be byte-aligned.
616:             *
617:             * @params tagImplicit if true, the tag is assumed implicit.
618:             * @return the bit string held in this value
619:             */
620:            public byte[] getBitString(boolean tagImplicit) throws IOException {
621:                if (!tagImplicit) {
622:                    if (tag != tag_BitString)
623:                        throw new IOException(
624:                                "DerValue.getBitString, not a bit string "
625:                                        + tag);
626:                }
627:                return buffer.getBitString();
628:            }
629:
630:            /**
631:             * Returns an ASN.1 BIT STRING value, with the tag assumed implicit
632:             * based on the parameter.  The bit string need not be byte-aligned.
633:             *
634:             * @params tagImplicit if true, the tag is assumed implicit.
635:             * @return the bit string held in this value
636:             */
637:            public BitArray getUnalignedBitString(boolean tagImplicit)
638:                    throws IOException {
639:                if (!tagImplicit) {
640:                    if (tag != tag_BitString)
641:                        throw new IOException(
642:                                "DerValue.getBitString, not a bit string "
643:                                        + tag);
644:                }
645:                return buffer.getUnalignedBitString();
646:            }
647:
648:            /**
649:             * Helper routine to return all the bytes contained in the
650:             * DerInputStream associated with this object.
651:             */
652:            public byte[] getDataBytes() throws IOException {
653:                byte[] retVal = new byte[length];
654:                synchronized (data) {
655:                    data.reset();
656:                    data.getBytes(retVal);
657:                }
658:                return retVal;
659:            }
660:
661:            /**
662:             * Returns an ASN.1 STRING value
663:             *
664:             * @return the printable string held in this value
665:             */
666:            public String getPrintableString() throws IOException {
667:                if (tag != tag_PrintableString)
668:                    throw new IOException(
669:                            "DerValue.getPrintableString, not a string " + tag);
670:
671:                return new String(getDataBytes(), "ASCII");
672:            }
673:
674:            /**
675:             * Returns an ASN.1 T61 (Teletype) STRING value
676:             *
677:             * @return the teletype string held in this value
678:             */
679:            public String getT61String() throws IOException {
680:                if (tag != tag_T61String)
681:                    throw new IOException("DerValue.getT61String, not T61 "
682:                            + tag);
683:
684:                return new String(getDataBytes(), "ISO-8859-1");
685:            }
686:
687:            /**
688:             * Returns an ASN.1 IA5 (ASCII) STRING value
689:             *
690:             * @return the ASCII string held in this value
691:             */
692:            public String getIA5String() throws IOException {
693:                if (tag != tag_IA5String)
694:                    throw new IOException("DerValue.getIA5String, not IA5 "
695:                            + tag);
696:
697:                return new String(getDataBytes(), "ASCII");
698:            }
699:
700:            /**
701:             * Returns the ASN.1 BMP (Unicode) STRING value as a Java string.
702:             *
703:             * @return a string corresponding to the encoded BMPString held in 
704:             * this value
705:             */
706:            public String getBMPString() throws IOException {
707:                if (tag != tag_BMPString)
708:                    throw new IOException("DerValue.getBMPString, not BMP "
709:                            + tag);
710:
711:                // BMPString is the same as Unicode in big endian, unmarked
712:                // format.
713:                return new String(getDataBytes(), "UnicodeBigUnmarked");
714:            }
715:
716:            /**
717:             * Returns the ASN.1 UTF-8 STRING value as a Java String.
718:             *
719:             * @return a string corresponding to the encoded UTF8String held in 
720:             * this value
721:             */
722:            public String getUTF8String() throws IOException {
723:                if (tag != tag_UTF8String)
724:                    throw new IOException("DerValue.getUTF8String, not UTF-8 "
725:                            + tag);
726:
727:                return new String(getDataBytes(), "UTF8");
728:            }
729:
730:            /**
731:             * Returns the ASN.1 GENERAL STRING value as a Java String.
732:             *
733:             * @return a string corresponding to the encoded GeneralString held in 
734:             * this value
735:             */
736:            public String getGeneralString() throws IOException {
737:                if (tag != tag_GeneralString)
738:                    throw new IOException(
739:                            "DerValue.getGeneralString, not GeneralString "
740:                                    + tag);
741:
742:                return new String(getDataBytes(), "ASCII");
743:            }
744:
745:            /**
746:             * Returns a Date if the DerValue is UtcTime.
747:             *
748:             * @return the Date held in this DER value
749:             */
750:            public Date getUTCTime() throws IOException {
751:                if (tag != tag_UtcTime) {
752:                    throw new IOException(
753:                            "DerValue.getUTCTime, not a UtcTime: " + tag);
754:                }
755:                return buffer.getUTCTime(data.available());
756:            }
757:
758:            /**
759:             * Returns a Date if the DerValue is GeneralizedTime.
760:             *
761:             * @return the Date held in this DER value
762:             */
763:            public Date getGeneralizedTime() throws IOException {
764:                if (tag != tag_GeneralizedTime) {
765:                    throw new IOException(
766:                            "DerValue.getGeneralizedTime, not a GeneralizedTime: "
767:                                    + tag);
768:                }
769:                return buffer.getGeneralizedTime(data.available());
770:            }
771:
772:            /**
773:             * Returns true iff the other object is a DER value which
774:             * is bitwise equal to this one.
775:             *
776:             * @param other the object being compared with this one
777:             */
778:            public boolean equals(Object other) {
779:                if (other instanceof  DerValue)
780:                    return equals((DerValue) other);
781:                else
782:                    return false;
783:            }
784:
785:            /**
786:             * Bitwise equality comparison.  DER encoded values have a single
787:             * encoding, so that bitwise equality of the encoded values is an
788:             * efficient way to establish equivalence of the unencoded values.
789:             *
790:             * @param other the object being compared with this one
791:             */
792:            public boolean equals(DerValue other) {
793:                if (this  == other) {
794:                    return true;
795:                }
796:                if (tag != other.tag) {
797:                    return false;
798:                }
799:                if (data == other.data) {
800:                    return true;
801:                }
802:
803:                // make sure the order of lock is always consistent to avoid a deadlock
804:                return (System.identityHashCode(this .data) > System
805:                        .identityHashCode(other.data)) ? doEquals(this , other)
806:                        : doEquals(other, this );
807:            }
808:
809:            /**
810:             * Helper for public method equals()
811:             */
812:            private static boolean doEquals(DerValue d1, DerValue d2) {
813:                synchronized (d1.data) {
814:                    synchronized (d2.data) {
815:                        d1.data.reset();
816:                        d2.data.reset();
817:                        return d1.buffer.equals(d2.buffer);
818:                    }
819:                }
820:            }
821:
822:            /**
823:             * Returns a printable representation of the value.
824:             *
825:             * @return printable representation of the value
826:             */
827:            public String toString() {
828:                try {
829:
830:                    String str = getAsString();
831:                    if (str != null)
832:                        return "\"" + str + "\"";
833:                    if (tag == tag_Null)
834:                        return "[DerValue, null]";
835:                    if (tag == tag_ObjectId)
836:                        return "OID." + getOID();
837:
838:                    // integers
839:                    else
840:                        return "[DerValue, tag = " + tag + ", length = "
841:                                + length + "]";
842:                } catch (IOException e) {
843:                    throw new IllegalArgumentException("misformatted DER value");
844:                }
845:            }
846:
847:            /**
848:             * Returns a DER-encoded value, such that if it's passed to the
849:             * DerValue constructor, a value equivalent to "this" is returned.
850:             *
851:             * @return DER-encoded value, including tag and length.
852:             */
853:            public byte[] toByteArray() throws IOException {
854:                DerOutputStream out = new DerOutputStream();
855:
856:                encode(out);
857:                data.reset();
858:                return out.toByteArray();
859:            }
860:
861:            /**
862:             * For "set" and "sequence" types, this function may be used
863:             * to return a DER stream of the members of the set or sequence.
864:             * This operation is not supported for primitive types such as
865:             * integers or bit strings.
866:             */
867:            public DerInputStream toDerInputStream() throws IOException {
868:                if (tag == tag_Sequence || tag == tag_Set)
869:                    return new DerInputStream(buffer);
870:                throw new IOException("toDerInputStream rejects tag type "
871:                        + tag);
872:            }
873:
874:            /**
875:             * Get the length of the encoded value.
876:             */
877:            public int length() {
878:                return length;
879:            }
880:
881:            /**
882:             * Determine if a character is one of the permissible characters for
883:             * PrintableString:
884:             * A-Z, a-z, 0-9, space, apostrophe (39), left and right parentheses,
885:             * plus sign, comma, hyphen, period, slash, colon, equals sign,
886:             * and question mark.
887:             *
888:             * Characters that are *not* allowed in PrintableString include
889:             * exclamation point, quotation mark, number sign, dollar sign,
890:             * percent sign, ampersand, asterisk, semicolon, less than sign,
891:             * greater than sign, at sign, left and right square brackets,
892:             * backslash, circumflex (94), underscore, back quote (96),
893:             * left and right curly brackets, vertical line, tilde,
894:             * and the control codes (0-31 and 127).
895:             *
896:             * This list is based on X.680 (the ASN.1 spec).
897:             */
898:            public static boolean isPrintableStringChar(char ch) {
899:                if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
900:                        || (ch >= '0' && ch <= '9')) {
901:                    return true;
902:                } else {
903:                    switch (ch) {
904:                    case ' ': /* space */
905:                    case '\'': /* apostrophe */
906:                    case '(': /* left paren */
907:                    case ')': /* right paren */
908:                    case '+': /* plus */
909:                    case ',': /* comma */
910:                    case '-': /* hyphen */
911:                    case '.': /* period */
912:                    case '/': /* slash */
913:                    case ':': /* colon */
914:                    case '=': /* equals */
915:                    case '?': /* question mark */
916:                        return true;
917:                    default:
918:                        return false;
919:                    }
920:                }
921:            }
922:
923:            /**
924:             * Create the tag of the attribute.
925:             *
926:             * @params class the tag class type, one of UNIVERSAL, CONTEXT,
927:             *               APPLICATION or PRIVATE
928:             * @params form if true, the value is constructed, otherwise it
929:             * is primitive.
930:             * @params val the tag value
931:             */
932:            public static byte createTag(byte tagClass, boolean form, byte val) {
933:                byte tag = (byte) (tagClass | val);
934:                if (form) {
935:                    tag |= (byte) 0x20;
936:                }
937:                return (tag);
938:            }
939:
940:            /**
941:             * Set the tag of the attribute. Commonly used to reset the
942:             * tag value used for IMPLICIT encodings.
943:             *
944:             * @params tag the tag value
945:             */
946:            public void resetTag(byte tag) {
947:                this .tag = tag;
948:            }
949:
950:            /**
951:             * Returns a hashcode for this DerValue.
952:             *
953:             * @return a hashcode for this DerValue.
954:             */
955:            public int hashCode() {
956:                return toString().hashCode();
957:            }
958:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.