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