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}