1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.asn1.util;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport java.io.IOException;
4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Enumeration;
5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
64c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Encodable;
74c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Integer;
84c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1ObjectIdentifier;
9c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.ASN1OctetString;
104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Primitive;
11c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.ASN1Sequence;
12c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.ASN1Set;
13e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstromimport org.bouncycastle.asn1.ASN1TaggedObject;
14c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.BERApplicationSpecific;
15c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.BERConstructedOctetString;
16e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstromimport org.bouncycastle.asn1.BEROctetString;
17c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.BERSequence;
18c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.BERSet;
19c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.BERTaggedObject;
204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.BERTags;
21c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERApplicationSpecific;
22c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERBMPString;
23c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERBitString;
24c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERBoolean;
25c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DEREnumerated;
26c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERExternal;
27c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERGeneralizedTime;
28c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERIA5String;
29c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERNull;
30c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERPrintableString;
31c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERSequence;
32c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERT61String;
33c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERUTCTime;
34c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERUTF8String;
35c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERVisibleString;
36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.util.encoders.Hex;
37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class ASN1Dump
39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
40c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static final String  TAB = "    ";
41c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static final int SAMPLE_SIZE = 32;
42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * dump a DER object as a formatted string with indentation
45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     * @param obj the ASN1Primitive to be dumped out.
47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
48c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    static void _dumpAsString(
49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String      indent,
50c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        boolean     verbose,
514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1Primitive obj,
52c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        StringBuffer    buf)
53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
54c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        String nl = System.getProperty("line.separator");
55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (obj instanceof ASN1Sequence)
56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            Enumeration     e = ((ASN1Sequence)obj).getObjects();
58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            String          tab = indent + TAB;
59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            buf.append(indent);
616e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if (obj instanceof BERSequence)
62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                buf.append("BER Sequence");
64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else if (obj instanceof DERSequence)
66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                buf.append("DER Sequence");
68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                buf.append("Sequence");
72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
74c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(nl);
75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            while (e.hasMoreElements())
77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                Object  o = e.nextElement();
79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
80c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                if (o == null || o.equals(DERNull.INSTANCE))
81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    buf.append(tab);
83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    buf.append("NULL");
84c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    buf.append(nl);
85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                else if (o instanceof ASN1Primitive)
87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    _dumpAsString(tab, verbose, (ASN1Primitive)o, buf);
89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                else
91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    _dumpAsString(tab, verbose, ((ASN1Encodable)o).toASN1Primitive(), buf);
93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
96e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        else if (obj instanceof ASN1TaggedObject)
97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            String          tab = indent + TAB;
99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            buf.append(indent);
101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (obj instanceof BERTaggedObject)
102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                buf.append("BER Tagged [");
104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                buf.append("Tagged [");
108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
110e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            ASN1TaggedObject o = (ASN1TaggedObject)obj;
111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            buf.append(Integer.toString(o.getTagNo()));
113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            buf.append(']');
114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (!o.isExplicit())
116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                buf.append(" IMPLICIT ");
118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
120c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(nl);
121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (o.isEmpty())
123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                buf.append(tab);
125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                buf.append("EMPTY");
126c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(nl);
127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
130c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                _dumpAsString(tab, verbose, o.getObject(), buf);
131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
133e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        else if (obj instanceof ASN1Set)
134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            Enumeration     e = ((ASN1Set)obj).getObjects();
136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            String          tab = indent + TAB;
137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            buf.append(indent);
139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
140e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            if (obj instanceof BERSet)
141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
142e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                buf.append("BER Set");
143e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            }
144e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            else
145e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            {
146e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                buf.append("DER Set");
147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
149c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(nl);
150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            while (e.hasMoreElements())
152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                Object  o = e.nextElement();
154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (o == null)
156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    buf.append(tab);
158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    buf.append("NULL");
159c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    buf.append(nl);
160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                else if (o instanceof ASN1Primitive)
162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    _dumpAsString(tab, verbose, (ASN1Primitive)o, buf);
164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                else
166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    _dumpAsString(tab, verbose, ((ASN1Encodable)o).toASN1Primitive(), buf);
168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
171e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        else if (obj instanceof ASN1OctetString)
172b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
173c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            ASN1OctetString oct = (ASN1OctetString)obj;
174e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
175e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            if (obj instanceof BEROctetString || obj instanceof  BERConstructedOctetString)
176c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
177e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                buf.append(indent + "BER Constructed Octet String" + "[" + oct.getOctets().length + "] ");
178c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
179e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            else
180e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            {
181e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                buf.append(indent + "DER Octet String" + "[" + oct.getOctets().length + "] ");
182c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
183c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (verbose)
184c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
185c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(dumpBinaryDataAsString(indent, oct.getOctets()));
186c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
187a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            else
188a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
189c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(nl);
190c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
191b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
192e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        else if (obj instanceof ASN1ObjectIdentifier)
193e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
194e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            buf.append(indent + "ObjectIdentifier(" + ((ASN1ObjectIdentifier)obj).getId() + ")" + nl);
195e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        }
196e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        else if (obj instanceof DERBoolean)
197e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
198e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            buf.append(indent + "Boolean(" + ((DERBoolean)obj).isTrue() + ")" + nl);
199e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        }
200e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        else if (obj instanceof ASN1Integer)
201e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
202e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            buf.append(indent + "Integer(" + ((ASN1Integer)obj).getValue() + ")" + nl);
203e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        }
204b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else if (obj instanceof DERBitString)
205b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
206c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            DERBitString bt = (DERBitString)obj;
207c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(indent + "DER Bit String" + "[" + bt.getBytes().length + ", " + bt.getPadBits() + "] ");
208c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (verbose)
209c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
210c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(dumpBinaryDataAsString(indent, bt.getBytes()));
211c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
212a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            else
213a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
214c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(nl);
215c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
216b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
217b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else if (obj instanceof DERIA5String)
218b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
219c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(indent + "IA5String(" + ((DERIA5String)obj).getString() + ") " + nl);
220b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
221b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else if (obj instanceof DERUTF8String)
222b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
223c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(indent + "UTF8String(" + ((DERUTF8String)obj).getString() + ") " + nl);
224b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
225b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else if (obj instanceof DERPrintableString)
226b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
227c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(indent + "PrintableString(" + ((DERPrintableString)obj).getString() + ") " + nl);
228b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
229b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else if (obj instanceof DERVisibleString)
230b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
231c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(indent + "VisibleString(" + ((DERVisibleString)obj).getString() + ") " + nl);
232b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
233b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else if (obj instanceof DERBMPString)
234b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
235c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(indent + "BMPString(" + ((DERBMPString)obj).getString() + ") " + nl);
236b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
237b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else if (obj instanceof DERT61String)
238b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
239c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(indent + "T61String(" + ((DERT61String)obj).getString() + ") " + nl);
240b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
241b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else if (obj instanceof DERUTCTime)
242b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
243c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(indent + "UTCTime(" + ((DERUTCTime)obj).getTime() + ") " + nl);
244b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
245b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else if (obj instanceof DERGeneralizedTime)
246b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
247c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(indent + "GeneralizedTime(" + ((DERGeneralizedTime)obj).getTime() + ") " + nl);
248b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
249c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        else if (obj instanceof BERApplicationSpecific)
250c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
251c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(outputApplicationSpecific("BER", indent, verbose, obj, nl));
252c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
253c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        else if (obj instanceof DERApplicationSpecific)
254c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
255c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(outputApplicationSpecific("DER", indent, verbose, obj, nl));
256c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
257c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        else if (obj instanceof DEREnumerated)
258c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
259c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            DEREnumerated en = (DEREnumerated) obj;
260c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(indent + "DER Enumerated(" + en.getValue() + ")" + nl);
261c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
262c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        else if (obj instanceof DERExternal)
263c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
264c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            DERExternal ext = (DERExternal) obj;
265c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(indent + "External " + nl);
266c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            String          tab = indent + TAB;
267c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (ext.getDirectReference() != null)
268c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
269c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(tab + "Direct Reference: " + ext.getDirectReference().getId() + nl);
270c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
271c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (ext.getIndirectReference() != null)
272c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
273c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(tab + "Indirect Reference: " + ext.getIndirectReference().toString() + nl);
274c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
275c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (ext.getDataValueDescriptor() != null)
276c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
277c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                _dumpAsString(tab, verbose, ext.getDataValueDescriptor(), buf);
278c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
279c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(tab + "Encoding: " + ext.getEncoding() + nl);
280c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            _dumpAsString(tab, verbose, ext.getExternalContent(), buf);
281b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
282b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else
283b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
284c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            buf.append(indent + obj.toString() + nl);
285c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
286c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
287c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
2884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private static String outputApplicationSpecific(String type, String indent, boolean verbose, ASN1Primitive obj, String nl)
289c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
290c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        DERApplicationSpecific app = (DERApplicationSpecific)obj;
291c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        StringBuffer buf = new StringBuffer();
292c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
293c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (app.isConstructed())
294c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
295c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            try
296c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
2974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ASN1Sequence s = ASN1Sequence.getInstance(app.getObject(BERTags.SEQUENCE));
298c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "]" + nl);
299c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                for (Enumeration e = s.getObjects(); e.hasMoreElements();)
300c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                {
3014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    _dumpAsString(indent + TAB, verbose, (ASN1Primitive)e.nextElement(), buf);
302c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                }
303c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
304c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            catch (IOException e)
305c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
306c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(e);
307c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
308c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return buf.toString();
309b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
310c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
311c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "] (" + new String(Hex.encode(app.getContents())) + ")" + nl;
312b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
313b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
314b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
315c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * dump out a DER object as a formatted string, in non-verbose mode.
316b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
3174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     * @param obj the ASN1Primitive to be dumped out.
318c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * @return  the resulting string.
319b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
320b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public static String dumpAsString(
321b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Object   obj)
322b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
323c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return dumpAsString(obj, false);
324c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
325c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
326c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    /**
327c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * Dump out the object as a string.
328c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     *
329c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * @param obj  the object to be dumped
330c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * @param verbose  if true, dump out the contents of octet and bit strings.
331c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * @return  the resulting string.
332c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     */
333c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    public static String dumpAsString(
334c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        Object   obj,
335c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        boolean  verbose)
336c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
337c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        StringBuffer buf = new StringBuffer();
338c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
3394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (obj instanceof ASN1Primitive)
340b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
3414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            _dumpAsString("", verbose, (ASN1Primitive)obj, buf);
342b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
3434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (obj instanceof ASN1Encodable)
344b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
3454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            _dumpAsString("", verbose, ((ASN1Encodable)obj).toASN1Primitive(), buf);
346c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
347c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        else
348c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
349c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return "unknown object type " + obj.toString();
350c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
351c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
352c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return buf.toString();
353c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
354c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
355c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static String dumpBinaryDataAsString(String indent, byte[] bytes)
356c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
357c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        String nl = System.getProperty("line.separator");
358c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        StringBuffer buf = new StringBuffer();
359c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
360c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        indent += TAB;
361c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
362c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        buf.append(nl);
363c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        for (int i = 0; i < bytes.length; i += SAMPLE_SIZE)
364c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
365c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (bytes.length - i > SAMPLE_SIZE)
366c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
367c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(indent);
368c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(new String(Hex.encode(bytes, i, SAMPLE_SIZE)));
369c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(TAB);
370c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(calculateAscString(bytes, i, SAMPLE_SIZE));
371c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(nl);
372c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
373c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            else
374c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
375c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(indent);
376c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(new String(Hex.encode(bytes, i, bytes.length - i)));
377c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                for (int j = bytes.length - i; j != SAMPLE_SIZE; j++)
378c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                {
379c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    buf.append("  ");
380c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                }
381c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(TAB);
382c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(calculateAscString(bytes, i, bytes.length - i));
383c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append(nl);
384c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
385c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
386c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
387c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return buf.toString();
388c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
389c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
390c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private static String calculateAscString(byte[] bytes, int off, int len)
391c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
392c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        StringBuffer buf = new StringBuffer();
393c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
394c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        for (int i = off; i != off + len; i++)
395c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
396c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (bytes[i] >= ' ' && bytes[i] <= '~')
397c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
398c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                buf.append((char)bytes[i]);
399c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
400b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
401b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
402c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return buf.toString();
403b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
404b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
405