278 lines
7.5 KiB
C#
278 lines
7.5 KiB
C#
using System.IO;
|
|
|
|
namespace GostCryptography.Asn1.Ber
|
|
{
|
|
public class Asn1BerOutputStream : Asn1OutputStream
|
|
{
|
|
private static readonly byte[] Eoc = new byte[2];
|
|
|
|
public Asn1BerOutputStream(Stream outputStream)
|
|
: base(new BufferedStream(outputStream))
|
|
{
|
|
}
|
|
|
|
public Asn1BerOutputStream(Stream outputStream, int bufSize)
|
|
: base((bufSize == 0) ? outputStream : new BufferedStream(outputStream, bufSize))
|
|
{
|
|
}
|
|
|
|
public virtual void Encode(Asn1Type type, bool explicitTagging)
|
|
{
|
|
type.Encode(this, explicitTagging);
|
|
}
|
|
|
|
public virtual void EncodeBitString(byte[] data, int numbits, bool explicitTagging, Asn1Tag tag)
|
|
{
|
|
if (explicitTagging)
|
|
{
|
|
EncodeTag(tag);
|
|
}
|
|
|
|
var count = (numbits + 7) / 8;
|
|
EncodeLength(count + 1);
|
|
|
|
var num2 = numbits % 8;
|
|
|
|
if (num2 != 0)
|
|
{
|
|
num2 = 8 - num2;
|
|
data[count - 1] = (byte)(data[count - 1] & ((byte)~((1 << num2) - 1)));
|
|
}
|
|
|
|
OutputStream.WriteByte((byte)num2);
|
|
|
|
if (count > 0)
|
|
{
|
|
OutputStream.Write(data, 0, count);
|
|
}
|
|
}
|
|
|
|
public virtual void EncodeBmpString(string data, bool explicitTagging, Asn1Tag tag)
|
|
{
|
|
if (explicitTagging)
|
|
{
|
|
EncodeTag(tag);
|
|
}
|
|
|
|
if (data == null)
|
|
{
|
|
EncodeLength(0);
|
|
}
|
|
else
|
|
{
|
|
EncodeLength(data.Length * 2);
|
|
|
|
var length = data.Length;
|
|
|
|
for (var i = 0; i < length; i++)
|
|
{
|
|
var num3 = data[i];
|
|
var num2 = num3 / 0x100;
|
|
var num = num3 % 0x100;
|
|
|
|
OutputStream.WriteByte((byte)num2);
|
|
OutputStream.WriteByte((byte)num);
|
|
}
|
|
}
|
|
}
|
|
|
|
public virtual void EncodeCharString(string data, bool explicitTagging, Asn1Tag tag)
|
|
{
|
|
if (explicitTagging)
|
|
{
|
|
EncodeTag(tag);
|
|
}
|
|
|
|
if (data == null)
|
|
{
|
|
EncodeLength(0);
|
|
}
|
|
else
|
|
{
|
|
EncodeLength(data.Length);
|
|
var buffer = Asn1Util.ToByteArray(data);
|
|
OutputStream.Write(buffer, 0, buffer.Length);
|
|
}
|
|
}
|
|
|
|
public virtual void EncodeEoc()
|
|
{
|
|
OutputStream.Write(Eoc, 0, Eoc.Length);
|
|
}
|
|
|
|
public virtual void EncodeIdentifier(long ident)
|
|
{
|
|
var number = 0x7fL;
|
|
var identBytesCount = Asn1RunTime.GetIdentBytesCount(ident);
|
|
|
|
number = number << (7 * identBytesCount);
|
|
|
|
if (identBytesCount > 0)
|
|
{
|
|
while (identBytesCount > 0)
|
|
{
|
|
number = Asn1Util.UrShift(number, 7);
|
|
identBytesCount--;
|
|
|
|
var num3 = Asn1Util.UrShift(ident & number, identBytesCount * 7);
|
|
|
|
if (identBytesCount != 0)
|
|
{
|
|
num3 |= 0x80L;
|
|
}
|
|
|
|
OutputStream.WriteByte((byte)num3);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OutputStream.WriteByte(0);
|
|
}
|
|
}
|
|
|
|
public virtual void EncodeIntValue(long data, bool encodeLen)
|
|
{
|
|
long num2;
|
|
var num = data;
|
|
var buffer = new byte[9];
|
|
var len = 0;
|
|
var length = buffer.Length;
|
|
|
|
do
|
|
{
|
|
num2 = num % 0x100L;
|
|
num /= 0x100L;
|
|
|
|
if ((num < 0L) && (num2 != 0L))
|
|
{
|
|
num -= 1L;
|
|
}
|
|
|
|
buffer[--length] = (byte)num2;
|
|
len++;
|
|
}
|
|
while ((num != 0L) && (num != -1L));
|
|
|
|
if ((data > 0L) && ((num2 & 0x80L) == 0x80L))
|
|
{
|
|
buffer[--length] = 0;
|
|
len++;
|
|
}
|
|
else if ((data < 0L) && ((num2 & 0x80L) == 0L))
|
|
{
|
|
buffer[--length] = 0xff;
|
|
len++;
|
|
}
|
|
|
|
if (encodeLen)
|
|
{
|
|
EncodeLength(len);
|
|
}
|
|
|
|
OutputStream.Write(buffer, length, len);
|
|
}
|
|
|
|
public virtual void EncodeLength(int len)
|
|
{
|
|
if (len >= 0)
|
|
{
|
|
var bytesCount = Asn1Util.GetBytesCount(len);
|
|
|
|
if (len > 0x7f)
|
|
{
|
|
OutputStream.WriteByte((byte)(bytesCount | 0x80));
|
|
}
|
|
for (var i = (8 * bytesCount) - 8; i >= 0; i -= 8)
|
|
{
|
|
var num3 = (byte)((len >> i) & 0xff);
|
|
OutputStream.WriteByte(num3);
|
|
}
|
|
}
|
|
else if (len == Asn1Status.IndefiniteLength)
|
|
{
|
|
OutputStream.WriteByte(0x80);
|
|
}
|
|
}
|
|
|
|
public virtual void EncodeOctetString(byte[] data, bool explicitTagging, Asn1Tag tag)
|
|
{
|
|
if (explicitTagging)
|
|
{
|
|
EncodeTag(tag);
|
|
}
|
|
if (data == null)
|
|
{
|
|
EncodeLength(0);
|
|
}
|
|
else
|
|
{
|
|
EncodeLength(data.Length);
|
|
OutputStream.Write(data, 0, data.Length);
|
|
}
|
|
}
|
|
|
|
public virtual void EncodeTag(Asn1Tag tag)
|
|
{
|
|
var num = (byte)(((byte)tag.Class) | ((byte)tag.Form));
|
|
if (tag.IdCode < 0x1f)
|
|
{
|
|
OutputStream.WriteByte((byte)(num | tag.IdCode));
|
|
}
|
|
else
|
|
{
|
|
OutputStream.WriteByte((byte)(num | 0x1f));
|
|
EncodeIdentifier(tag.IdCode);
|
|
}
|
|
}
|
|
|
|
public virtual void EncodeTag(short tagClass, short tagForm, int tagIdCode)
|
|
{
|
|
EncodeTag(new Asn1Tag(tagClass, tagForm, tagIdCode));
|
|
}
|
|
|
|
public virtual void EncodeTagAndIndefLen(Asn1Tag tag)
|
|
{
|
|
EncodeTag(tag);
|
|
OutputStream.WriteByte(0x80);
|
|
}
|
|
|
|
public virtual void EncodeTagAndIndefLen(short tagClass, short tagForm, int tagIdCode)
|
|
{
|
|
EncodeTag(new Asn1Tag(tagClass, tagForm, tagIdCode));
|
|
OutputStream.WriteByte(0x80);
|
|
}
|
|
|
|
public virtual void EncodeTagAndLength(Asn1Tag tag, int len)
|
|
{
|
|
EncodeTag(tag);
|
|
EncodeLength(len);
|
|
}
|
|
|
|
public virtual void EncodeUnivString(int[] data, bool explicitTagging, Asn1Tag tag)
|
|
{
|
|
if (explicitTagging)
|
|
{
|
|
EncodeTag(tag);
|
|
}
|
|
if (data == null)
|
|
{
|
|
EncodeLength(0);
|
|
}
|
|
else
|
|
{
|
|
EncodeLength(data.Length * 4);
|
|
var length = data.Length;
|
|
|
|
for (var i = 0; i < length; ++i)
|
|
{
|
|
var number = data[i];
|
|
OutputStream.WriteByte((byte)(Asn1Util.UrShift(number, 0x18) & 0xff));
|
|
OutputStream.WriteByte((byte)(Asn1Util.UrShift(number, 0x10) & 0xff));
|
|
OutputStream.WriteByte((byte)(Asn1Util.UrShift(number, 8) & 0xff));
|
|
OutputStream.WriteByte((byte)(number & 0xff));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|