| package org.bouncycastle.asn1; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.OutputStream; |
| |
| /** |
| * Basic class for streaming DER encoding generators. |
| */ |
| public abstract class DERGenerator |
| extends ASN1Generator |
| { |
| private boolean _tagged = false; |
| private boolean _isExplicit; |
| private int _tagNo; |
| |
| protected DERGenerator( |
| OutputStream out) |
| { |
| super(out); |
| } |
| |
| /** |
| * Create a DER encoding generator for a tagged object. |
| * |
| * @param out the output stream to encode objects to. |
| * @param tagNo the tag number to head the output stream with. |
| * @param isExplicit true if the tagging should be explicit, false otherwise. |
| */ |
| public DERGenerator( |
| OutputStream out, |
| int tagNo, |
| boolean isExplicit) |
| { |
| super(out); |
| |
| _tagged = true; |
| _isExplicit = isExplicit; |
| _tagNo = tagNo; |
| } |
| |
| private void writeLength( |
| OutputStream out, |
| int length) |
| throws IOException |
| { |
| if (length > 127) |
| { |
| int size = 1; |
| int val = length; |
| |
| while ((val >>>= 8) != 0) |
| { |
| size++; |
| } |
| |
| out.write((byte)(size | 0x80)); |
| |
| for (int i = (size - 1) * 8; i >= 0; i -= 8) |
| { |
| out.write((byte)(length >> i)); |
| } |
| } |
| else |
| { |
| out.write((byte)length); |
| } |
| } |
| |
| void writeDEREncoded( |
| OutputStream out, |
| int tag, |
| byte[] bytes) |
| throws IOException |
| { |
| out.write(tag); |
| writeLength(out, bytes.length); |
| out.write(bytes); |
| } |
| |
| void writeDEREncoded( |
| int tag, |
| byte[] bytes) |
| throws IOException |
| { |
| if (_tagged) |
| { |
| int tagNum = _tagNo | BERTags.TAGGED; |
| |
| if (_isExplicit) |
| { |
| int newTag = _tagNo | BERTags.CONSTRUCTED | BERTags.TAGGED; |
| |
| ByteArrayOutputStream bOut = new ByteArrayOutputStream(); |
| |
| writeDEREncoded(bOut, tag, bytes); |
| |
| writeDEREncoded(_out, newTag, bOut.toByteArray()); |
| } |
| else |
| { |
| if ((tag & BERTags.CONSTRUCTED) != 0) |
| { |
| writeDEREncoded(_out, tagNum | BERTags.CONSTRUCTED, bytes); |
| } |
| else |
| { |
| writeDEREncoded(_out, tagNum, bytes); |
| } |
| } |
| } |
| else |
| { |
| writeDEREncoded(_out, tag, bytes); |
| } |
| } |
| } |