001/* 002 * $HeadURL: file:///opt/dev/not-yet-commons-ssl-SVN-repo/tags/commons-ssl-0.3.17/src/java/org/apache/commons/ssl/ASN1Util.java $ 003 * $Revision: 183 $ 004 * $Date: 2015-03-16 12:12:27 -0700 (Mon, 16 Mar 2015) $ 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 032package org.apache.commons.ssl; 033 034import java.io.FileInputStream; 035import java.io.IOException; 036import java.math.BigInteger; 037import java.util.Enumeration; 038import java.util.List; 039import java.util.Vector; 040 041import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Encodable; 042import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1InputStream; 043import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer; 044import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1ObjectIdentifier; 045import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1OctetString; 046import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence; 047import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Set; 048import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject; 049import org.apache.commons.ssl.org.bouncycastle.asn1.DERPrintableString; 050import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence; 051import org.apache.commons.ssl.org.bouncycastle.asn1.DERSet; 052import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject; 053import org.apache.commons.ssl.org.bouncycastle.asn1.DLSequence; 054import org.apache.commons.ssl.util.Hex; 055 056/** 057 * @author Credit Union Central of British Columbia 058 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a> 059 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a> 060 * @since 16-Nov-2005 061 */ 062public class ASN1Util { 063 public static boolean DEBUG = false; 064 public final static BigInteger BIGGEST = 065 new BigInteger(Integer.toString(Integer.MAX_VALUE)); 066 067 public static ASN1Structure analyze(byte[] asn1) 068 throws IOException { 069 ASN1InputStream asn = new ASN1InputStream(asn1); 070 DLSequence seq = (DLSequence) asn.readObject(); 071 ASN1Structure pkcs8 = new ASN1Structure(); 072 ASN1Util.analyze(seq, pkcs8, 0); 073 return pkcs8; 074 } 075 076 public static void main(String[] args) throws Exception { 077 DEBUG = true; 078 FileInputStream in = new FileInputStream(args[0]); 079 byte[] bytes = Util.streamToBytes(in); 080 List list = PEMUtil.decode(bytes); 081 if (!list.isEmpty()) { 082 bytes = ((PEMItem) list.get(0)).getDerBytes(); 083 } 084 085 ASN1Structure asn1 = analyze(bytes); 086 while (asn1.bigPayload != null) { 087 System.out.println("------------------------------------------"); 088 System.out.println(asn1); 089 System.out.println("------------------------------------------"); 090 asn1 = analyze(asn1.bigPayload); 091 } 092 } 093 094 095 public static void analyze(ASN1Encodable seq, ASN1Structure pkcs8, 096 int depth) { 097 String tag = null; 098 if (depth >= 2) { 099 pkcs8.derIntegers = null; 100 } 101 Enumeration en; 102 if (seq instanceof DLSequence) { 103 en = ((DLSequence) seq).getObjects(); 104 } else if (seq instanceof DERSet) { 105 en = ((DERSet) seq).getObjects(); 106 } else if (seq instanceof DERTaggedObject) { 107 DERTaggedObject derTag = (DERTaggedObject) seq; 108 tag = Integer.toString(derTag.getTagNo()); 109 Vector v = new Vector(); 110 v.add(derTag.getObject()); 111 en = v.elements(); 112 } else { 113 throw new IllegalArgumentException("DEREncodable must be one of: DLSequence, DERSet, DERTaggedObject"); 114 } 115 while (en != null && en.hasMoreElements()) { 116 ASN1Encodable obj = (ASN1Encodable) en.nextElement(); 117 if (!(obj instanceof ASN1Sequence) && 118 !(obj instanceof ASN1Set) && 119 !(obj instanceof ASN1TaggedObject)) { 120 String str = obj.toString(); 121 String name = obj.getClass().getName(); 122 name = name.substring(name.lastIndexOf('.') + 1); 123 if (tag != null) { 124 name = " [tag=" + tag + "] " + name; 125 } 126 for (int i = 0; i < depth; i++) { 127 name = " " + name; 128 } 129 if (obj instanceof ASN1Integer) { 130 ASN1Integer dInt = (ASN1Integer) obj; 131 if (pkcs8.derIntegers != null) { 132 pkcs8.derIntegers.add(dInt); 133 } 134 BigInteger big = dInt.getValue(); 135 int intValue = big.intValue(); 136 if (BIGGEST.compareTo(big) >= 0 && intValue > 0) { 137 if (pkcs8.iterationCount == 0) { 138 pkcs8.iterationCount = intValue; 139 } else if (pkcs8.keySize == 0) { 140 pkcs8.keySize = intValue; 141 } 142 } 143 str = dInt.getValue().toString(); 144 } else if (obj instanceof ASN1ObjectIdentifier) { 145 ASN1ObjectIdentifier id = (ASN1ObjectIdentifier) obj; 146 str = id.getId(); 147 pkcs8.oids.add(str); 148 if (pkcs8.oid1 == null) { 149 pkcs8.oid1 = str; 150 } else if (pkcs8.oid2 == null) { 151 pkcs8.oid2 = str; 152 } else if (pkcs8.oid3 == null) { 153 pkcs8.oid3 = str; 154 } 155 } else { 156 pkcs8.derIntegers = null; 157 if (obj instanceof ASN1OctetString) { 158 ASN1OctetString oct = (ASN1OctetString) obj; 159 byte[] octets = oct.getOctets(); 160 int len = Math.min(10, octets.length); 161 boolean probablyBinary = false; 162 for (int i = 0; i < len; i++) { 163 byte b = octets[i]; 164 boolean isBinary = b > 128 || b < 0; 165 if (isBinary) { 166 probablyBinary = true; 167 break; 168 } 169 } 170 if (probablyBinary && octets.length > 64) { 171 if (pkcs8.bigPayload == null) { 172 pkcs8.bigPayload = octets; 173 } 174 str = "probably binary"; 175 } else { 176 str = Hex.encode(octets); 177 if (octets.length <= 64) { 178 if (octets.length % 8 == 0) { 179 if (pkcs8.salt == null) { 180 pkcs8.salt = octets; 181 } else if (pkcs8.iv == null) { 182 pkcs8.iv = octets; 183 } 184 } else { 185 if (pkcs8.smallPayload == null) { 186 pkcs8.smallPayload = octets; 187 } 188 } 189 } 190 } 191 str += " (length=" + octets.length + ")"; 192 } else if (obj instanceof DERPrintableString) { 193 DERPrintableString dps = (DERPrintableString) obj; 194 str = dps.getString(); 195 } 196 } 197 198 if (DEBUG) { 199 System.out.println(name + ": [" + str + "]"); 200 } 201 } else { 202 if (tag != null && DEBUG) { 203 String name = obj.getClass().getName(); 204 name = name.substring(name.lastIndexOf('.') + 1); 205 name = " [tag=" + tag + "] " + name; 206 for (int i = 0; i < depth; i++) { 207 name = " " + name; 208 } 209 System.out.println(name); 210 } 211 analyze(obj, pkcs8, depth + 1); 212 } 213 } 214 } 215}