151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.security.util; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.ByteArrayOutputStream; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.OutputStream; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.text.SimpleDateFormat; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Date; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.TimeZone; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Comparator; 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Arrays; 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.math.BigInteger; 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Locale; 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Output stream marshaling DER-encoded data. This is eventually provided 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in the form of a byte array; there is no advance limit on the size of 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * that byte array. 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P>At this time, this class supports only a subset of the types of 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DER data encodings which are defined. That subset is sufficient for 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * generating most X.509 certificates. 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author David Brownell 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Amit Kapoor 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Hemma Prafullchandra 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class DerOutputStream 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiextends ByteArrayOutputStream implements DerEncoder { 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Construct an DER output stream. 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param size how large a buffer to preallocate. 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerOutputStream(int size) { super(size); } 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Construct an DER output stream. 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerOutputStream() { } 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes tagged, pre-marshaled data. This calcuates and encodes 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the length, so that the output data is the standard triple of 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * { tag, length, data } used by all DER values. 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param tag the DER value tag for the data, such as 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <em>DerValue.tag_Sequence</em> 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param buf buffered data, which must be DER-encoded 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void write(byte tag, byte[] buf) throws IOException { 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(tag); 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putLength(buf.length); 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(buf, 0, buf.length); 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes tagged data using buffer-to-buffer copy. As above, 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this writes a standard DER record. This is often used when 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * efficiently encapsulating values in sequences. 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param tag the DER value tag for the data, such as 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <em>DerValue.tag_Sequence</em> 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param out buffered data 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void write(byte tag, DerOutputStream out) throws IOException { 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(tag); 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putLength(out.count); 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(out.buf, 0, out.count); 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Writes implicitly tagged data using buffer-to-buffer copy. As above, 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this writes a standard DER record. This is often used when 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * efficiently encapsulating implicitly tagged values. 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param tag the DER value of the context-specific tag that replaces 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * original tag of the value in the output, such as in 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre> 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <em> <field> [N] IMPLICIT <type></em> 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre> 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For example, <em>FooLength [1] IMPLICIT INTEGER</em>, with value=4; 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * would be encoded as "81 01 04" whereas in explicit 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * tagging it would be encoded as "A1 03 02 01 04". 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Notice that the tag is A1 and not 81, this is because with 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * explicit tagging the form is always constructed. 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param value original value being implicitly tagged 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void writeImplicit(byte tag, DerOutputStream value) 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(tag); 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(value.buf, 1, value.count-1); 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals pre-encoded DER value onto the output stream. 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putDerValue(DerValue val) throws IOException { 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski val.encode(this); 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * PRIMITIVES -- these are "universal" ASN.1 simple types. 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * BOOLEAN, INTEGER, BIT STRING, OCTET STRING, NULL 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * OBJECT IDENTIFIER, SEQUENCE(OF), SET(OF) 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * PrintableString, T61String, IA5String, UTCTime 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a DER boolean on the output stream. 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putBoolean(boolean val) throws IOException { 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(DerValue.tag_Boolean); 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putLength(1); 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (val) { 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(0xff); 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(0); 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a DER enumerated on the output stream. 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param i the enumerated value. 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putEnumerated(int i) throws IOException { 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(DerValue.tag_Enumerated); 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putIntegerContents(i); 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a DER integer on the output stream. 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param i the integer in the form of a BigInteger. 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putInteger(BigInteger i) throws IOException { 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(DerValue.tag_Integer); 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] buf = i.toByteArray(); // least number of bytes 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putLength(buf.length); 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(buf, 0, buf.length); 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a DER integer on the output stream. 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param i the integer in the form of an Integer. 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putInteger(Integer i) throws IOException { 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putInteger(i.intValue()); 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a DER integer on the output stream. 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param i the integer. 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putInteger(int i) throws IOException { 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(DerValue.tag_Integer); 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putIntegerContents(i); 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void putIntegerContents(int i) throws IOException { 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] bytes = new byte[4]; 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int start = 0; 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Obtain the four bytes of the int 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bytes[3] = (byte) (i & 0xff); 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bytes[2] = (byte)((i & 0xff00) >>> 8); 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bytes[1] = (byte)((i & 0xff0000) >>> 16); 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bytes[0] = (byte)((i & 0xff000000) >>> 24); 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Reduce them to the least number of bytes needed to 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // represent this int 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (bytes[0] == (byte)0xff) { 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Eliminate redundant 0xff 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int j = 0; j < 3; j++) { 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((bytes[j] == (byte)0xff) && 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ((bytes[j+1] & 0x80) == 0x80)) 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski start++; 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (bytes[0] == 0x00) { 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Eliminate redundant 0x00 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int j = 0; j < 3; j++) { 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((bytes[j] == 0x00) && 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ((bytes[j+1] & 0x80) == 0)) 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski start++; 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putLength(4 - start); 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int k = start; k < 4; k++) 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(bytes[k]); 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a DER bit string on the output stream. The bit 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * string must be byte-aligned. 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param bits the bit string, MSB first 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putBitString(byte[] bits) throws IOException { 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(DerValue.tag_BitString); 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putLength(bits.length + 1); 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(0); // all of last octet is used 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(bits); 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a DER bit string on the output stream. 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The bit strings need not be byte-aligned. 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param bits the bit string, MSB first 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putUnalignedBitString(BitArray ba) throws IOException { 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] bits = ba.toByteArray(); 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(DerValue.tag_BitString); 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putLength(bits.length + 1); 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(bits.length*8 - ba.length()); // excess bits in last octet 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(bits); 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a truncated DER bit string on the output stream. 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The bit strings need not be byte-aligned. 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param bits the bit string, MSB first 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putTruncatedUnalignedBitString(BitArray ba) throws IOException { 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putUnalignedBitString(ba.truncate()); 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DER-encodes an ASN.1 OCTET STRING value on the output stream. 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param octets the octet string 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putOctetString(byte[] octets) throws IOException { 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(DerValue.tag_OctetString, octets); 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a DER "null" value on the output stream. These are 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * often used to indicate optional values which have been omitted. 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putNull() throws IOException { 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(DerValue.tag_Null); 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putLength(0); 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals an object identifier (OID) on the output stream. 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Corresponds to the ASN.1 "OBJECT IDENTIFIER" construct. 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putOID(ObjectIdentifier oid) throws IOException { 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski oid.encode(this); 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a sequence on the output stream. This supports both 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the ASN.1 "SEQUENCE" (zero to N values) and "SEQUENCE OF" 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (one to N values) constructs. 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putSequence(DerValue[] seq) throws IOException { 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerOutputStream bytes = new DerOutputStream(); 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int i; 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (i = 0; i < seq.length; i++) 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski seq[i].encode(bytes); 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(DerValue.tag_Sequence, bytes); 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals the contents of a set on the output stream without 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ordering the elements. Ok for BER encoding, but not for DER 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * encoding. 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For DER encoding, use orderedPutSet() or orderedPutSetOf(). 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putSet(DerValue[] set) throws IOException { 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerOutputStream bytes = new DerOutputStream(); 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int i; 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (i = 0; i < set.length; i++) 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski set[i].encode(bytes); 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(DerValue.tag_Set, bytes); 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals the contents of a set on the output stream. Sets 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are semantically unordered, but DER requires that encodings of 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * set elements be sorted into ascending lexicographical order 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * before being output. Hence sets with the same tags and 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * elements have the same DER encoding. 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This method supports the ASN.1 "SET OF" construct, but not 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * "SET", which uses a different order. 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putOrderedSetOf(byte tag, DerEncoder[] set) throws IOException { 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putOrderedSet(tag, set, lexOrder); 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals the contents of a set on the output stream. Sets 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are semantically unordered, but DER requires that encodings of 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * set elements be sorted into ascending tag order 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * before being output. Hence sets with the same tags and 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * elements have the same DER encoding. 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This method supports the ASN.1 "SET" construct, but not 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * "SET OF", which uses a different order. 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putOrderedSet(byte tag, DerEncoder[] set) throws IOException { 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putOrderedSet(tag, set, tagOrder); 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Lexicographical order comparison on byte arrays, for ordering 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * elements of a SET OF objects in DER encoding. 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static ByteArrayLexOrder lexOrder = new ByteArrayLexOrder(); 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Tag order comparison on byte arrays, for ordering elements of 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * SET objects in DER encoding. 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static ByteArrayTagOrder tagOrder = new ByteArrayTagOrder(); 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a the contents of a set on the output stream with the 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * encodings of its sorted in increasing order. 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param order the order to use when sorting encodings of components. 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void putOrderedSet(byte tag, DerEncoder[] set, 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Comparator<byte[]> order) throws IOException { 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerOutputStream[] streams = new DerOutputStream[set.length]; 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < set.length; i++) { 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski streams[i] = new DerOutputStream(); 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski set[i].derEncode(streams[i]); 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // order the element encodings 38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[][] bufs = new byte[streams.length][]; 38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < streams.length; i++) { 38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bufs[i] = streams[i].toByteArray(); 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Arrays.<byte[]>sort(bufs, order); 38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerOutputStream bytes = new DerOutputStream(); 39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < streams.length; i++) { 39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bytes.write(bufs[i]); 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(tag, bytes); 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a string as a DER encoded UTF8String. 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putUTF8String(String s) throws IOException { 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeString(s, DerValue.tag_UTF8String, "UTF8"); 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a string as a DER encoded PrintableString. 40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putPrintableString(String s) throws IOException { 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeString(s, DerValue.tag_PrintableString, "ASCII"); 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a string as a DER encoded T61String. 41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putT61String(String s) throws IOException { 41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Works for characters that are defined in both ASCII and 41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * T61. 41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeString(s, DerValue.tag_T61String, "ISO-8859-1"); 42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a string as a DER encoded IA5String. 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putIA5String(String s) throws IOException { 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeString(s, DerValue.tag_IA5String, "ASCII"); 42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a string as a DER encoded BMPString. 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putBMPString(String s) throws IOException { 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeString(s, DerValue.tag_BMPString, "UnicodeBigUnmarked"); 43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a string as a DER encoded GeneralString. 43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putGeneralString(String s) throws IOException { 44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski writeString(s, DerValue.tag_GeneralString, "ASCII"); 44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Private helper routine for writing DER encoded string values. 44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param s the string to write 44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param stringTag one of the DER string tags that indicate which 44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * encoding should be used to write the string out. 44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param enc the name of the encoder that should be used corresponding 44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to the above tag. 45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void writeString(String s, byte stringTag, String enc) 45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] data = s.getBytes(enc); 45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(stringTag); 45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putLength(data.length); 45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(data); 45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a DER UTC time/date value. 46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P>YYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time 46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and with seconds (even if seconds=0) as per RFC 3280. 46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putUTCTime(Date d) throws IOException { 46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putTime(d, DerValue.tag_UtcTime); 46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Marshals a DER Generalized Time/date value. 47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P>YYYYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time 47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and with seconds (even if seconds=0) as per RFC 3280. 47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putGeneralizedTime(Date d) throws IOException { 47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putTime(d, DerValue.tag_GeneralizedTime); 47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Private helper routine for marshalling a DER UTC/Generalized 48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * time/date value. If the tag specified is not that for UTC Time 48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * then it defaults to Generalized Time. 48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param d the date to be marshalled 48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param tag the tag for UTC Time or Generalized Time 48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void putTime(Date d, byte tag) throws IOException { 48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Format the date. 49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski TimeZone tz = TimeZone.getTimeZone("GMT"); 49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String pattern = null; 49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag == DerValue.tag_UtcTime) { 49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pattern = "yyMMddHHmmss'Z'"; 49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tag = DerValue.tag_GeneralizedTime; 50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pattern = "yyyyMMddHHmmss'Z'"; 50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.US); 50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sdf.setTimeZone(tz); 50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] time = (sdf.format(d)).getBytes("ISO-8859-1"); 50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Write the formatted date. 50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(tag); 51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski putLength(time.length); 51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(time); 51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Put the encoding of the length in the stream. 51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @params len the length of the attribute. 52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException on writing errors. 52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putLength(int len) throws IOException { 52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len < 128) { 52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)len); 52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (len < (1 << 8)) { 52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)0x081); 52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)len); 52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (len < (1 << 16)) { 53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)0x082); 53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)(len >> 8)); 53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)len); 53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (len < (1 << 24)) { 53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)0x083); 53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)(len >> 16)); 53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)(len >> 8)); 53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)len); 54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)0x084); 54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)(len >> 24)); 54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)(len >> 16)); 54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)(len >> 8)); 54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write((byte)len); 54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Put the tag of the attribute in the stream. 55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @params class the tag class type, one of UNIVERSAL, CONTEXT, 55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * APPLICATION or PRIVATE 55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @params form if true, the value is constructed, otherwise it is 55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * primitive. 55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @params val the tag value 55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void putTag(byte tagClass, boolean form, byte val) { 56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte tag = (byte)(tagClass | val); 56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (form) { 56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tag |= (byte)0x20; 56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski write(tag); 56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Write the current contents of this <code>DerOutputStream</code> 56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to an <code>OutputStream</code>. 57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException on output error. 57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void derEncode(OutputStream out) throws IOException { 57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out.write(toByteArray()); 57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 577