    001package org.apache.commons.ssl.asn1;
    002
    003import java.io.ByteArrayOutputStream;
    004import java.io.IOException;
    005import java.io.InputStream;
    006import java.io.OutputStream;
    007
    008public abstract class DERGenerator
    009    extends ASN1Generator {
    010    private boolean _tagged = false;
    011    private boolean _isExplicit;
    012    private int _tagNo;
    013
    014    protected DERGenerator(
    015        OutputStream out) {
    016        super(out);
    017    }
    018
    019    public DERGenerator(
    020        OutputStream out,
    021        int tagNo,
    022        boolean isExplicit) {
    023        super(out);
    024
    025        _tagged = true;
    026        _isExplicit = isExplicit;
    027        _tagNo = tagNo;
    028    }
    029
    030    private void writeLength(
    031        OutputStream out,
    032        int length)
    033        throws IOException {
    034        if (length > 127) {
    035            int size = 1;
    036            int val = length;
    037
    038            while ((val >>>= 8) != 0) {
    039                size++;
    040            }
    041
    042            out.write((byte) (size | 0x80));
    043
    044            for (int i = (size - 1) * 8; i >= 0; i -= 8) {
    045                out.write((byte) (length >> i));
    046            }
    047        } else {
    048            out.write((byte) length);
    049        }
    050    }
    051
    052    void writeDEREncoded(
    053        OutputStream out,
    054        int tag,
    055        byte[] bytes)
    056        throws IOException {
    057        out.write(tag);
    058        writeLength(out, bytes.length);
    059        out.write(bytes);
    060    }
    061
    062    void writeDEREncoded(
    063        int tag,
    064        byte[] bytes)
    065        throws IOException {
    066        if (_tagged) {
    067            int tagNum = _tagNo | DERTags.TAGGED;
    068
    069            if (_isExplicit) {
    070                int newTag = _tagNo | DERTags.CONSTRUCTED | DERTags.TAGGED;
    071
    072                ByteArrayOutputStream bOut = new ByteArrayOutputStream();
    073
    074                writeDEREncoded(bOut, tag, bytes);
    075
    076                writeDEREncoded(_out, newTag, bOut.toByteArray());
    077            } else {
    078                if ((tag & DERTags.CONSTRUCTED) != 0) {
    079                    writeDEREncoded(_out, tagNum | DERTags.CONSTRUCTED, bytes);
    080                } else {
    081                    writeDEREncoded(_out, tagNum, bytes);
    082                }
    083            }
    084        } else {
    085            writeDEREncoded(_out, tag, bytes);
    086        }
    087    }
    088
    089    void writeDEREncoded(
    090        OutputStream out,
    091        int tag,
    092        InputStream in)
    093        throws IOException {
    094        out.write(tag);
    095
    096        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
    097
    098        int b = 0;
    099        while ((b = in.read()) >= 0) {
    100            bOut.write(b);
    101        }
    102
    103        byte[] bytes = bOut.toByteArray();
    104
    105        writeLength(out, bytes.length);
    106        out.write(bytes);
    107    }
    108}