001 /* 002 * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.11/src/java/org/apache/commons/ssl/ASN1Util.java $ 003 * $Revision: 121 $ 004 * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $ 005 * 006 * ==================================================================== 007 * Licensed to the Apache Software Foundation (ASF) under one 008 * or more contributor license agreements. See the NOTICE file 009 * distributed with this work for additional information 010 * regarding copyright ownership. The ASF licenses this file 011 * to you under the Apache License, Version 2.0 (the 012 * "License"); you may not use this file except in compliance 013 * with the License. You may obtain a copy of the License at 014 * 015 * http://www.apache.org/licenses/LICENSE-2.0 016 * 017 * Unless required by applicable law or agreed to in writing, 018 * software distributed under the License is distributed on an 019 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 020 * KIND, either express or implied. See the License for the 021 * specific language governing permissions and limitations 022 * under the License. 023 * ==================================================================== 024 * 025 * This software consists of voluntary contributions made by many 026 * individuals on behalf of the Apache Software Foundation. For more 027 * information on the Apache Software Foundation, please see 028 * <http://www.apache.org/>. 029 * 030 */ 031 032 package org.apache.commons.ssl; 033 034 import org.apache.commons.ssl.asn1.ASN1InputStream; 035 import org.apache.commons.ssl.asn1.DEREncodable; 036 import org.apache.commons.ssl.asn1.DERInteger; 037 import org.apache.commons.ssl.asn1.DERObjectIdentifier; 038 import org.apache.commons.ssl.asn1.DEROctetString; 039 import org.apache.commons.ssl.asn1.DERPrintableString; 040 import org.apache.commons.ssl.asn1.DERSequence; 041 import org.apache.commons.ssl.asn1.DERSet; 042 import org.apache.commons.ssl.asn1.DERTaggedObject; 043 import org.apache.commons.ssl.util.Hex; 044 045 import java.io.FileInputStream; 046 import java.io.IOException; 047 import java.math.BigInteger; 048 import java.util.Enumeration; 049 import java.util.List; 050 import java.util.Vector; 051 052 /** 053 * @author Credit Union Central of British Columbia 054 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a> 055 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a> 056 * @since 16-Nov-2005 057 */ 058 public class ASN1Util { 059 public static boolean DEBUG = false; 060 public final static BigInteger BIGGEST = 061 new BigInteger(Integer.toString(Integer.MAX_VALUE)); 062 063 public static ASN1Structure analyze(byte[] asn1) 064 throws IOException { 065 ASN1InputStream asn = new ASN1InputStream(asn1); 066 DERSequence seq = (DERSequence) asn.readObject(); 067 ASN1Structure pkcs8 = new ASN1Structure(); 068 ASN1Util.analyze(seq, pkcs8, 0); 069 return pkcs8; 070 } 071 072 public static void main(String[] args) throws Exception { 073 DEBUG = true; 074 FileInputStream in = new FileInputStream(args[0]); 075 byte[] bytes = Util.streamToBytes(in); 076 List list = PEMUtil.decode(bytes); 077 if (!list.isEmpty()) { 078 bytes = ((PEMItem) list.get(0)).getDerBytes(); 079 } 080 081 ASN1Structure asn1 = analyze(bytes); 082 while (asn1.bigPayload != null) { 083 System.out.println("------------------------------------------"); 084 System.out.println(asn1); 085 System.out.println("------------------------------------------"); 086 asn1 = analyze(asn1.bigPayload); 087 } 088 } 089 090 091 public static void analyze(DEREncodable seq, ASN1Structure pkcs8, 092 int depth) { 093 String tag = null; 094 if (depth >= 2) { 095 pkcs8.derIntegers = null; 096 } 097 Enumeration en; 098 if (seq instanceof DERSequence) { 099 en = ((DERSequence) seq).getObjects(); 100 } else if (seq instanceof DERSet) { 101 en = ((DERSet) seq).getObjects(); 102 } else if (seq instanceof DERTaggedObject) { 103 DERTaggedObject derTag = (DERTaggedObject) seq; 104 tag = Integer.toString(derTag.getTagNo()); 105 Vector v = new Vector(); 106 v.add(derTag.getObject()); 107 en = v.elements(); 108 } else { 109 throw new IllegalArgumentException("DEREncodable must be one of: DERSequence, DERSet, DERTaggedObject"); 110 } 111 while (en != null && en.hasMoreElements()) { 112 DEREncodable obj = (DEREncodable) en.nextElement(); 113 if (!(obj instanceof DERSequence) && 114 !(obj instanceof DERSet) && 115 !(obj instanceof DERTaggedObject)) { 116 String str = obj.toString(); 117 String name = obj.getClass().getName(); 118 name = name.substring(name.lastIndexOf('.') + 1); 119 if (tag != null) { 120 name = " [tag=" + tag + "] " + name; 121 } 122 for (int i = 0; i < depth; i++) { 123 name = " " + name; 124 } 125 if (obj instanceof DERInteger) { 126 DERInteger dInt = (DERInteger) obj; 127 if (pkcs8.derIntegers != null) { 128 pkcs8.derIntegers.add(dInt); 129 } 130 BigInteger big = dInt.getValue(); 131 int intValue = big.intValue(); 132 if (BIGGEST.compareTo(big) >= 0 && intValue > 0) { 133 if (pkcs8.iterationCount == 0) { 134 pkcs8.iterationCount = intValue; 135 } else if (pkcs8.keySize == 0) { 136 pkcs8.keySize = intValue; 137 } 138 } 139 str = dInt.getValue().toString(); 140 } else if (obj instanceof DERObjectIdentifier) { 141 DERObjectIdentifier id = (DERObjectIdentifier) obj; 142 str = id.getId(); 143 pkcs8.oids.add(str); 144 if (pkcs8.oid1 == null) { 145 pkcs8.oid1 = str; 146 } else if (pkcs8.oid2 == null) { 147 pkcs8.oid2 = str; 148 } else if (pkcs8.oid3 == null) { 149 pkcs8.oid3 = str; 150 } 151 } else { 152 pkcs8.derIntegers = null; 153 if (obj instanceof DEROctetString) { 154 DEROctetString oct = (DEROctetString) obj; 155 byte[] octets = oct.getOctets(); 156 int len = Math.min(10, octets.length); 157 boolean probablyBinary = false; 158 for (int i = 0; i < len; i++) { 159 byte b = octets[i]; 160 boolean isBinary = b > 128 || b < 0; 161 if (isBinary) { 162 probablyBinary = true; 163 break; 164 } 165 } 166 if (probablyBinary && octets.length > 64) { 167 if (pkcs8.bigPayload == null) { 168 pkcs8.bigPayload = octets; 169 } 170 str = "probably binary"; 171 } else { 172 str = Hex.encode(octets); 173 if (octets.length <= 64) { 174 if (octets.length % 8 == 0) { 175 if (pkcs8.salt == null) { 176 pkcs8.salt = octets; 177 } else if (pkcs8.iv == null) { 178 pkcs8.iv = octets; 179 } 180 } else { 181 if (pkcs8.smallPayload == null) { 182 pkcs8.smallPayload = octets; 183 } 184 } 185 } 186 } 187 str += " (length=" + octets.length + ")"; 188 } else if (obj instanceof DERPrintableString) { 189 DERPrintableString dps = (DERPrintableString) obj; 190 str = dps.getString(); 191 } 192 } 193 194 if (DEBUG) { 195 System.out.println(name + ": [" + str + "]"); 196 } 197 } else { 198 if (tag != null && DEBUG) { 199 String name = obj.getClass().getName(); 200 name = name.substring(name.lastIndexOf('.') + 1); 201 name = " [tag=" + tag + "] " + name; 202 for (int i = 0; i < depth; i++) { 203 name = " " + name; 204 } 205 System.out.println(name); 206 } 207 analyze(obj, pkcs8, depth + 1); 208 } 209 } 210 } 211 }