asn1der.java

来自「一个非常好的ssh客户端实现」· Java 代码 · 共 399 行

JAVA
399
字号
/****************************************************************************** * * Copyright (c) 1999-2003 AppGate Network Security AB. All Rights Reserved. *  * This file contains Original Code and/or Modifications of Original Code as * defined in and that are subject to the MindTerm Public Source License, * Version 2.0, (the 'License'). You may not use this file except in compliance * with the License. *  * You should have received a copy of the MindTerm Public Source License * along with this software; see the file LICENSE.  If not, write to * AppGate Network Security AB, Otterhallegatan 2, SE-41118 Goteborg, SWEDEN * *****************************************************************************/package com.mindbright.asn1;import java.io.InputStream;import java.io.OutputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.math.BigInteger;public class ASN1DER implements ASN1Encoder, ASN1Decoder {    protected final static byte[] BOOL_TRUE  = { (byte)0xff };    protected final static byte[] BOOL_FALSE = { (byte)0x00 };    protected final static int INDEFINITE_LEN = -1;    public int encode(OutputStream out, ASN1Object object) throws IOException {	ByteArrayOutputStream encVal = new ByteArrayOutputStream();	int tag = object.getTag();	int len = object.encodeValue(this, encVal);	int cnt = len;	out.write((byte)tag);	cnt++;	cnt += encodeLength(out, len);	encVal.writeTo(out);	return cnt;    }    public int encodeLength(OutputStream out, int len) throws IOException {	int cnt = 0;	if(len < 0x80) {	    out.write((byte)len);	    cnt++;	} else {	    byte[] encLen = new byte[5];	    int i = 4;	    do {		encLen[i--] = (byte)(len & 0xff);		len >>>= 8;	    } while(len > 0);	    int c = (5 - i);	    encLen[i] = (byte)(0x80 | (c - 1));	    out.write(encLen, i, c);	    cnt += c;	}	return cnt;    }    public int encodeBoolean(OutputStream out, boolean b) throws IOException {	out.write(b ? BOOL_TRUE : BOOL_FALSE);	return 1;    }    public int encodeInteger(OutputStream out, BigInteger i)	throws IOException    {	byte[] enc = i.toByteArray();	out.write(enc);	return enc.length;    }    public int encodeNull(OutputStream out) throws IOException {	return 0;    }    public int encodeOID(OutputStream out, int[] oid) throws IOException {	int cnt = 1;	out.write((40 * oid[0]) + oid[1]);	for(int i = 2; i < oid.length; i++) {	    int v = oid[i];	    if(v < 0x80) {		out.write((byte)v);		cnt++;	    } else {		byte[] b = new byte[4];		int    j = 4;		do {		    j--;		    b[j] = (byte)(v & 0x7f);		    v >>>= 7;		    if(j < 3) {			b[j] = (byte)(((int)b[j] & 0xff) | 0x80);		    }		} while(v > 0);		while(j < 4) {		    out.write(b[j++]);		    cnt++;		}	    }	}	return cnt;    }    public int encodeString(OutputStream out, byte[] string)	throws IOException    {	out.write(string);	return string.length;    }    public int encodeStructure(OutputStream out, ASN1Structure struct)	throws IOException    {	int count = struct.getCount();	int size  = 0;	for(int i = 0; i < count; i++) {	    ASN1Object component = struct.getComponent(i);	    if(struct.isOptional(i)) {		ASN1Object d = struct.getDefault(i);		if(!component.isSet() || component.equals(d)) {		    continue;		}	    }	    size += encode(out, component);	}	return size;    }    public int decode(InputStream in, ASN1Object object) throws IOException {	int   tag = decodeTag(in);	int[] dl  = decodeLength(in);	decodeValue(in, tag, dl[0], object);	return 1 + dl[1] + dl[0];    }    public int decodeTag(InputStream in) throws IOException {	int tag = in.read();	if((tag & ASN1.MASK_NUMBER) == ASN1.MASK_NUMBER) {	    throw new IOException("Long form of tags not supported yet");	}	return tag;    }    public int[] decodeLength(InputStream in) throws IOException {	int cnt = 1;	int len = in.read();	if(len > 0x80) {	    int n = (len & 0x7f);	    len = 0;	    for(int i = 0; i < n; i++) {		len <<= 8;		len += in.read();		cnt++;	    }	} else if(len == 0x80) {	    len = INDEFINITE_LEN;	}	return new int[] { len, cnt };    }    public void decodeValue(InputStream in, int tag, int len, ASN1Object object)	throws IOException    {	if(((tag & ASN1.TYPE_CONSTRUCTED) != 0) &&	   (object instanceof ASN1String)) {	    ASN1ConstructedString cs =		new ASN1ConstructedString(tag, object.getClass());	    cs.decodeValue(this, in, tag, len);	    ByteArrayOutputStream ba = new ByteArrayOutputStream();	    for(int i = 0; i < cs.getCount(); i++) {		ASN1Object s = cs.getComponent(i);		s.encodeValue(this, ba);	    }	    ((ASN1String)object).setRaw(ba.toByteArray());	} else {	    object.decodeValue(this, in, tag, len);	}    }    public boolean decodeBoolean(InputStream in, int len) throws IOException {	byte b = (byte)in.read();	if(len != 1 ||	   (b != BOOL_FALSE[0] && b != BOOL_TRUE[0])) {	    throw new IOException("Invalid DER encoding of boolean");	}	return (b == BOOL_TRUE[0]);    }    public BigInteger decodeInteger(InputStream in, int len)	throws IOException    {	byte[] enc = new byte[len];	readNextN(in, enc, len);	return new BigInteger(enc);    }    public void decodeNull(InputStream in, int len) throws IOException {	if(len != 0) {	    throw new IOException("Invalid DER encoding of NULL");	}    }    public int[] decodeOID(InputStream in, int len) throws IOException {	int[] oid = new int[len + 1];	if(len < 1) {	    throw new IOException("Invalid DER encoding of OID");	}	oid[0] = in.read();	len--;	if(oid[0] > ((2 * 40) + 39)) {	    oid[1] = oid[0] - (2 * 40);	    oid[0] = 2;	} else {	    oid[1] = oid[0] % 40;	    oid[0] = oid[0] / 40;	}	int i = 2;	while(len > 0) {	    int v = 0;	    int d = in.read();	    len--;	    while(d > 0x80) {		d &= 0x7f;		v <<= 7;		v |= d;		d = in.read();		len--;	    }	    v <<= 7;	    v |= d;	    oid[i++] = v;	}	int[] tmp = oid;	oid = new int[i];	System.arraycopy(tmp, 0, oid, 0, i);	return oid;    }    public byte[] decodeString(InputStream in, int len) throws IOException {	byte[] string = new byte[len];	readNextN(in, string, len);	return string;    }    private final class CountingInputStream extends InputStream {        int pos;        InputStream in;                CountingInputStream(InputStream in) {            pos = 0;            this.in = in;        }                public int read() throws IOException {            int res = in.read();            pos++;            return res;        }                public int read(byte[] b) throws IOException {            return read(b, 0, b.length);        }                public int read(byte[] b, int off, int len)            throws IOException {            int res = in.read(b, off, len);            if (res > 0)                pos += res;            return res;        }         }        private void decodeStructureIndef(InputStream in, ASN1Structure struct)	throws IOException {        boolean endOfStruct = false;        int     i           = 0;        while(!endOfStruct) {            int   tag = decodeTag(in);            int[] dl  = decodeLength(in);            if((tag == 0) && (dl[0] == 0)) {                endOfStruct = true;            } else {                ASN1Object component = null;                do {                    component = struct.getDecodeComponent(i++, tag);                } while(component == null);                decodeValue(in, tag, dl[0], component);            }        }    }        public void decodeStructure(InputStream in, int len, ASN1Structure struct)        throws IOException {        if (len == INDEFINITE_LEN) {            decodeStructureIndef(in, struct);            return;        }        CountingInputStream cin;        if (in instanceof CountingInputStream) {            cin = (CountingInputStream)in;        } else {            cin = new CountingInputStream(in);        }        	int i     = 0;	while(len > 0) {	    int   tag = decodeTag(cin);	    int[] dl  = decodeLength(cin);  	    len -= (1 + dl[1]);	    ASN1Object component = null;            int pos = cin.pos;            	    do {		component = struct.getDecodeComponent(i++, tag);	    } while(component == null);	    decodeValue(cin, tag, dl[0], component);                        if (dl[0] < 0) {                len -= (cin.pos - pos);            } else {                if ((cin.pos - pos) != dl[0]) {                    throw new IOException("Component size mismatch: " + (cin.pos - pos) + " " + len);                }                len -= dl[0];            }	}    }    private void readNextN(InputStream in, byte[] buf, int n)	throws IOException    {	int wPos = 0;	while(wPos < n) {	    int s = in.read(buf, wPos, n - wPos);	    if(s == -1)		throw new IOException("DER encoding ended prematurely");	    wPos += s;	}    }    public static void main(String[] argv) {	try {	    ASN1DER der = new ASN1DER();	    /*	    ByteArrayOutputStream ba = new ByteArrayOutputStream();	    ASN1SequenceOf so = new ASN1SequenceOf(ASN1OID.class);	    ASN1OID o = new ASN1OID();	    o = (ASN1OID)so.getComponent(0);	    o.setString("1.2.840.113549.2.5");	    o = (ASN1OID)so.getComponent(1);	    o.setString("1.2.840.113549.2.2");	    o = (ASN1OID)so.getComponent(2);	    o.setString("1.3.14.3.2.26");	    o = (ASN1OID)so.getComponent(3);	    o.setString("1.3.36.3.2.1");	    der.encode(ba, so);	    com.mindbright.util.HexDump.print(ba.toByteArray());	    */	    ASN1Any any = new ASN1Any();	    java.io.FileInputStream file =		new java.io.FileInputStream("key.p12");	    der.decode(file, any);	    //    der.decode(new java.io.ByteArrayInputStream(ba.toByteArray()), any);	} catch (Exception e) {	    e.printStackTrace();	}    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?