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 + -
显示快捷键?