Initial Commit

This commit is contained in:
2023-06-21 12:46:23 -04:00
commit c70248a520
1352 changed files with 336780 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
using System.Collections;
using System.IO;
namespace Org.BouncyCastle.Asn1
{
public abstract class Asn1Generator
{
private Stream _out;
protected Asn1Generator(
Stream outStream)
{
_out = outStream;
}
protected Stream Out
{
get { return _out; }
}
public abstract void AddObject(Asn1Encodable obj);
public abstract Stream GetRawOutputStream();
public abstract void Close();
}
}

View File

@@ -0,0 +1,10 @@
using System;
using System.IO;
namespace Org.BouncyCastle.Asn1
{
[Obsolete("Will be removed")]
public class Asn1ObjectParser
{
}
}

View File

@@ -0,0 +1,10 @@
using System.IO;
namespace Org.BouncyCastle.Asn1
{
public interface Asn1OctetStringParser
: IAsn1Convertible
{
Stream GetOctetStream();
}
}

View File

@@ -0,0 +1,8 @@
namespace Org.BouncyCastle.Asn1
{
public interface Asn1SequenceParser
: IAsn1Convertible
{
IAsn1Convertible ReadObject();
}
}

View File

@@ -0,0 +1,8 @@
namespace Org.BouncyCastle.Asn1
{
public interface Asn1SetParser
: IAsn1Convertible
{
IAsn1Convertible ReadObject();
}
}

View File

@@ -0,0 +1,154 @@
using System;
using System.IO;
namespace Org.BouncyCastle.Asn1
{
public class Asn1StreamParser
{
private readonly Stream _in;
private readonly int _limit;
public Asn1StreamParser(
Stream inStream)
: this(inStream, int.MaxValue)
{
}
public Asn1StreamParser(
Stream inStream,
int limit)
{
if (!inStream.CanRead)
throw new ArgumentException("Expected stream to be readable", "inStream");
this._in = inStream;
this._limit = limit;
}
public Asn1StreamParser(
byte[] encoding)
: this(new MemoryStream(encoding, false), encoding.Length)
{
}
public virtual IAsn1Convertible ReadObject()
{
int tag = _in.ReadByte();
if (tag == -1)
return null;
// turn of looking for "00" while we resolve the tag
Set00Check(false);
//
// calculate tag number
//
int tagNo = 0;
if ((tag & Asn1Tags.Tagged) != 0 || (tag & Asn1Tags.Application) != 0)
{
tagNo = Asn1InputStream.ReadTagNumber(_in, tag);
}
bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
int baseTagNo = tag & ~Asn1Tags.Constructed;
//
// calculate length
//
int length = Asn1InputStream.ReadLength(_in, _limit);
if (length < 0) // indefinite length method
{
if (!isConstructed)
throw new IOException("indefinite length primitive encoding encountered");
IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in);
if ((tag & Asn1Tags.Tagged) != 0)
{
return new BerTaggedObjectParser(tag, tagNo, indIn);
}
Asn1StreamParser sp = new Asn1StreamParser(indIn);
// TODO There are other tags that may be constructed (e.g. BitString)
switch (baseTagNo)
{
case Asn1Tags.OctetString:
return new BerOctetStringParser(sp);
case Asn1Tags.Sequence:
return new BerSequenceParser(sp);
case Asn1Tags.Set:
return new BerSetParser(sp);
default:
throw new IOException("unknown BER object encountered");
}
}
else
{
DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
if ((tag & Asn1Tags.Application) != 0)
{
return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray());
}
if ((tag & Asn1Tags.Tagged) != 0)
{
return new BerTaggedObjectParser(tag, tagNo, defIn);
}
if (isConstructed)
{
// TODO There are other tags that may be constructed (e.g. BitString)
switch (baseTagNo)
{
case Asn1Tags.OctetString:
//
// yes, people actually do this...
//
return new BerOctetStringParser(new Asn1StreamParser(defIn));
case Asn1Tags.Sequence:
return new DerSequenceParser(new Asn1StreamParser(defIn));
case Asn1Tags.Set:
return new DerSetParser(new Asn1StreamParser(defIn));
default:
// TODO Add DerUnknownTagParser class?
return new DerUnknownTag(tag, defIn.ToArray());
}
}
// Some primitive encodings can be handled by parsers too...
switch (baseTagNo)
{
case Asn1Tags.OctetString:
return new DerOctetStringParser(defIn);
}
return Asn1InputStream.CreatePrimitiveDerObject(tag, defIn.ToArray());
}
}
private void Set00Check(
bool enabled)
{
if (_in is IndefiniteLengthInputStream)
{
((IndefiniteLengthInputStream) _in).SetEofOn00(enabled);
}
}
internal Asn1EncodableVector ReadVector()
{
Asn1EncodableVector v = new Asn1EncodableVector();
IAsn1Convertible obj;
while ((obj = ReadObject()) != null)
{
v.Add(obj.ToAsn1Object());
}
return v;
}
}
}

View File

@@ -0,0 +1,10 @@
namespace Org.BouncyCastle.Asn1
{
public interface Asn1TaggedObjectParser
: IAsn1Convertible
{
int TagNo { get; }
IAsn1Convertible GetObjectParser(int tag, bool isExplicit);
}
}

View File

@@ -0,0 +1,78 @@
using System.IO;
namespace Org.BouncyCastle.Asn1
{
public abstract class Asn1Encodable
: IAsn1Convertible
{
public const string Der = "DER";
public const string Ber = "BER";
public byte[] GetEncoded()
{
MemoryStream bOut = new MemoryStream();
Asn1OutputStream aOut = new Asn1OutputStream(bOut);
aOut.WriteObject(this);
return bOut.ToArray();
}
public byte[] GetEncoded(
string encoding)
{
if (encoding.Equals(Der))
{
MemoryStream bOut = new MemoryStream();
DerOutputStream dOut = new DerOutputStream(bOut);
dOut.WriteObject(this);
return bOut.ToArray();
}
return GetEncoded();
}
/**
* Return the DER encoding of the object, null if the DER encoding can not be made.
*
* @return a DER byte array, null otherwise.
*/
public byte[] GetDerEncoded()
{
try
{
return GetEncoded(Der);
}
catch (IOException)
{
return null;
}
}
public sealed override int GetHashCode()
{
return ToAsn1Object().CallAsn1GetHashCode();
}
public sealed override bool Equals(
object obj)
{
if (obj == this)
return true;
IAsn1Convertible other = obj as IAsn1Convertible;
if (other == null)
return false;
Asn1Object o1 = ToAsn1Object();
Asn1Object o2 = other.ToAsn1Object();
return o1 == o2 || o1.CallAsn1Equals(o2);
}
public abstract Asn1Object ToAsn1Object();
}
}

View File

@@ -0,0 +1,76 @@
using System;
using System.Collections;
namespace Org.BouncyCastle.Asn1
{
public class Asn1EncodableVector
: IEnumerable
{
private ArrayList v = new ArrayList();
public static Asn1EncodableVector FromEnumerable(
IEnumerable e)
{
Asn1EncodableVector v = new Asn1EncodableVector();
foreach (Asn1Encodable obj in e)
{
v.Add(obj);
}
return v;
}
// public Asn1EncodableVector()
// {
// }
public Asn1EncodableVector(
params Asn1Encodable[] v)
{
Add(v);
}
// public void Add(
// Asn1Encodable obj)
// {
// v.Add(obj);
// }
public void Add(
params Asn1Encodable[] objs)
{
foreach (Asn1Encodable obj in objs)
{
v.Add(obj);
}
}
public Asn1Encodable this[
int index]
{
get { return (Asn1Encodable) v[index]; }
}
[Obsolete("Use 'object[index]' syntax instead")]
public Asn1Encodable Get(
int index)
{
return this[index];
}
[Obsolete("Use 'Count' property instead")]
public int Size
{
get { return v.Count; }
}
public int Count
{
get { return v.Count; }
}
public IEnumerator GetEnumerator()
{
return v.GetEnumerator();
}
}
}

View File

@@ -0,0 +1,307 @@
using System;
using System.Diagnostics;
using System.IO;
using Org.BouncyCastle.Asn1.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Asn1
{
/**
* a general purpose ASN.1 decoder - note: this class differs from the
* others in that it returns null after it has read the last object in
* the stream. If an ASN.1 Null is encountered a Der/BER Null object is
* returned.
*/
public class Asn1InputStream
: FilterStream
{
private readonly int limit;
public Asn1InputStream(
Stream inputStream)
: this(inputStream, int.MaxValue)
{
}
/**
* Create an ASN1InputStream where no DER object will be longer than limit.
*
* @param input stream containing ASN.1 encoded data.
* @param limit maximum size of a DER encoded object.
*/
public Asn1InputStream(
Stream inputStream,
int limit)
: base(inputStream)
{
this.limit = limit;
}
/**
* Create an ASN1InputStream based on the input byte array. The length of DER objects in
* the stream is automatically limited to the length of the input array.
*
* @param input array containing ASN.1 encoded data.
*/
public Asn1InputStream(
byte[] input)
: this(new MemoryStream(input, false), input.Length)
{
}
internal Asn1EncodableVector BuildEncodableVector()
{
Asn1EncodableVector v = new Asn1EncodableVector();
Asn1Object o;
while ((o = ReadObject()) != null)
{
v.Add(o);
}
return v;
}
internal virtual Asn1EncodableVector BuildDerEncodableVector(
DefiniteLengthInputStream dIn)
{
return new Asn1InputStream(dIn).BuildEncodableVector();
}
internal virtual DerSequence CreateDerSequence(
DefiniteLengthInputStream dIn)
{
return DerSequence.FromVector(BuildDerEncodableVector(dIn));
}
internal virtual DerSet CreateDerSet(
DefiniteLengthInputStream dIn)
{
return DerSet.FromVector(BuildDerEncodableVector(dIn), false);
}
public Asn1Object ReadObject()
{
int tag = ReadByte();
if (tag <= 0)
{
if (tag == 0)
throw new IOException("unexpected end-of-contents marker");
return null;
}
//
// calculate tag number
//
int tagNo = 0;
if ((tag & Asn1Tags.Tagged) != 0 || (tag & Asn1Tags.Application) != 0)
{
tagNo = ReadTagNumber(this, tag);
}
bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
int baseTagNo = tag & ~Asn1Tags.Constructed;
//
// calculate length
//
int length = ReadLength(this, limit);
if (length < 0) // indefinite length method
{
if (!isConstructed)
throw new IOException("indefinite length primitive encoding encountered");
IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this);
if ((tag & Asn1Tags.Tagged) != 0)
{
return new BerTaggedObjectParser(tag, tagNo, indIn).ToAsn1Object();
}
Asn1StreamParser sp = new Asn1StreamParser(indIn);
// TODO There are other tags that may be constructed (e.g. BitString)
switch (baseTagNo)
{
case Asn1Tags.OctetString:
return new BerOctetStringParser(sp).ToAsn1Object();
case Asn1Tags.Sequence:
return new BerSequenceParser(sp).ToAsn1Object();
case Asn1Tags.Set:
return new BerSetParser(sp).ToAsn1Object();
default:
throw new IOException("unknown BER object encountered");
}
}
else
{
DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this, length);
if ((tag & Asn1Tags.Application) != 0)
{
return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray());
}
if ((tag & Asn1Tags.Tagged) != 0)
{
return new BerTaggedObjectParser(tag, tagNo, defIn).ToAsn1Object();
}
if (isConstructed)
{
// TODO There are other tags that may be constructed (e.g. BitString)
switch (baseTagNo)
{
case Asn1Tags.OctetString:
//
// yes, people actually do this...
//
return new BerOctetString(BuildDerEncodableVector(defIn));
case Asn1Tags.Sequence:
return CreateDerSequence(defIn);
case Asn1Tags.Set:
return CreateDerSet(defIn);
default:
return new DerUnknownTag(tag, defIn.ToArray());
}
}
return CreatePrimitiveDerObject(tag, defIn.ToArray());
}
}
internal static int ReadTagNumber(
Stream s,
int tag)
{
int tagNo = tag & 0x1f;
//
// with tagged object tag number is bottom 5 bits, or stored at the start of the content
//
if (tagNo == 0x1f)
{
tagNo = 0;
int b = s.ReadByte();
// X.690-0207 8.1.2.4.2
// "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
if ((b & 0x7f) == 0) // Note: -1 will pass
{
throw new IOException("corrupted stream - invalid high tag number found");
}
while ((b >= 0) && ((b & 0x80) != 0))
{
tagNo |= (b & 0x7f);
tagNo <<= 7;
b = s.ReadByte();
}
if (b < 0)
throw new EndOfStreamException("EOF found inside tag value.");
tagNo |= (b & 0x7f);
}
return tagNo;
}
internal static int ReadLength(
Stream s,
int limit)
{
int length = s.ReadByte();
if (length < 0)
throw new EndOfStreamException("EOF found when length expected");
if (length == 0x80)
return -1; // indefinite-length encoding
if (length > 127)
{
int size = length & 0x7f;
if (size > 4)
throw new IOException("DER length more than 4 bytes");
length = 0;
for (int i = 0; i < size; i++)
{
int next = s.ReadByte();
if (next < 0)
throw new EndOfStreamException("EOF found reading length");
length = (length << 8) + next;
}
if (length < 0)
throw new IOException("Corrupted stream - negative length found");
if (length >= limit) // after all we must have read at least 1 byte
throw new IOException("Corrupted stream - out of bounds length found");
}
return length;
}
internal static Asn1Object CreatePrimitiveDerObject(
int tag,
byte[] bytes)
{
Debug.Assert((tag & (Asn1Tags.Application | Asn1Tags.Constructed | Asn1Tags.Tagged)) == 0);
switch (tag)
{
case Asn1Tags.BitString:
{
int padBits = bytes[0];
byte[] data = new byte[bytes.Length - 1];
Array.Copy(bytes, 1, data, 0, bytes.Length - 1);
return new DerBitString(data, padBits);
}
case Asn1Tags.BmpString:
return new DerBmpString(bytes);
case Asn1Tags.Boolean:
return new DerBoolean(bytes);
case Asn1Tags.Enumerated:
return new DerEnumerated(bytes);
case Asn1Tags.GeneralizedTime:
return new DerGeneralizedTime(bytes);
case Asn1Tags.GeneralString:
return new DerGeneralString(bytes);
case Asn1Tags.IA5String:
return new DerIA5String(bytes);
case Asn1Tags.Integer:
return new DerInteger(bytes);
case Asn1Tags.Null:
return DerNull.Instance; // actual content is ignored (enforce 0 length?)
case Asn1Tags.NumericString:
return new DerNumericString(bytes);
case Asn1Tags.ObjectIdentifier:
return new DerObjectIdentifier(bytes);
case Asn1Tags.OctetString:
return new DerOctetString(bytes);
case Asn1Tags.PrintableString:
return new DerPrintableString(bytes);
case Asn1Tags.T61String:
return new DerT61String(bytes);
case Asn1Tags.UniversalString:
return new DerUniversalString(bytes);
case Asn1Tags.UtcTime:
return new DerUtcTime(bytes);
case Asn1Tags.Utf8String:
return new DerUtf8String(bytes);
case Asn1Tags.VisibleString:
return new DerVisibleString(bytes);
default:
return new DerUnknownTag(tag, bytes);
}
}
}
}

View File

@@ -0,0 +1,18 @@
namespace Org.BouncyCastle.Asn1
{
/**
* A Null object.
*/
public abstract class Asn1Null
: Asn1Object
{
internal Asn1Null()
{
}
public override string ToString()
{
return "NULL";
}
}
}

View File

@@ -0,0 +1,48 @@
using System.IO;
namespace Org.BouncyCastle.Asn1
{
public abstract class Asn1Object
: Asn1Encodable
{
/// <summary>Create a base ASN.1 object from a byte array.</summary>
/// <param name="data">The byte array to parse.</param>
/// <returns>The base ASN.1 object represented by the byte array.</returns>
/// <exception cref="IOException">If there is a problem parsing the data.</exception>
public static Asn1Object FromByteArray(
byte[] data)
{
return new Asn1InputStream(data).ReadObject();
}
/// <summary>Read a base ASN.1 object from a stream.</summary>
/// <param name="inStr">The stream to parse.</param>
/// <returns>The base ASN.1 object represented by the byte array.</returns>
/// <exception cref="IOException">If there is a problem parsing the data.</exception>
public static Asn1Object FromStream(
Stream inStr)
{
return new Asn1InputStream(inStr).ReadObject();
}
public sealed override Asn1Object ToAsn1Object()
{
return this;
}
internal abstract void Encode(DerOutputStream derOut);
protected abstract bool Asn1Equals(Asn1Object asn1Object);
protected abstract int Asn1GetHashCode();
internal bool CallAsn1Equals(Asn1Object obj)
{
return Asn1Equals(obj);
}
internal int CallAsn1GetHashCode()
{
return Asn1GetHashCode();
}
}
}

View File

@@ -0,0 +1,128 @@
using System;
using System.Collections;
using System.IO;
using System.Text;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
namespace Org.BouncyCastle.Asn1
{
public abstract class Asn1OctetString
: Asn1Object, Asn1OctetStringParser
{
internal byte[] str;
/**
* return an Octet string from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static Asn1OctetString GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
/**
* return an Octet string from the given object.
*
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static Asn1OctetString GetInstance(
object obj)
{
if (obj == null || obj is Asn1OctetString)
{
return (Asn1OctetString)obj;
}
if (obj is Asn1TaggedObject)
{
return GetInstance(((Asn1TaggedObject)obj).GetObject());
}
if (obj is Asn1Sequence)
{
ArrayList v = new ArrayList();
foreach (object o in ((Asn1Sequence) obj))
{
v.Add(o);
}
return new BerOctetString(v);
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* @param string the octets making up the octet string.
*/
internal Asn1OctetString(
byte[] str)
{
if (str == null)
throw new ArgumentNullException("str");
this.str = str;
}
internal Asn1OctetString(
Asn1Encodable obj)
{
try
{
this.str = obj.GetDerEncoded();
}
catch (IOException e)
{
throw new ArgumentException("Error processing object : " + e.ToString());
}
}
public Stream GetOctetStream()
{
return new MemoryStream(str, false);
}
public Asn1OctetStringParser Parser
{
get { return this; }
}
public virtual byte[] GetOctets()
{
return str;
}
protected override int Asn1GetHashCode()
{
return Arrays.GetHashCode(GetOctets());
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerOctetString other = asn1Object as DerOctetString;
if (other == null)
return false;
return Arrays.AreEqual(GetOctets(), other.GetOctets());
}
public override string ToString()
{
byte[] hex = Hex.Encode(str);
return "#" + Encoding.ASCII.GetString(hex, 0, hex.Length);
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.IO;
namespace Org.BouncyCastle.Asn1
{
public class Asn1OutputStream
: DerOutputStream
{
public Asn1OutputStream(Stream os) : base(os)
{
}
[Obsolete("Use version taking an Asn1Encodable arg instead")]
public override void WriteObject(
object obj)
{
if (obj == null)
{
WriteNull();
}
else if (obj is Asn1Object)
{
((Asn1Object)obj).Encode(this);
}
else if (obj is Asn1Encodable)
{
((Asn1Encodable)obj).ToAsn1Object().Encode(this);
}
else
{
throw new IOException("object not Asn1Encodable");
}
}
}
}

View File

@@ -0,0 +1,231 @@
using System;
using System.Collections;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Asn1
{
public abstract class Asn1Sequence
: Asn1Object, IEnumerable
{
private readonly ArrayList seq;
/**
* return an Asn1Sequence from the given object.
*
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static Asn1Sequence GetInstance(
object obj)
{
if (obj == null || obj is Asn1Sequence)
{
return (Asn1Sequence)obj;
}
throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
}
/**
* Return an ASN1 sequence from a tagged object. There is a special
* case here, if an object appears to have been explicitly tagged on
* reading but we were expecting it to be implicitly tagged in the
* normal course of events it indicates that we lost the surrounding
* sequence - so we need to add it back (this will happen if the tagged
* object is a sequence that contains other sequences). If you are
* dealing with implicitly tagged sequences you really <b>should</b>
* be using this method.
*
* @param obj the tagged object.
* @param explicitly true if the object is meant to be explicitly tagged,
* false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static Asn1Sequence GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
Asn1Object inner = obj.GetObject();
if (explicitly)
{
if (!obj.IsExplicit())
throw new ArgumentException("object implicit - explicit expected.");
return (Asn1Sequence) inner;
}
//
// constructed object which appears to be explicitly tagged
// when it should be implicit means we have to add the
// surrounding sequence.
//
if (obj.IsExplicit())
{
if (obj is BerTaggedObject)
{
return new BerSequence(inner);
}
return new DerSequence(inner);
}
if (inner is Asn1Sequence)
{
return (Asn1Sequence) inner;
}
throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
}
protected internal Asn1Sequence(
int capacity)
{
seq = new ArrayList(capacity);
}
public virtual IEnumerator GetEnumerator()
{
return seq.GetEnumerator();
}
[Obsolete("Use GetEnumerator() instead")]
public IEnumerator GetObjects()
{
return GetEnumerator();
}
private class Asn1SequenceParserImpl
: Asn1SequenceParser
{
private readonly Asn1Sequence outer;
private readonly int max;
private int index;
public Asn1SequenceParserImpl(
Asn1Sequence outer)
{
this.outer = outer;
this.max = outer.Count;
}
public IAsn1Convertible ReadObject()
{
if (index == max)
return null;
Asn1Encodable obj = outer[index++];
if (obj is Asn1Sequence)
return ((Asn1Sequence)obj).Parser;
if (obj is Asn1Set)
return ((Asn1Set)obj).Parser;
// NB: Asn1OctetString implements Asn1OctetStringParser directly
// if (obj is Asn1OctetString)
// return ((Asn1OctetString)obj).Parser;
return obj;
}
public Asn1Object ToAsn1Object()
{
return outer;
}
}
public virtual Asn1SequenceParser Parser
{
get { return new Asn1SequenceParserImpl(this); }
}
/**
* return the object at the sequence position indicated by index.
*
* @param index the sequence number (starting at zero) of the object
* @return the object at the sequence position indicated by index.
*/
public virtual Asn1Encodable this[int index]
{
get { return (Asn1Encodable) seq[index]; }
}
[Obsolete("Use 'object[index]' syntax instead")]
public Asn1Encodable GetObjectAt(
int index)
{
return this[index];
}
[Obsolete("Use 'Count' property instead")]
public int Size
{
get { return Count; }
}
public virtual int Count
{
get { return seq.Count; }
}
protected override int Asn1GetHashCode()
{
int hc = Count;
foreach (object o in this)
{
hc *= 17;
if (o != null)
{
hc ^= o.GetHashCode();
}
}
return hc;
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
Asn1Sequence other = asn1Object as Asn1Sequence;
if (other == null)
return false;
if (Count != other.Count)
{
return false;
}
IEnumerator s1 = GetEnumerator();
IEnumerator s2 = other.GetEnumerator();
while (s1.MoveNext() && s2.MoveNext())
{
// if (!Platform.Equals(s1.Current, s2.Current))
Asn1Object o1 = ((Asn1Encodable) s1.Current).ToAsn1Object();
if (!o1.Equals(s2.Current))
{
return false;
}
}
return true;
}
protected internal void AddObject(
Asn1Encodable obj)
{
seq.Add(obj);
}
public override string ToString()
{
return CollectionUtilities.ToString(seq);
}
}
}

View File

@@ -0,0 +1,307 @@
using System;
using System.Collections;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Asn1
{
abstract public class Asn1Set
: Asn1Object, IEnumerable
{
private readonly ArrayList _set;
/**
* return an ASN1Set from the given object.
*
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static Asn1Set GetInstance(
object obj)
{
if (obj == null || obj is Asn1Set)
{
return (Asn1Set)obj;
}
throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
}
/**
* Return an ASN1 set from a tagged object. There is a special
* case here, if an object appears to have been explicitly tagged on
* reading but we were expecting it to be implicitly tagged in the
* normal course of events it indicates that we lost the surrounding
* set - so we need to add it back (this will happen if the tagged
* object is a sequence that contains other sequences). If you are
* dealing with implicitly tagged sets you really <b>should</b>
* be using this method.
*
* @param obj the tagged object.
* @param explicitly true if the object is meant to be explicitly tagged
* false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static Asn1Set GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
Asn1Object inner = obj.GetObject();
if (explicitly)
{
if (!obj.IsExplicit())
throw new ArgumentException("object implicit - explicit expected.");
return (Asn1Set) inner;
}
//
// constructed object which appears to be explicitly tagged
// and it's really implicit means we have to add the
// surrounding sequence.
//
if (obj.IsExplicit())
{
return new DerSet(inner);
}
if (inner is Asn1Set)
{
return (Asn1Set) inner;
}
//
// in this case the parser returns a sequence, convert it
// into a set.
//
if (inner is Asn1Sequence)
{
Asn1EncodableVector v = new Asn1EncodableVector();
Asn1Sequence s = (Asn1Sequence) inner;
foreach (Asn1Encodable ae in s)
{
v.Add(ae);
}
// TODO Should be able to construct set directly from sequence?
return new DerSet(v, false);
}
throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
}
protected internal Asn1Set(
int capacity)
{
_set = new ArrayList(capacity);
}
public virtual IEnumerator GetEnumerator()
{
return _set.GetEnumerator();
}
[Obsolete("Use GetEnumerator() instead")]
public IEnumerator GetObjects()
{
return GetEnumerator();
}
/**
* return the object at the set position indicated by index.
*
* @param index the set number (starting at zero) of the object
* @return the object at the set position indicated by index.
*/
public virtual Asn1Encodable this[int index]
{
get { return (Asn1Encodable) _set[index]; }
}
[Obsolete("Use 'object[index]' syntax instead")]
public Asn1Encodable GetObjectAt(
int index)
{
return this[index];
}
[Obsolete("Use 'Count' property instead")]
public int Size
{
get { return Count; }
}
public virtual int Count
{
get { return _set.Count; }
}
private class Asn1SetParserImpl
: Asn1SetParser
{
private readonly Asn1Set outer;
private readonly int max;
private int index;
public Asn1SetParserImpl(
Asn1Set outer)
{
this.outer = outer;
this.max = outer.Count;
}
public IAsn1Convertible ReadObject()
{
if (index == max)
return null;
Asn1Encodable obj = outer[index++];
if (obj is Asn1Sequence)
return ((Asn1Sequence)obj).Parser;
if (obj is Asn1Set)
return ((Asn1Set)obj).Parser;
// NB: Asn1OctetString implements Asn1OctetStringParser directly
// if (obj is Asn1OctetString)
// return ((Asn1OctetString)obj).Parser;
return obj;
}
public virtual Asn1Object ToAsn1Object()
{
return outer;
}
}
public Asn1SetParser Parser
{
get { return new Asn1SetParserImpl(this); }
}
protected override int Asn1GetHashCode()
{
int hc = Count;
foreach (object o in this)
{
hc *= 17;
if (o != null)
{
hc ^= o.GetHashCode();
}
}
return hc;
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
Asn1Set other = asn1Object as Asn1Set;
if (other == null)
return false;
if (Count != other.Count)
{
return false;
}
IEnumerator s1 = GetEnumerator();
IEnumerator s2 = other.GetEnumerator();
while (s1.MoveNext() && s2.MoveNext())
{
// if (!Platform.Equals(s1.Current, s2.Current))
Asn1Object o1 = ((Asn1Encodable) s1.Current).ToAsn1Object();
if (!o1.Equals(s2.Current))
{
return false;
}
}
return true;
}
/**
* return true if a &lt;= b (arrays are assumed padded with zeros).
*/
private bool LessThanOrEqual(
byte[] a,
byte[] b)
{
int cmpLen = System.Math.Min(a.Length, b.Length);
for (int i = 0; i < cmpLen; ++i)
{
byte l = a[i];
byte r = b[i];
if (l != r)
{
return r > l ? true : false;
}
}
return a.Length <= b.Length;
}
protected internal void Sort()
{
if (_set.Count > 1)
{
bool swapped = true;
int lastSwap = _set.Count - 1;
while (swapped)
{
int index = 0;
int swapIndex = 0;
byte[] a = ((Asn1Encodable) _set[0]).GetEncoded();
swapped = false;
while (index != lastSwap)
{
byte[] b = ((Asn1Encodable) _set[index + 1]).GetEncoded();
if (LessThanOrEqual(a, b))
{
a = b;
}
else
{
object o = _set[index];
_set[index] = _set[index + 1];
_set[index + 1] = o;
swapped = true;
swapIndex = index;
}
index++;
}
lastSwap = swapIndex;
}
}
}
protected internal void AddObject(
Asn1Encodable obj)
{
_set.Add(obj);
}
public override string ToString()
{
return CollectionUtilities.ToString(_set);
}
}
}

View File

@@ -0,0 +1,177 @@
using System;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
/**
* ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
* a [n] where n is some number - these are assumed to follow the construction
* rules (as with sequences).
*/
public abstract class Asn1TaggedObject
: Asn1Object, Asn1TaggedObjectParser
{
internal int tagNo;
// internal bool empty;
internal bool explicitly = true;
internal Asn1Encodable obj;
static public Asn1TaggedObject GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
if (explicitly)
{
return (Asn1TaggedObject) obj.GetObject();
}
throw new ArgumentException("implicitly tagged tagged object");
}
static public Asn1TaggedObject GetInstance(
object obj)
{
if (obj == null || obj is Asn1TaggedObject)
{
return (Asn1TaggedObject) obj;
}
throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
}
/**
* @param tagNo the tag number for this object.
* @param obj the tagged object.
*/
protected Asn1TaggedObject(
int tagNo,
Asn1Encodable obj)
{
this.explicitly = true;
this.tagNo = tagNo;
this.obj = obj;
}
/**
* @param explicitly true if the object is explicitly tagged.
* @param tagNo the tag number for this object.
* @param obj the tagged object.
*/
protected Asn1TaggedObject(
bool explicitly,
int tagNo,
Asn1Encodable obj)
{
this.explicitly = explicitly;
this.tagNo = tagNo;
this.obj = obj;
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
Asn1TaggedObject other = asn1Object as Asn1TaggedObject;
if (other == null)
return false;
return this.tagNo == other.tagNo
// && this.empty == other.empty
&& this.explicitly == other.explicitly // TODO Should this be part of equality?
&& Platform.Equals(GetObject(), other.GetObject());
}
protected override int Asn1GetHashCode()
{
int code = tagNo.GetHashCode();
// TODO: actually this is wrong - the problem is that a re-encoded
// object may end up with a different hashCode due to implicit
// tagging. As implicit tagging is ambiguous if a sequence is involved
// it seems the only correct method for both equals and hashCode is to
// compare the encodings...
// code ^= explicitly.GetHashCode();
if (obj != null)
{
code ^= obj.GetHashCode();
}
return code;
}
public int TagNo
{
get { return tagNo; }
}
/**
* return whether or not the object may be explicitly tagged.
* <p>
* Note: if the object has been read from an input stream, the only
* time you can be sure if isExplicit is returning the true state of
* affairs is if it returns false. An implicitly tagged object may appear
* to be explicitly tagged, so you need to understand the context under
* which the reading was done as well, see GetObject below.</p>
*/
public bool IsExplicit()
{
return explicitly;
}
public bool IsEmpty()
{
return false; //empty;
}
/**
* return whatever was following the tag.
* <p>
* Note: tagged objects are generally context dependent if you're
* trying to extract a tagged object you should be going via the
* appropriate GetInstance method.</p>
*/
public Asn1Object GetObject()
{
if (obj != null)
{
return obj.ToAsn1Object();
}
return null;
}
/**
* Return the object held in this tagged object as a parser assuming it has
* the type of the passed in tag. If the object doesn't have a parser
* associated with it, the base object is returned.
*/
public IAsn1Convertible GetObjectParser(
int tag,
bool isExplicit)
{
switch (tag)
{
case Asn1Tags.Set:
return Asn1Set.GetInstance(this, isExplicit).Parser;
case Asn1Tags.Sequence:
return Asn1Sequence.GetInstance(this, isExplicit).Parser;
case Asn1Tags.OctetString:
return Asn1OctetString.GetInstance(this, isExplicit).Parser;
}
if (isExplicit)
{
return GetObject();
}
throw Platform.CreateNotImplementedException("implicit tagging for tag: " + tag);
}
public override string ToString()
{
return "[" + tagNo + "]" + obj;
}
}
}

View File

@@ -0,0 +1,36 @@
namespace Org.BouncyCastle.Asn1
{
public class Asn1Tags
{
public const int Boolean = 0x01;
public const int Integer = 0x02;
public const int BitString = 0x03;
public const int OctetString = 0x04;
public const int Null = 0x05;
public const int ObjectIdentifier = 0x06;
public const int External = 0x08;
public const int Enumerated = 0x0a;
public const int Sequence = 0x10;
public const int SequenceOf = 0x10; // for completeness
public const int Set = 0x11;
public const int SetOf = 0x11; // for completeness
public const int NumericString = 0x12;
public const int PrintableString = 0x13;
public const int T61String = 0x14;
public const int VideotexString = 0x15;
public const int IA5String = 0x16;
public const int UtcTime = 0x17;
public const int GeneralizedTime = 0x18;
public const int GraphicString = 0x19;
public const int VisibleString = 0x1a;
public const int GeneralString = 0x1b;
public const int UniversalString = 0x1c;
public const int BmpString = 0x1e;
public const int Utf8String = 0x0c;
public const int Constructed = 0x20;
public const int Application = 0x40;
public const int Tagged = 0x80;
}
}

View File

@@ -0,0 +1,102 @@
using System.IO;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Asn1
{
public class BerGenerator
: Asn1Generator
{
private bool _tagged = false;
private bool _isExplicit;
private int _tagNo;
protected BerGenerator(
Stream outStream)
: base(outStream)
{
}
public BerGenerator(
Stream outStream,
int tagNo,
bool isExplicit)
: base(outStream)
{
_tagged = true;
_isExplicit = isExplicit;
_tagNo = tagNo;
}
public override void AddObject(
Asn1Encodable obj)
{
new BerOutputStream(Out).WriteObject(obj);
}
public override Stream GetRawOutputStream()
{
return Out;
}
public override void Close()
{
WriteBerEnd();
}
private void WriteHdr(
int tag)
{
Out.WriteByte((byte) tag);
Out.WriteByte(0x80);
}
protected void WriteBerHeader(
int tag)
{
if (_tagged)
{
int tagNum = _tagNo | Asn1Tags.Tagged;
if (_isExplicit)
{
WriteHdr(tagNum | Asn1Tags.Constructed);
WriteHdr(tag);
}
else
{
if ((tag & Asn1Tags.Constructed) != 0)
{
WriteHdr(tagNum | Asn1Tags.Constructed);
}
else
{
WriteHdr(tagNum);
}
}
}
else
{
WriteHdr(tag);
}
}
protected void WriteBerBody(
Stream contentStream)
{
Streams.PipeAll(contentStream, Out);
}
protected void WriteBerEnd()
{
Out.WriteByte(0x00);
Out.WriteByte(0x00);
if (_tagged && _isExplicit) // write extra end for tag header
{
Out.WriteByte(0x00);
Out.WriteByte(0x00);
}
}
}
}

View File

@@ -0,0 +1,117 @@
using System;
using System.IO;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Asn1
{
public class BerOctetStringGenerator
: BerGenerator
{
public BerOctetStringGenerator(Stream outStream)
: base(outStream)
{
WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
}
public BerOctetStringGenerator(
Stream outStream,
int tagNo,
bool isExplicit)
: base(outStream, tagNo, isExplicit)
{
WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
}
public Stream GetOctetOutputStream()
{
return GetOctetOutputStream(new byte[1000]); // limit for CER encoding.
}
public Stream GetOctetOutputStream(
int bufSize)
{
return bufSize < 1
? GetOctetOutputStream()
: GetOctetOutputStream(new byte[bufSize]);
}
public Stream GetOctetOutputStream(
byte[] buf)
{
return new BufferedBerOctetStream(this, buf);
}
private class BufferedBerOctetStream
: BaseOutputStream
{
private byte[] _buf;
private int _off;
private readonly BerOctetStringGenerator _gen;
private readonly DerOutputStream _derOut;
internal BufferedBerOctetStream(
BerOctetStringGenerator gen,
byte[] buf)
{
_gen = gen;
_buf = buf;
_off = 0;
_derOut = new DerOutputStream(_gen.Out);
}
public override void WriteByte(
byte b)
{
_buf[_off++] = b;
if (_off == _buf.Length)
{
DerOctetString.Encode(_derOut, _buf, 0, _off);
_off = 0;
}
}
public override void Write(
byte[] buf,
int offset,
int len)
{
while (len > 0)
{
int numToCopy = System.Math.Min(len, _buf.Length - _off);
if (numToCopy == _buf.Length)
{
DerOctetString.Encode(_derOut, buf, offset, numToCopy);
}
else
{
Array.Copy(buf, offset, _buf, _off, numToCopy);
_off += numToCopy;
if (_off < _buf.Length)
break;
DerOctetString.Encode(_derOut, _buf, 0, _off);
_off = 0;
}
offset += numToCopy;
len -= numToCopy;
}
}
public override void Close()
{
if (_off != 0)
{
DerOctetString.Encode(_derOut, _buf, 0, _off);
}
_gen.WriteBerEnd();
base.Close();
}
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.IO;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Asn1
{
public class BerOctetStringParser
: Asn1OctetStringParser
{
private readonly Asn1StreamParser _parser;
internal BerOctetStringParser(
Asn1StreamParser parser)
{
_parser = parser;
}
public Stream GetOctetStream()
{
return new ConstructedOctetStream(_parser);
}
public Asn1Object ToAsn1Object()
{
try
{
return new BerOctetString(Streams.ReadAll(GetOctetStream()));
}
catch (IOException e)
{
throw new InvalidOperationException("IOException converting stream to byte array: " + e.Message, e);
}
}
}
}

View File

@@ -0,0 +1,24 @@
using System.IO;
namespace Org.BouncyCastle.Asn1
{
public class BerSequenceGenerator
: BerGenerator
{
public BerSequenceGenerator(
Stream outStream)
: base(outStream)
{
WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Sequence);
}
public BerSequenceGenerator(
Stream outStream,
int tagNo,
bool isExplicit)
: base(outStream, tagNo, isExplicit)
{
WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Sequence);
}
}
}

View File

@@ -0,0 +1,24 @@
namespace Org.BouncyCastle.Asn1
{
public class BerSequenceParser
: Asn1SequenceParser
{
private readonly Asn1StreamParser _parser;
internal BerSequenceParser(
Asn1StreamParser parser)
{
this._parser = parser;
}
public IAsn1Convertible ReadObject()
{
return _parser.ReadObject();
}
public Asn1Object ToAsn1Object()
{
return new BerSequence(_parser.ReadVector());
}
}
}

View File

@@ -0,0 +1,24 @@
using System.IO;
namespace Org.BouncyCastle.Asn1
{
public class BerSetGenerator
: BerGenerator
{
public BerSetGenerator(
Stream outStream)
: base(outStream)
{
WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Set);
}
public BerSetGenerator(
Stream outStream,
int tagNo,
bool isExplicit)
: base(outStream, tagNo, isExplicit)
{
WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Set);
}
}
}

View File

@@ -0,0 +1,24 @@
namespace Org.BouncyCastle.Asn1
{
public class BerSetParser
: Asn1SetParser
{
private readonly Asn1StreamParser _parser;
internal BerSetParser(
Asn1StreamParser parser)
{
this._parser = parser;
}
public IAsn1Convertible ReadObject()
{
return _parser.ReadObject();
}
public Asn1Object ToAsn1Object()
{
return new BerSet(_parser.ReadVector(), false);
}
}
}

View File

@@ -0,0 +1,128 @@
using System;
using System.IO;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
public class BerTaggedObjectParser
: Asn1TaggedObjectParser
{
private int _baseTag;
private int _tagNumber;
private Stream _contentStream;
private bool _indefiniteLength;
internal BerTaggedObjectParser(
int baseTag,
int tagNumber,
Stream contentStream)
{
if (!contentStream.CanRead)
throw new ArgumentException("Expected stream to be readable", "contentStream");
_baseTag = baseTag;
_tagNumber = tagNumber;
_contentStream = contentStream;
_indefiniteLength = contentStream is IndefiniteLengthInputStream;
}
public bool IsConstructed
{
get { return (_baseTag & Asn1Tags.Constructed) != 0; }
}
public int TagNo
{
get { return _tagNumber; }
}
public IAsn1Convertible GetObjectParser(
int tag,
bool isExplicit)
{
if (isExplicit)
{
return new Asn1StreamParser(_contentStream).ReadObject();
}
switch (tag)
{
case Asn1Tags.Set:
if (_indefiniteLength)
{
return new BerSetParser(new Asn1StreamParser(_contentStream));
}
else
{
return new DerSetParser(new Asn1StreamParser(_contentStream));
}
case Asn1Tags.Sequence:
if (_indefiniteLength)
{
return new BerSequenceParser(new Asn1StreamParser(_contentStream));
}
else
{
return new DerSequenceParser(new Asn1StreamParser(_contentStream));
}
case Asn1Tags.OctetString:
// TODO Is the handling of definite length constructed encodings correct?
if (_indefiniteLength || IsConstructed)
{
return new BerOctetStringParser(new Asn1StreamParser(_contentStream));
}
else
{
return new DerOctetStringParser((DefiniteLengthInputStream)_contentStream);
}
}
throw Platform.CreateNotImplementedException("implicit tagging");
}
private Asn1EncodableVector rLoadVector(Stream inStream)
{
try
{
return new Asn1StreamParser(inStream).ReadVector();
}
catch (IOException e)
{
throw new InvalidOperationException(e.Message, e);
}
}
public Asn1Object ToAsn1Object()
{
if (_indefiniteLength)
{
Asn1EncodableVector v = rLoadVector(_contentStream);
return v.Count == 1
? new BerTaggedObject(true, _tagNumber, v[0])
: new BerTaggedObject(false, _tagNumber, BerSequence.FromVector(v));
}
if (IsConstructed)
{
Asn1EncodableVector v = rLoadVector(_contentStream);
return v.Count == 1
? new DerTaggedObject(true, _tagNumber, v[0])
: new DerTaggedObject(false, _tagNumber, DerSequence.FromVector(v));
}
try
{
DefiniteLengthInputStream defIn = (DefiniteLengthInputStream) _contentStream;
return new DerTaggedObject(false, _tagNumber, new DerOctetString(defIn.ToArray()));
}
catch (IOException e)
{
throw new InvalidOperationException(e.Message, e);
}
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
namespace Org.BouncyCastle.Asn1
{
/**
* A BER Null object.
*/
public class BerNull
: DerNull
{
public static new readonly BerNull Instance = new BerNull(0);
[Obsolete("Use static Instance object")]
public BerNull()
{
}
private BerNull(int dummy) : base(dummy)
{
}
internal override void Encode(
DerOutputStream derOut)
{
if (derOut is Asn1OutputStream || derOut is BerOutputStream)
{
derOut.WriteByte(Asn1Tags.Null);
}
else
{
base.Encode(derOut);
}
}
}
}

View File

@@ -0,0 +1,150 @@
using System;
using System.Collections;
using System.IO;
namespace Org.BouncyCastle.Asn1
{
public class BerOctetString
: DerOctetString, IEnumerable
{
private const int MaxLength = 1000;
/**
* convert a vector of octet strings into a single byte string
*/
private static byte[] ToBytes(
IEnumerable octs)
{
MemoryStream bOut = new MemoryStream();
foreach (DerOctetString o in octs)
{
byte[] octets = o.GetOctets();
bOut.Write(octets, 0, octets.Length);
}
return bOut.ToArray();
}
private readonly IEnumerable octs;
/// <param name="str">The octets making up the octet string.</param>
public BerOctetString(
byte[] str)
: base(str)
{
}
public BerOctetString(
IEnumerable octets)
: base(ToBytes(octets))
{
this.octs = octets;
}
public BerOctetString(
Asn1Object obj)
: base(obj)
{
}
public BerOctetString(
Asn1Encodable obj)
: base(obj.ToAsn1Object())
{
}
public override byte[] GetOctets()
{
return str;
}
/**
* return the DER octets that make up this string.
*/
public IEnumerator GetEnumerator()
{
if (octs == null)
{
return GenerateOcts().GetEnumerator();
}
return octs.GetEnumerator();
}
[Obsolete("Use GetEnumerator() instead")]
public IEnumerator GetObjects()
{
return GetEnumerator();
}
private ArrayList GenerateOcts()
{
int start = 0;
int end = 0;
ArrayList vec = new ArrayList();
while ((end + 1) < str.Length)
{
if (str[end] == 0 && str[end + 1] == 0)
{
byte[] nStr = new byte[end - start + 1];
Array.Copy(str, start, nStr, 0, nStr.Length);
vec.Add(new DerOctetString(nStr));
start = end + 1;
}
end++;
}
byte[] nStr2 = new byte[str.Length - start];
Array.Copy(str, start, nStr2, 0, nStr2.Length);
vec.Add(new DerOctetString(nStr2));
return vec;
}
internal override void Encode(
DerOutputStream derOut)
{
if (derOut is Asn1OutputStream || derOut is BerOutputStream)
{
derOut.WriteByte(Asn1Tags.Constructed | Asn1Tags.OctetString);
derOut.WriteByte(0x80);
//
// write out the octet array
//
if (octs != null)
{
foreach (DerOctetString oct in octs)
{
derOut.WriteObject(oct);
}
}
else
{
for (int i = 0; i < str.Length; i += MaxLength)
{
int end = System.Math.Min(str.Length, i + MaxLength);
byte[] nStr = new byte[end - i];
Array.Copy(str, i, nStr, 0, nStr.Length);
derOut.WriteObject(new DerOctetString(nStr));
}
}
derOut.WriteByte(0x00);
derOut.WriteByte(0x00);
}
else
{
base.Encode(derOut);
}
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.IO;
namespace Org.BouncyCastle.Asn1
{
// TODO Make Obsolete in favour of Asn1OutputStream?
public class BerOutputStream
: DerOutputStream
{
public BerOutputStream(Stream os) : base(os)
{
}
[Obsolete("Use version taking an Asn1Encodable arg instead")]
public override void WriteObject(
object obj)
{
if (obj == null)
{
WriteNull();
}
else if (obj is Asn1Object)
{
((Asn1Object)obj).Encode(this);
}
else if (obj is Asn1Encodable)
{
((Asn1Encodable)obj).ToAsn1Object().Encode(this);
}
else
{
throw new IOException("object not BerEncodable");
}
}
}
}

View File

@@ -0,0 +1,69 @@
namespace Org.BouncyCastle.Asn1
{
public class BerSequence
: DerSequence
{
public static new readonly BerSequence Empty = new BerSequence();
public static new BerSequence FromVector(
Asn1EncodableVector v)
{
return v.Count < 1 ? Empty : new BerSequence(v);
}
/**
* create an empty sequence
*/
public BerSequence()
{
}
/**
* create a sequence containing one object
*/
public BerSequence(
Asn1Encodable obj)
: base(obj)
{
}
public BerSequence(
params Asn1Encodable[] v)
: base(v)
{
}
/**
* create a sequence containing a vector of objects.
*/
public BerSequence(
Asn1EncodableVector v)
: base(v)
{
}
/*
*/
internal override void Encode(
DerOutputStream derOut)
{
if (derOut is Asn1OutputStream || derOut is BerOutputStream)
{
derOut.WriteByte(Asn1Tags.Sequence | Asn1Tags.Constructed);
derOut.WriteByte(0x80);
foreach (Asn1Encodable o in this)
{
derOut.WriteObject(o);
}
derOut.WriteByte(0x00);
derOut.WriteByte(0x00);
}
else
{
base.Encode(derOut);
}
}
}
}

View File

@@ -0,0 +1,70 @@
namespace Org.BouncyCastle.Asn1
{
public class BerSet
: DerSet
{
public static new readonly BerSet Empty = new BerSet();
public static new BerSet FromVector(
Asn1EncodableVector v)
{
return v.Count < 1 ? Empty : new BerSet(v);
}
internal static new BerSet FromVector(
Asn1EncodableVector v,
bool needsSorting)
{
return v.Count < 1 ? Empty : new BerSet(v, needsSorting);
}
/**
* create an empty sequence
*/
public BerSet()
{
}
/**
* create a set containing one object
*/
public BerSet(Asn1Encodable obj) : base(obj)
{
}
/**
* create a set containing a vector of objects.
*/
public BerSet(Asn1EncodableVector v) : base(v, false)
{
}
internal BerSet(Asn1EncodableVector v, bool needsSorting) : base(v, needsSorting)
{
}
/*
*/
internal override void Encode(
DerOutputStream derOut)
{
if (derOut is Asn1OutputStream || derOut is BerOutputStream)
{
derOut.WriteByte(Asn1Tags.Set | Asn1Tags.Constructed);
derOut.WriteByte(0x80);
foreach (Asn1Encodable o in this)
{
derOut.WriteObject(o);
}
derOut.WriteByte(0x00);
derOut.WriteByte(0x00);
}
else
{
base.Encode(derOut);
}
}
}
}

View File

@@ -0,0 +1,108 @@
using System;
using System.Collections;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
/**
* BER TaggedObject - in ASN.1 notation this is any object preceded by
* a [n] where n is some number - these are assumed to follow the construction
* rules (as with sequences).
*/
public class BerTaggedObject
: DerTaggedObject
{
/**
* @param tagNo the tag number for this object.
* @param obj the tagged object.
*/
public BerTaggedObject(
int tagNo,
Asn1Encodable obj)
: base(tagNo, obj)
{
}
/**
* @param explicitly true if an explicitly tagged object.
* @param tagNo the tag number for this object.
* @param obj the tagged object.
*/
public BerTaggedObject(
bool explicitly,
int tagNo,
Asn1Encodable obj)
: base(explicitly, tagNo, obj)
{
}
/**
* create an implicitly tagged object that contains a zero
* length sequence.
*/
public BerTaggedObject(
int tagNo)
: base(false, tagNo, BerSequence.Empty)
{
}
internal override void Encode(
DerOutputStream derOut)
{
if (derOut is Asn1OutputStream || derOut is BerOutputStream)
{
derOut.WriteTag((byte)(Asn1Tags.Constructed | Asn1Tags.Tagged), tagNo);
derOut.WriteByte(0x80);
if (!IsEmpty())
{
if (!explicitly)
{
IEnumerable eObj;
if (obj is Asn1OctetString)
{
if (obj is BerOctetString)
{
eObj = (BerOctetString) obj;
}
else
{
Asn1OctetString octs = (Asn1OctetString)obj;
eObj = new BerOctetString(octs.GetOctets());
}
}
else if (obj is Asn1Sequence)
{
eObj = (Asn1Sequence) obj;
}
else if (obj is Asn1Set)
{
eObj = (Asn1Set) obj;
}
else
{
throw Platform.CreateNotImplementedException(obj.GetType().Name);
}
foreach (Asn1Encodable o in eObj)
{
derOut.WriteObject(o);
}
}
else
{
derOut.WriteObject(obj);
}
}
derOut.WriteByte(0x00);
derOut.WriteByte(0x00);
}
else
{
base.Encode(derOut);
}
}
}
}

View File

@@ -0,0 +1,102 @@
using System.IO;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Asn1
{
internal class ConstructedOctetStream
: BaseInputStream
{
private readonly Asn1StreamParser _parser;
private bool _first = true;
private Stream _currentStream;
internal ConstructedOctetStream(
Asn1StreamParser parser)
{
_parser = parser;
}
public override int Read(byte[] buffer, int offset, int count)
{
if (_currentStream == null)
{
if (!_first)
return 0;
Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject();
if (s == null)
return 0;
_first = false;
_currentStream = s.GetOctetStream();
}
int totalRead = 0;
for (;;)
{
int numRead = _currentStream.Read(buffer, offset + totalRead, count - totalRead);
if (numRead > 0)
{
totalRead += numRead;
if (totalRead == count)
return totalRead;
}
else
{
Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject();
if (aos == null)
{
_currentStream = null;
return totalRead;
}
_currentStream = aos.GetOctetStream();
}
}
}
public override int ReadByte()
{
if (_currentStream == null)
{
if (!_first)
return 0;
Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject();
if (s == null)
return 0;
_first = false;
_currentStream = s.GetOctetStream();
}
for (;;)
{
int b = _currentStream.ReadByte();
if (b >= 0)
{
return b;
}
Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject();
if (aos == null)
{
_currentStream = null;
return -1;
}
_currentStream = aos.GetOctetStream();
}
}
}
}

View File

@@ -0,0 +1,107 @@
using System.IO;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Asn1
{
public abstract class DerGenerator
: Asn1Generator
{
private bool _tagged = false;
private bool _isExplicit;
private int _tagNo;
protected DerGenerator(
Stream outStream)
: base(outStream)
{
}
protected DerGenerator(
Stream outStream,
int tagNo,
bool isExplicit)
: base(outStream)
{
_tagged = true;
_isExplicit = isExplicit;
_tagNo = tagNo;
}
private static void WriteLength(
Stream outStr,
int length)
{
if (length > 127)
{
int size = 1;
int val = length;
while ((val >>= 8) != 0)
{
size++;
}
outStr.WriteByte((byte)(size | 0x80));
for (int i = (size - 1) * 8; i >= 0; i -= 8)
{
outStr.WriteByte((byte)(length >> i));
}
}
else
{
outStr.WriteByte((byte)length);
}
}
internal static void WriteDerEncoded(
Stream outStream,
int tag,
byte[] bytes)
{
outStream.WriteByte((byte) tag);
WriteLength(outStream, bytes.Length);
outStream.Write(bytes, 0, bytes.Length);
}
internal void WriteDerEncoded(
int tag,
byte[] bytes)
{
if (_tagged)
{
int tagNum = _tagNo | Asn1Tags.Tagged;
if (_isExplicit)
{
int newTag = _tagNo | Asn1Tags.Constructed | Asn1Tags.Tagged;
MemoryStream bOut = new MemoryStream();
WriteDerEncoded(bOut, tag, bytes);
WriteDerEncoded(Out, newTag, bOut.ToArray());
}
else
{
if ((tag & Asn1Tags.Constructed) != 0)
{
tagNum |= Asn1Tags.Constructed;
}
WriteDerEncoded(Out, tagNum, bytes);
}
}
else
{
WriteDerEncoded(Out, tag, bytes);
}
}
internal static void WriteDerEncoded(
Stream outStr,
int tag,
Stream inStr)
{
WriteDerEncoded(outStr, tag, Streams.ReadAll(inStr));
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.IO;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Asn1
{
public class DerOctetStringParser
: Asn1OctetStringParser
{
private readonly DefiniteLengthInputStream stream;
internal DerOctetStringParser(
DefiniteLengthInputStream stream)
{
this.stream = stream;
}
public Stream GetOctetStream()
{
return stream;
}
public Asn1Object ToAsn1Object()
{
try
{
return new DerOctetString(stream.ToArray());
}
catch (IOException e)
{
throw new InvalidOperationException("IOException converting stream to byte array: " + e.Message, e);
}
}
}
}

View File

@@ -0,0 +1,40 @@
using System.IO;
namespace Org.BouncyCastle.Asn1
{
public class DerSequenceGenerator
: DerGenerator
{
private readonly MemoryStream _bOut = new MemoryStream();
public DerSequenceGenerator(
Stream outStream)
: base(outStream)
{
}
public DerSequenceGenerator(
Stream outStream,
int tagNo,
bool isExplicit)
: base(outStream, tagNo, isExplicit)
{
}
public override void AddObject(
Asn1Encodable obj)
{
new DerOutputStream(_bOut).WriteObject(obj);
}
public override Stream GetRawOutputStream()
{
return _bOut;
}
public override void Close()
{
WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Sequence, _bOut.ToArray());
}
}
}

View File

@@ -0,0 +1,24 @@
namespace Org.BouncyCastle.Asn1
{
public class DerSequenceParser
: Asn1SequenceParser
{
private readonly Asn1StreamParser _parser;
internal DerSequenceParser(
Asn1StreamParser parser)
{
this._parser = parser;
}
public IAsn1Convertible ReadObject()
{
return _parser.ReadObject();
}
public Asn1Object ToAsn1Object()
{
return new DerSequence(_parser.ReadVector());
}
}
}

View File

@@ -0,0 +1,40 @@
using System.IO;
namespace Org.BouncyCastle.Asn1
{
public class DerSetGenerator
: DerGenerator
{
private readonly MemoryStream _bOut = new MemoryStream();
public DerSetGenerator(
Stream outStream)
: base(outStream)
{
}
public DerSetGenerator(
Stream outStream,
int tagNo,
bool isExplicit)
: base(outStream, tagNo, isExplicit)
{
}
public override void AddObject(
Asn1Encodable obj)
{
new DerOutputStream(_bOut).WriteObject(obj);
}
public override Stream GetRawOutputStream()
{
return _bOut;
}
public override void Close()
{
WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Set, _bOut.ToArray());
}
}
}

View File

@@ -0,0 +1,24 @@
namespace Org.BouncyCastle.Asn1
{
public class DerSetParser
: Asn1SetParser
{
private readonly Asn1StreamParser _parser;
internal DerSetParser(
Asn1StreamParser parser)
{
this._parser = parser;
}
public IAsn1Convertible ReadObject()
{
return _parser.ReadObject();
}
public Asn1Object ToAsn1Object()
{
return new DerSet(_parser.ReadVector(), false);
}
}
}

View File

@@ -0,0 +1,86 @@
using System;
using System.IO;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Asn1
{
class DefiniteLengthInputStream
: LimitedInputStream
{
private static readonly byte[] EmptyBytes = new byte[0];
private int _length;
internal DefiniteLengthInputStream(
Stream inStream,
int length)
: base(inStream)
{
if (length < 0)
throw new ArgumentException("negative lengths not allowed", "length");
this._length = length;
}
public override int ReadByte()
{
if (_length > 0)
{
int b = _in.ReadByte();
if (b < 0)
throw new EndOfStreamException();
--_length;
return b;
}
SetParentEofDetect(true);
return -1;
}
public override int Read(
byte[] buf,
int off,
int len)
{
if (_length > 0)
{
int toRead = System.Math.Min(len, _length);
int numRead = _in.Read(buf, off, toRead);
if (numRead < 1)
throw new EndOfStreamException();
_length -= numRead;
return numRead;
}
SetParentEofDetect(true);
return 0;
}
internal byte[] ToArray()
{
byte[] bytes;
if (_length > 0)
{
bytes = new byte[_length];
if (Streams.ReadFully(_in, bytes) < _length)
throw new EndOfStreamException();
_length = 0;
}
else
{
bytes = EmptyBytes;
}
SetParentEofDetect(true);
return bytes;
}
}
}

View File

@@ -0,0 +1,150 @@
using System;
using System.IO;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
/**
* Base class for an application specific object
*/
public class DerApplicationSpecific
: Asn1Object
{
private readonly bool isConstructed;
private readonly int tag;
private readonly byte[] octets;
internal DerApplicationSpecific(
bool isConstructed,
int tag,
byte[] octets)
{
this.isConstructed = isConstructed;
this.tag = tag;
this.octets = octets;
}
public DerApplicationSpecific(
int tag,
byte[] octets)
: this(false, tag, octets)
{
}
public DerApplicationSpecific(
int tag,
Asn1Encodable obj)
: this(true, tag, obj)
{
}
public DerApplicationSpecific(
bool isExplicit,
int tag,
Asn1Encodable obj)
{
if (tag >= 0x1f)
throw new IOException("unsupported tag number");
byte[] data = obj.GetDerEncoded();
this.isConstructed = isExplicit;
this.tag = tag;
if (isExplicit)
{
this.octets = data;
}
else
{
int lenBytes = GetLengthOfLength(data);
byte[] tmp = new byte[data.Length - lenBytes];
Array.Copy(data, lenBytes, tmp, 0, tmp.Length);
this.octets = tmp;
}
}
private int GetLengthOfLength(
byte[] data)
{
int count = 2; // TODO: assumes only a 1 byte tag number
while((data[count - 1] & 0x80) != 0)
{
count++;
}
return count;
}
public bool IsConstructed()
{
return isConstructed;
}
public byte[] GetContents()
{
return octets;
}
public int ApplicationTag
{
get { return tag; }
}
public Asn1Object GetObject()
{
return FromByteArray(GetContents());
}
/**
* Return the enclosed object assuming implicit tagging.
*
* @param derTagNo the type tag that should be applied to the object's contents.
* @return the resulting object
* @throws IOException if reconstruction fails.
*/
public Asn1Object GetObject(
int derTagNo)
{
if (tag >= 0x1f)
throw new IOException("unsupported tag number");
byte[] tmp = this.GetEncoded();
tmp[0] = (byte) derTagNo;
return FromByteArray(tmp);;
}
internal override void Encode(
DerOutputStream derOut)
{
int classBits = Asn1Tags.Application;
if (isConstructed)
{
classBits |= Asn1Tags.Constructed;
}
derOut.WriteEncoded(classBits, tag, octets);
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerApplicationSpecific other = asn1Object as DerApplicationSpecific;
if (other == null)
return false;
return this.isConstructed == other.isConstructed
&& this.tag == other.tag
&& Arrays.AreEqual(this.octets, other.octets);
}
protected override int Asn1GetHashCode()
{
return isConstructed.GetHashCode() ^ tag.GetHashCode() ^ Arrays.GetHashCode(octets);
}
}
}

View File

@@ -0,0 +1,118 @@
using System;
namespace Org.BouncyCastle.Asn1
{
/**
* Der BMPString object.
*/
public class DerBmpString
: DerStringBase
{
private readonly string str;
/**
* return a BMP string from the given object.
*
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static DerBmpString GetInstance(
object obj)
{
if (obj == null || obj is DerBmpString)
{
return (DerBmpString)obj;
}
if (obj is Asn1OctetString)
{
return new DerBmpString(((Asn1OctetString)obj).GetOctets());
}
if (obj is Asn1TaggedObject)
{
return GetInstance(((Asn1TaggedObject)obj).GetObject());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* return a BMP string from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerBmpString GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
/**
* basic constructor - byte encoded string.
*/
public DerBmpString(
byte[] str)
{
if (str == null)
throw new ArgumentNullException("str");
char[] cs = new char[str.Length / 2];
for (int i = 0; i != cs.Length; i++)
{
cs[i] = (char)((str[2 * i] << 8) | (str[2 * i + 1] & 0xff));
}
this.str = new string(cs);
}
/**
* basic constructor
*/
public DerBmpString(
string str)
{
if (str == null)
throw new ArgumentNullException("str");
this.str = str;
}
public override string GetString()
{
return str;
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerBmpString other = asn1Object as DerBmpString;
if (other == null)
return false;
return this.str.Equals(other.str);
}
internal override void Encode(
DerOutputStream derOut)
{
char[] c = str.ToCharArray();
byte[] b = new byte[c.Length * 2];
for (int i = 0; i != c.Length; i++)
{
b[2 * i] = (byte)(c[i] >> 8);
b[2 * i + 1] = (byte)c[i];
}
derOut.WriteEncoded(Asn1Tags.BmpString, b);
}
}
}

View File

@@ -0,0 +1,245 @@
using System;
using System.Text;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
public class DerBitString
: DerStringBase
{
private static readonly char[] table
= { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
private readonly byte[] data;
private readonly int padBits;
/**
* return the correct number of pad bits for a bit string defined in
* a 32 bit constant
*/
static internal int GetPadBits(
int bitString)
{
int val = 0;
for (int i = 3; i >= 0; i--)
{
//
// this may look a little odd, but if it isn't done like this pre jdk1.2
// JVM's break!
//
if (i != 0)
{
if ((bitString >> (i * 8)) != 0)
{
val = (bitString >> (i * 8)) & 0xFF;
break;
}
}
else
{
if (bitString != 0)
{
val = bitString & 0xFF;
break;
}
}
}
if (val == 0)
{
return 7;
}
int bits = 1;
while (((val <<= 1) & 0xFF) != 0)
{
bits++;
}
return 8 - bits;
}
/**
* return the correct number of bytes for a bit string defined in
* a 32 bit constant
*/
static internal byte[] GetBytes(
int bitString)
{
int bytes = 4;
for (int i = 3; i >= 1; i--)
{
if ((bitString & (0xFF << (i * 8))) != 0)
{
break;
}
bytes--;
}
byte[] result = new byte[bytes];
for (int i = 0; i < bytes; i++)
{
result[i] = (byte) ((bitString >> (i * 8)) & 0xFF);
}
return result;
}
/**
* return a Bit string from the passed in object
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerBitString GetInstance(
object obj)
{
if (obj == null || obj is DerBitString)
{
return (DerBitString) obj;
}
if (obj is Asn1OctetString)
{
byte[] bytes = ((Asn1OctetString) obj).GetOctets();
int padBits = bytes[0];
byte[] data = new byte[bytes.Length - 1];
Array.Copy(bytes, 1, data, 0, bytes.Length - 1);
return new DerBitString(data, padBits);
}
if (obj is Asn1TaggedObject)
{
return GetInstance(((Asn1TaggedObject) obj).GetObject());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* return a Bit string from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerBitString GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
internal DerBitString(
byte data,
int padBits)
{
this.data = new byte[]{ data };
this.padBits = padBits;
}
/**
* @param data the octets making up the bit string.
* @param padBits the number of extra bits at the end of the string.
*/
public DerBitString(
byte[] data,
int padBits)
{
// TODO Deep copy?
this.data = data;
this.padBits = padBits;
}
public DerBitString(
byte[] data)
{
// TODO Deep copy?
this.data = data;
}
public DerBitString(
Asn1Encodable obj)
{
this.data = obj.GetDerEncoded();
// this.padBits = 0;
}
public byte[] GetBytes()
{
return data;
}
public int PadBits
{
get { return padBits; }
}
/**
* @return the value of the bit string as an int (truncating if necessary)
*/
public int IntValue
{
get
{
int value = 0;
for (int i = 0; i != data.Length && i != 4; i++)
{
value |= (data[i] & 0xff) << (8 * i);
}
return value;
}
}
internal override void Encode(
DerOutputStream derOut)
{
byte[] bytes = new byte[GetBytes().Length + 1];
bytes[0] = (byte) PadBits;
Array.Copy(GetBytes(), 0, bytes, 1, bytes.Length - 1);
derOut.WriteEncoded(Asn1Tags.BitString, bytes);
}
protected override int Asn1GetHashCode()
{
return padBits.GetHashCode() ^ Arrays.GetHashCode(data);
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerBitString other = asn1Object as DerBitString;
if (other == null)
return false;
return this.padBits == other.padBits
&& Arrays.AreEqual(this.data, other.data);
}
public override string GetString()
{
StringBuilder buffer = new StringBuilder("#");
byte[] str = GetDerEncoded();
for (int i = 0; i != str.Length; i++)
{
uint ubyte = str[i];
buffer.Append(table[(ubyte >> 4) & 0xf]);
buffer.Append(table[str[i] & 0xf]);
}
return buffer.ToString();
}
}
}

View File

@@ -0,0 +1,110 @@
using System;
namespace Org.BouncyCastle.Asn1
{
public class DerBoolean
: Asn1Object
{
private readonly byte value;
public static readonly DerBoolean False = new DerBoolean(false);
public static readonly DerBoolean True = new DerBoolean(true);
/**
* return a bool from the passed in object.
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerBoolean GetInstance(
object obj)
{
if (obj == null || obj is DerBoolean)
{
return (DerBoolean) obj;
}
if (obj is Asn1OctetString)
{
return new DerBoolean(((Asn1OctetString) obj).GetOctets());
}
if (obj is Asn1TaggedObject)
{
return GetInstance(((Asn1TaggedObject) obj).GetObject());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* return a DerBoolean from the passed in bool.
*/
public static DerBoolean GetInstance(
bool value)
{
return value ? True : False;
}
/**
* return a Boolean from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerBoolean GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
public DerBoolean(
byte[] value)
{
// TODO Are there any constraints on the possible byte values?
this.value = value[0];
}
private DerBoolean(
bool value)
{
this.value = value ? (byte)0xff : (byte)0;
}
public bool IsTrue
{
get { return value != 0; }
}
internal override void Encode(
DerOutputStream derOut)
{
// TODO Should we make sure the byte value is one of '0' or '0xff' here?
derOut.WriteEncoded(Asn1Tags.Boolean, new byte[]{ value });
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerBoolean other = asn1Object as DerBoolean;
if (other == null)
return false;
return IsTrue == other.IsTrue;
}
protected override int Asn1GetHashCode()
{
return IsTrue.GetHashCode();
}
public override string ToString()
{
return IsTrue ? "TRUE" : "FALSE";
}
}
}

View File

@@ -0,0 +1,103 @@
using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
public class DerEnumerated
: Asn1Object
{
private readonly byte[] bytes;
/**
* return an integer from the passed in object
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerEnumerated GetInstance(
object obj)
{
if (obj == null || obj is DerEnumerated)
{
return (DerEnumerated)obj;
}
if (obj is Asn1OctetString)
{
return new DerEnumerated(((Asn1OctetString)obj).GetOctets());
}
if (obj is Asn1TaggedObject)
{
return GetInstance(((Asn1TaggedObject)obj).GetObject());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* return an Enumerated from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerEnumerated GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
public DerEnumerated(
int value)
{
bytes = BigInteger.ValueOf(value).ToByteArray();
}
public DerEnumerated(
BigInteger value)
{
bytes = value.ToByteArray();
}
public DerEnumerated(
byte[] bytes)
{
this.bytes = bytes;
}
public BigInteger Value
{
get
{
return new BigInteger(bytes);
}
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.Enumerated, bytes);
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerEnumerated other = asn1Object as DerEnumerated;
if (other == null)
return false;
return Arrays.AreEqual(this.bytes, other.bytes);
}
protected override int Asn1GetHashCode()
{
return Arrays.GetHashCode(bytes);
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Text;
namespace Org.BouncyCastle.Asn1
{
public class DerGeneralString
: DerStringBase
{
private readonly string str;
public static DerGeneralString GetInstance(
object obj)
{
if (obj == null || obj is DerGeneralString)
{
return (DerGeneralString) obj;
}
if (obj is Asn1OctetString)
{
return new DerGeneralString(((Asn1OctetString) obj).GetOctets());
}
if (obj is Asn1TaggedObject)
{
return GetInstance(((Asn1TaggedObject) obj).GetObject());
}
throw new ArgumentException("illegal object in GetInstance: "
+ obj.GetType().Name);
}
public static DerGeneralString GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
public DerGeneralString(
byte[] str)
: this(Encoding.ASCII.GetString(str, 0, str.Length))
{
}
public DerGeneralString(
string str)
{
if (str == null)
throw new ArgumentNullException("str");
this.str = str;
}
public override string GetString()
{
return str;
}
public byte[] GetOctets()
{
return Encoding.ASCII.GetBytes(str);
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.GeneralString, GetOctets());
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerGeneralString other = asn1Object as DerGeneralString;
if (other == null)
return false;
return this.str.Equals(other.str);
}
}
}

View File

@@ -0,0 +1,289 @@
using System;
using System.Globalization;
using System.Text;
namespace Org.BouncyCastle.Asn1
{
/**
* Generalized time object.
*/
public class DerGeneralizedTime
: Asn1Object
{
private readonly string time;
/**
* return a generalized time from the passed in object
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerGeneralizedTime GetInstance(
object obj)
{
if (obj == null || obj is DerGeneralizedTime)
{
return (DerGeneralizedTime)obj;
}
if (obj is Asn1OctetString)
{
return new DerGeneralizedTime(((Asn1OctetString)obj).GetOctets());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name, "obj");
}
/**
* return a Generalized Time object from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerGeneralizedTime GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
/**
* The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
* for local time, or Z+-HHMM on the end, for difference between local
* time and UTC time. The fractional second amount f must consist of at
* least one number with trailing zeroes removed.
*
* @param time the time string.
* @exception ArgumentException if string is an illegal format.
*/
public DerGeneralizedTime(
string time)
{
this.time = time;
try
{
ToDateTime();
}
catch (FormatException e)
{
throw new ArgumentException("invalid date string: " + e.Message);
}
}
/**
* base constructor from a local time object
*/
public DerGeneralizedTime(
DateTime time)
{
this.time = time.ToString(@"yyyyMMddHHmmss\Z");
}
internal DerGeneralizedTime(
byte[] bytes)
{
//
// explicitly convert to characters
//
this.time = Encoding.ASCII.GetString(bytes, 0, bytes.Length);
}
/**
* Return the time.
* @return The time string as it appeared in the encoded object.
*/
public string TimeString
{
get { return time; }
}
/**
* return the time - always in the form of
* YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
* <p>
* Normally in a certificate we would expect "Z" rather than "GMT",
* however adding the "GMT" means we can just use:
* <pre>
* dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
* </pre>
* To read in the time and Get a date which is compatible with our local
* time zone.</p>
*/
public string GetTime()
{
//
// standardise the format.
//
if (time[time.Length - 1] == 'Z')
{
return time.Substring(0, time.Length - 1) + "GMT+00:00";
}
else
{
int signPos = time.Length - 5;
char sign = time[signPos];
if (sign == '-' || sign == '+')
{
return time.Substring(0, signPos)
+ "GMT"
+ time.Substring(signPos, 3)
+ ":"
+ time.Substring(signPos + 3);
}
else
{
signPos = time.Length - 3;
sign = time[signPos];
if (sign == '-' || sign == '+')
{
return time.Substring(0, signPos)
+ "GMT"
+ time.Substring(signPos)
+ ":00";
}
}
}
return time + CalculateGmtOffset();
}
private string CalculateGmtOffset()
{
char sign = '+';
// Note: GetUtcOffset incorporates Daylight Savings offset
int minutes = TimeZone.CurrentTimeZone.GetUtcOffset(ToDateTime()).Minutes;
if (minutes < 0)
{
sign = '-';
minutes = -minutes;
}
int hours = minutes / 60;
minutes %= 60;
return "GMT" + sign + Convert(hours) + ":" + Convert(minutes);
}
private static string Convert(
int time)
{
if (time < 10)
{
return "0" + time;
}
return time.ToString();
}
public DateTime ToDateTime()
{
string formatStr;
string d = time;
bool makeUniversal = false;
if (d.EndsWith("Z"))
{
if (HasFractionalSeconds)
{
int fCount = d.Length - d.IndexOf('.') - 2;
formatStr = @"yyyyMMddHHmmss." + FString(fCount) + @"\Z";
}
else
{
formatStr = @"yyyyMMddHHmmss\Z";
}
}
else if (time.IndexOf('-') > 0 || time.IndexOf('+') > 0)
{
d = GetTime();
makeUniversal = true;
if (HasFractionalSeconds)
{
int fCount = d.IndexOf("GMT") - 1 - d.IndexOf('.');
formatStr = @"yyyyMMddHHmmss." + FString(fCount) + @"'GMT'zzz";
}
else
{
formatStr = @"yyyyMMddHHmmss'GMT'zzz";
}
}
else
{
if (HasFractionalSeconds)
{
int fCount = d.Length - 1 - d.IndexOf('.');
formatStr = @"yyyyMMddHHmmss." + FString(fCount);
}
else
{
formatStr = @"yyyyMMddHHmmss";
}
// TODO?
// dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
}
return ParseDateString(d, formatStr, makeUniversal);
}
private string FString(
int count)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; ++i)
{
sb.Append('f');
}
return sb.ToString();
}
private DateTime ParseDateString(
string dateStr,
string formatStr,
bool makeUniversal)
{
DateTime dt = DateTime.ParseExact(
dateStr,
formatStr,
DateTimeFormatInfo.InvariantInfo);
return makeUniversal ? dt.ToUniversalTime() : dt;
}
private bool HasFractionalSeconds
{
get { return time.IndexOf('.') == 14; }
}
private byte[] GetOctets()
{
return Encoding.ASCII.GetBytes(time);
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.GeneralizedTime, GetOctets());
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerGeneralizedTime other = asn1Object as DerGeneralizedTime;
if (other == null)
return false;
return this.time.Equals(other.time);
}
protected override int Asn1GetHashCode()
{
return time.GetHashCode();
}
}
}

View File

@@ -0,0 +1,146 @@
using System;
using System.Text;
namespace Org.BouncyCastle.Asn1
{
/**
* Der IA5String object - this is an ascii string.
*/
public class DerIA5String
: DerStringBase
{
private readonly string str;
/**
* return a IA5 string from the passed in object
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerIA5String GetInstance(
object obj)
{
if (obj == null || obj is DerIA5String)
{
return (DerIA5String)obj;
}
if (obj is Asn1OctetString)
{
return new DerIA5String(((Asn1OctetString)obj).GetOctets());
}
if (obj is Asn1TaggedObject)
{
return GetInstance(((Asn1TaggedObject)obj).GetObject());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* return an IA5 string from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerIA5String GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
/**
* basic constructor - with bytes.
*/
public DerIA5String(
byte[] str)
: this(Encoding.ASCII.GetString(str, 0, str.Length), false)
{
}
/**
* basic constructor - without validation.
*/
public DerIA5String(
string str)
: this(str, false)
{
}
/**
* Constructor with optional validation.
*
* @param string the base string to wrap.
* @param validate whether or not to check the string.
* @throws ArgumentException if validate is true and the string
* contains characters that should not be in an IA5String.
*/
public DerIA5String(
string str,
bool validate)
{
if (str == null)
throw new ArgumentNullException("str");
if (validate && !IsIA5String(str))
throw new ArgumentException("string contains illegal characters", "str");
this.str = str;
}
public override string GetString()
{
return str;
}
public byte[] GetOctets()
{
return Encoding.ASCII.GetBytes(str);
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.IA5String, GetOctets());
}
protected override int Asn1GetHashCode()
{
return this.str.GetHashCode();
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerIA5String other = asn1Object as DerIA5String;
if (other == null)
return false;
return this.str.Equals(other.str);
}
/**
* return true if the passed in String can be represented without
* loss as an IA5String, false otherwise.
*
* @return true if in printable set, false otherwise.
*/
public static bool IsIA5String(
string str)
{
foreach (char ch in str)
{
if (ch > 0x007f)
{
return false;
}
}
return true;
}
}
}

View File

@@ -0,0 +1,128 @@
using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
public class DerInteger
: Asn1Object
{
private readonly byte[] bytes;
/**
* return an integer from the passed in object
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerInteger GetInstance(
object obj)
{
if (obj == null)
{
return null;
}
DerInteger i = obj as DerInteger;
if (i != null)
{
return i;
}
Asn1OctetString octs = obj as Asn1OctetString;
if (octs != null)
{
return new DerInteger(octs.GetOctets());
}
Asn1TaggedObject tagged = obj as Asn1TaggedObject;
if (tagged != null)
{
return GetInstance(tagged.GetObject());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* return an Integer from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerInteger GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
if (obj == null)
throw new ArgumentNullException("obj");
return GetInstance(obj.GetObject());
}
public DerInteger(
int value)
{
bytes = BigInteger.ValueOf(value).ToByteArray();
}
public DerInteger(
BigInteger value)
{
if (value == null)
throw new ArgumentNullException("value");
bytes = value.ToByteArray();
}
public DerInteger(
byte[] bytes)
{
this.bytes = bytes;
}
public BigInteger Value
{
get { return new BigInteger(bytes); }
}
/**
* in some cases positive values Get crammed into a space,
* that's not quite big enough...
*/
public BigInteger PositiveValue
{
get { return new BigInteger(1, bytes); }
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.Integer, bytes);
}
protected override int Asn1GetHashCode()
{
return Arrays.GetHashCode(bytes);
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerInteger other = asn1Object as DerInteger;
if (other == null)
return false;
return Arrays.AreEqual(this.bytes, other.bytes);
}
public override string ToString()
{
return Value.ToString();
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
namespace Org.BouncyCastle.Asn1
{
/**
* A Null object.
*/
public class DerNull
: Asn1Null
{
public static readonly DerNull Instance = new DerNull(0);
byte[] zeroBytes = new byte[0];
[Obsolete("Use static Instance object")]
public DerNull()
{
}
protected internal DerNull(int dummy)
{
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.Null, zeroBytes);
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
return asn1Object is DerNull;
}
protected override int Asn1GetHashCode()
{
return -1;
}
}
}

View File

@@ -0,0 +1,139 @@
using System;
using System.Text;
namespace Org.BouncyCastle.Asn1
{
/**
* Der NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
*/
public class DerNumericString
: DerStringBase
{
private readonly string str;
/**
* return a Numeric string from the passed in object
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerNumericString GetInstance(
object obj)
{
if (obj == null || obj is DerNumericString)
{
return (DerNumericString)obj;
}
if (obj is Asn1OctetString)
{
return new DerNumericString(((Asn1OctetString)obj).GetOctets());
}
if (obj is Asn1TaggedObject)
{
return GetInstance(((Asn1TaggedObject)obj).GetObject());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* return an Numeric string from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerNumericString GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
/**
* basic constructor - with bytes.
*/
public DerNumericString(
byte[] str)
: this(Encoding.ASCII.GetString(str, 0, str.Length), false)
{
}
/**
* basic constructor - without validation..
*/
public DerNumericString(
string str)
: this(str, false)
{
}
/**
* Constructor with optional validation.
*
* @param string the base string to wrap.
* @param validate whether or not to check the string.
* @throws ArgumentException if validate is true and the string
* contains characters that should not be in a NumericString.
*/
public DerNumericString(
string str,
bool validate)
{
if (str == null)
throw new ArgumentNullException("str");
if (validate && !IsNumericString(str))
throw new ArgumentException("string contains illegal characters", "str");
this.str = str;
}
public override string GetString()
{
return str;
}
public byte[] GetOctets()
{
return Encoding.ASCII.GetBytes(str);
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.NumericString, GetOctets());
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerNumericString other = asn1Object as DerNumericString;
if (other == null)
return false;
return this.str.Equals(other.str);
}
/**
* Return true if the string can be represented as a NumericString ('0'..'9', ' ')
*
* @param str string to validate.
* @return true if numeric, fale otherwise.
*/
public static bool IsNumericString(
string str)
{
foreach (char ch in str)
{
if (ch > 0x007f || (ch != ' ' && !char.IsDigit(ch)))
return false;
}
return true;
}
}
}

View File

@@ -0,0 +1,260 @@
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Asn1
{
public class DerObjectIdentifier
: Asn1Object
{
private static readonly Regex OidRegex = new Regex(@"\A[0-2](\.[0-9]+)+\z");
private readonly string identifier;
/**
* return an Oid from the passed in object
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerObjectIdentifier GetInstance(
object obj)
{
if (obj == null || obj is DerObjectIdentifier)
{
return (DerObjectIdentifier) obj;
}
if (obj is Asn1OctetString)
{
return new DerObjectIdentifier(((Asn1OctetString)obj).GetOctets());
}
if (obj is Asn1TaggedObject)
{
return GetInstance(((Asn1TaggedObject)obj).GetObject());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name, "obj");
}
/**
* return an object Identifier from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerObjectIdentifier GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
public DerObjectIdentifier(
string identifier)
{
if (identifier == null)
throw new ArgumentNullException("identifier");
if (!OidRegex.IsMatch(identifier))
throw new FormatException("string " + identifier + " not an OID");
this.identifier = identifier;
}
// TODO Change to ID?
public string Id
{
get { return identifier; }
}
internal DerObjectIdentifier(
byte[] bytes)
: this(MakeOidStringFromBytes(bytes))
{
}
private void WriteField(
Stream outputStream,
long fieldValue)
{
if (fieldValue >= (1L << 7))
{
if (fieldValue >= (1L << 14))
{
if (fieldValue >= (1L << 21))
{
if (fieldValue >= (1L << 28))
{
if (fieldValue >= (1L << 35))
{
if (fieldValue >= (1L << 42))
{
if (fieldValue >= (1L << 49))
{
if (fieldValue >= (1L << 56))
{
outputStream.WriteByte((byte)((fieldValue >> 56) | 0x80));
}
outputStream.WriteByte((byte)((fieldValue >> 49) | 0x80));
}
outputStream.WriteByte((byte)((fieldValue >> 42) | 0x80));
}
outputStream.WriteByte((byte)((fieldValue >> 35) | 0x80));
}
outputStream.WriteByte((byte)((fieldValue >> 28) | 0x80));
}
outputStream.WriteByte((byte)((fieldValue >> 21) | 0x80));
}
outputStream.WriteByte((byte)((fieldValue >> 14) | 0x80));
}
outputStream.WriteByte((byte)((fieldValue >> 7) | 0x80));
}
outputStream.WriteByte((byte)(fieldValue & 0x7f));
}
private void WriteField(
Stream outputStream,
BigInteger fieldValue)
{
int byteCount = (fieldValue.BitLength + 6) / 7;
if (byteCount == 0)
{
outputStream.WriteByte(0);
}
else
{
BigInteger tmpValue = fieldValue;
byte[] tmp = new byte[byteCount];
for (int i = byteCount-1; i >= 0; i--)
{
tmp[i] = (byte) ((tmpValue.IntValue & 0x7f) | 0x80);
tmpValue = tmpValue.ShiftRight(7);
}
tmp[byteCount-1] &= 0x7f;
outputStream.Write(tmp, 0, tmp.Length);
}
}
internal override void Encode(
DerOutputStream derOut)
{
OidTokenizer tok = new OidTokenizer(identifier);
MemoryStream bOut = new MemoryStream();
DerOutputStream dOut = new DerOutputStream(bOut);
string token = tok.NextToken();
int first = int.Parse(token);
token = tok.NextToken();
int second = int.Parse(token);
WriteField(bOut, first * 40 + second);
while (tok.HasMoreTokens)
{
token = tok.NextToken();
if (token.Length < 18)
{
WriteField(bOut, Int64.Parse(token));
}
else
{
WriteField(bOut, new BigInteger(token));
}
}
dOut.Close();
derOut.WriteEncoded(Asn1Tags.ObjectIdentifier, bOut.ToArray());
}
protected override int Asn1GetHashCode()
{
return identifier.GetHashCode();
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerObjectIdentifier other = asn1Object as DerObjectIdentifier;
if (other == null)
return false;
return this.identifier.Equals(other.identifier);
}
public override string ToString()
{
return identifier;
}
private static string MakeOidStringFromBytes(
byte[] bytes)
{
StringBuilder objId = new StringBuilder();
long value = 0;
BigInteger bigValue = null;
bool first = true;
for (int i = 0; i != bytes.Length; i++)
{
int b = bytes[i];
if (value < 0x80000000000000L)
{
value = value * 128 + (b & 0x7f);
if ((b & 0x80) == 0) // end of number reached
{
if (first)
{
switch ((int)value / 40)
{
case 0:
objId.Append('0');
break;
case 1:
objId.Append('1');
value -= 40;
break;
default:
objId.Append('2');
value -= 80;
break;
}
first = false;
}
objId.Append('.');
objId.Append(value);
value = 0;
}
}
else
{
if (bigValue == null)
{
bigValue = BigInteger.ValueOf(value);
}
bigValue = bigValue.ShiftLeft(7);
bigValue = bigValue.Or(BigInteger.ValueOf(b & 0x7f));
if ((b & 0x80) == 0)
{
objId.Append('.');
objId.Append(bigValue);
bigValue = null;
value = 0;
}
}
}
return objId.ToString();
}
}
}

View File

@@ -0,0 +1,34 @@
namespace Org.BouncyCastle.Asn1
{
public class DerOctetString
: Asn1OctetString
{
/// <param name="str">The octets making up the octet string.</param>
public DerOctetString(
byte[] str)
: base(str)
{
}
public DerOctetString(
Asn1Encodable obj)
: base(obj)
{
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.OctetString, str);
}
internal static void Encode(
DerOutputStream derOut,
byte[] bytes,
int offset,
int length)
{
derOut.WriteEncoded(Asn1Tags.OctetString, bytes, offset, length);
}
}
}

View File

@@ -0,0 +1,147 @@
using System;
using System.IO;
using Org.BouncyCastle.Asn1.Utilities;
namespace Org.BouncyCastle.Asn1
{
public class DerOutputStream
: FilterStream
{
public DerOutputStream(Stream os)
: base(os)
{
}
private void WriteLength(
int length)
{
if (length > 127)
{
int size = 1;
uint val = (uint) length;
while ((val >>= 8) != 0)
{
size++;
}
WriteByte((byte)(size | 0x80));
for (int i = (size - 1) * 8; i >= 0; i -= 8)
{
WriteByte((byte)(length >> i));
}
}
else
{
WriteByte((byte)length);
}
}
internal void WriteEncoded(
int tag,
byte[] bytes)
{
WriteByte((byte) tag);
WriteLength(bytes.Length);
Write(bytes, 0, bytes.Length);
}
internal void WriteEncoded(
int tag,
byte[] bytes,
int offset,
int length)
{
WriteByte((byte) tag);
WriteLength(length);
Write(bytes, offset, length);
}
internal void WriteTag(
int flags,
int tagNo)
{
if (tagNo < 31)
{
WriteByte((byte)(flags | tagNo));
}
else
{
WriteByte((byte)(flags | 0x1f));
if (tagNo < 128)
{
WriteByte((byte)tagNo);
}
else
{
byte[] stack = new byte[5];
int pos = stack.Length;
stack[--pos] = (byte)(tagNo & 0x7F);
do
{
tagNo >>= 7;
stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
}
while (tagNo > 127);
Write(stack, pos, stack.Length - pos);
}
}
}
internal void WriteEncoded(
int flags,
int tagNo,
byte[] bytes)
{
WriteTag(flags, tagNo);
WriteLength(bytes.Length);
Write(bytes, 0, bytes.Length);
}
protected void WriteNull()
{
WriteByte(Asn1Tags.Null);
WriteByte(0x00);
}
[Obsolete("Use version taking an Asn1Encodable arg instead")]
public virtual void WriteObject(
object obj)
{
if (obj == null)
{
WriteNull();
}
else if (obj is Asn1Object)
{
((Asn1Object)obj).Encode(this);
}
else if (obj is Asn1Encodable)
{
((Asn1Encodable)obj).ToAsn1Object().Encode(this);
}
else
{
throw new IOException("object not Asn1Object");
}
}
public virtual void WriteObject(
Asn1Encodable obj)
{
if (obj == null)
{
WriteNull();
}
else
{
obj.ToAsn1Object().Encode(this);
}
}
}
}

View File

@@ -0,0 +1,164 @@
using System;
using System.Text;
namespace Org.BouncyCastle.Asn1
{
/**
* Der PrintableString object.
*/
public class DerPrintableString
: DerStringBase
{
private readonly string str;
/**
* return a printable string from the passed in object.
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerPrintableString GetInstance(
object obj)
{
if (obj == null || obj is DerPrintableString)
{
return (DerPrintableString)obj;
}
if (obj is Asn1OctetString)
{
return new DerPrintableString(((Asn1OctetString)obj).GetOctets());
}
if (obj is Asn1TaggedObject)
{
return GetInstance(((Asn1TaggedObject)obj).GetObject());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* return a Printable string from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerPrintableString GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
/**
* basic constructor - byte encoded string.
*/
public DerPrintableString(
byte[] str)
: this(Encoding.ASCII.GetString(str, 0, str.Length), false)
{
}
/**
* basic constructor - this does not validate the string
*/
public DerPrintableString(
string str)
: this(str, false)
{
}
/**
* Constructor with optional validation.
*
* @param string the base string to wrap.
* @param validate whether or not to check the string.
* @throws ArgumentException if validate is true and the string
* contains characters that should not be in a PrintableString.
*/
public DerPrintableString(
string str,
bool validate)
{
if (str == null)
throw new ArgumentNullException("str");
if (validate && !IsPrintableString(str))
throw new ArgumentException("string contains illegal characters", "str");
this.str = str;
}
public override string GetString()
{
return str;
}
public byte[] GetOctets()
{
return Encoding.ASCII.GetBytes(str);
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.PrintableString, GetOctets());
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerPrintableString other = asn1Object as DerPrintableString;
if (other == null)
return false;
return this.str.Equals(other.str);
}
/**
* return true if the passed in String can be represented without
* loss as a PrintableString, false otherwise.
*
* @return true if in printable set, false otherwise.
*/
public static bool IsPrintableString(
string str)
{
foreach (char ch in str)
{
if (ch > 0x007f)
return false;
if (char.IsLetterOrDigit(ch))
continue;
// if (char.IsPunctuation(ch))
// continue;
switch (ch)
{
case ' ':
case '\'':
case '(':
case ')':
case '+':
case '-':
case '.':
case ':':
case '=':
case '?':
case '/':
case ',':
continue;
}
return false;
}
return true;
}
}
}

View File

@@ -0,0 +1,85 @@
using System.Collections;
using System.IO;
namespace Org.BouncyCastle.Asn1
{
public class DerSequence
: Asn1Sequence
{
public static readonly DerSequence Empty = new DerSequence();
public static DerSequence FromVector(
Asn1EncodableVector v)
{
return v.Count < 1 ? Empty : new DerSequence(v);
}
/**
* create an empty sequence
*/
public DerSequence()
: base(0)
{
}
/**
* create a sequence containing one object
*/
public DerSequence(
Asn1Encodable obj)
: base(1)
{
AddObject(obj);
}
public DerSequence(
params Asn1Encodable[] v)
: base(v.Length)
{
foreach (Asn1Encodable ae in v)
{
AddObject(ae);
}
}
/**
* create a sequence containing a vector of objects.
*/
public DerSequence(
Asn1EncodableVector v)
: base(v.Count)
{
foreach (Asn1Encodable ae in v)
{
AddObject(ae);
}
}
/*
* A note on the implementation:
* <p>
* As Der requires the constructed, definite-length model to
* be used for structured types, this varies slightly from the
* ASN.1 descriptions given. Rather than just outputing Sequence,
* we also have to specify Constructed, and the objects length.
*/
internal override void Encode(
DerOutputStream derOut)
{
// TODO Intermediate buffer could be avoided if we could calculate expected length
MemoryStream bOut = new MemoryStream();
DerOutputStream dOut = new DerOutputStream(bOut);
foreach (Asn1Encodable obj in this)
{
dOut.WriteObject(obj);
}
dOut.Close();
byte[] bytes = bOut.ToArray();
derOut.WriteEncoded(Asn1Tags.Sequence | Asn1Tags.Constructed, bytes);
}
}
}

View File

@@ -0,0 +1,108 @@
using System.IO;
namespace Org.BouncyCastle.Asn1
{
/**
* A Der encoded set object
*/
public class DerSet
: Asn1Set
{
public static readonly DerSet Empty = new DerSet();
public static DerSet FromVector(
Asn1EncodableVector v)
{
return v.Count < 1 ? Empty : new DerSet(v);
}
internal static DerSet FromVector(
Asn1EncodableVector v,
bool needsSorting)
{
return v.Count < 1 ? Empty : new DerSet(v, needsSorting);
}
/**
* create an empty set
*/
public DerSet()
: base(0)
{
}
/**
* @param obj - a single object that makes up the set.
*/
public DerSet(
Asn1Encodable obj)
: base(1)
{
AddObject(obj);
}
public DerSet(
params Asn1Encodable[] v)
: base(v.Length)
{
foreach (Asn1Encodable o in v)
{
AddObject(o);
}
Sort();
}
/**
* @param v - a vector of objects making up the set.
*/
public DerSet(
Asn1EncodableVector v)
: this(v, true)
{
}
internal DerSet(
Asn1EncodableVector v,
bool needsSorting)
: base(v.Count)
{
foreach (Asn1Encodable o in v)
{
AddObject(o);
}
if (needsSorting)
{
Sort();
}
}
/*
* A note on the implementation:
* <p>
* As Der requires the constructed, definite-length model to
* be used for structured types, this varies slightly from the
* ASN.1 descriptions given. Rather than just outputing Set,
* we also have to specify Constructed, and the objects length.
*/
internal override void Encode(
DerOutputStream derOut)
{
// TODO Intermediate buffer could be avoided if we could calculate expected length
MemoryStream bOut = new MemoryStream();
DerOutputStream dOut = new DerOutputStream(bOut);
foreach (Asn1Encodable obj in this)
{
dOut.WriteObject(obj);
}
dOut.Close();
byte[] bytes = bOut.ToArray();
derOut.WriteEncoded(Asn1Tags.Set | Asn1Tags.Constructed, bytes);
}
}
}

View File

@@ -0,0 +1,22 @@
namespace Org.BouncyCastle.Asn1
{
public abstract class DerStringBase
: Asn1Object, IAsn1String
{
protected DerStringBase()
{
}
public abstract string GetString();
public override string ToString()
{
return GetString();
}
protected override int Asn1GetHashCode()
{
return GetString().GetHashCode();
}
}
}

View File

@@ -0,0 +1,105 @@
using System;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
/**
* Der T61String (also the teletex string) - 8-bit characters
*/
public class DerT61String
: DerStringBase
{
private readonly string str;
/**
* return a T61 string from the passed in object.
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerT61String GetInstance(
object obj)
{
if (obj == null || obj is DerT61String)
{
return (DerT61String)obj;
}
if (obj is Asn1OctetString)
{
return new DerT61String(((Asn1OctetString)obj).GetOctets());
}
if (obj is Asn1TaggedObject)
{
return GetInstance(((Asn1TaggedObject)obj).GetObject());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* return an T61 string from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerT61String GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
/**
* basic constructor - with bytes.
*/
public DerT61String(
byte[] str)
: this(Strings.FromByteArray(str))
{
}
/**
* basic constructor - with string.
*/
public DerT61String(
string str)
{
if (str == null)
throw new ArgumentNullException("str");
this.str = str;
}
public override string GetString()
{
return str;
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.T61String, GetOctets());
}
public byte[] GetOctets()
{
return Strings.ToByteArray(str);
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerT61String other = asn1Object as DerT61String;
if (other == null)
return false;
return this.str.Equals(other.str);
}
}
}

View File

@@ -0,0 +1,72 @@
namespace Org.BouncyCastle.Asn1
{
/**
* DER TaggedObject - in ASN.1 notation this is any object preceded by
* a [n] where n is some number - these are assumed to follow the construction
* rules (as with sequences).
*/
public class DerTaggedObject
: Asn1TaggedObject
{
/**
* @param tagNo the tag number for this object.
* @param obj the tagged object.
*/
public DerTaggedObject(
int tagNo,
Asn1Encodable obj)
: base(tagNo, obj)
{
}
/**
* @param explicitly true if an explicitly tagged object.
* @param tagNo the tag number for this object.
* @param obj the tagged object.
*/
public DerTaggedObject(
bool explicitly,
int tagNo,
Asn1Encodable obj)
: base(explicitly, tagNo, obj)
{
}
/**
* create an implicitly tagged object that contains a zero
* length sequence.
*/
public DerTaggedObject(
int tagNo)
: base(false, tagNo, DerSequence.Empty)
{
}
internal override void Encode(
DerOutputStream derOut)
{
if (!IsEmpty())
{
byte[] bytes = obj.GetDerEncoded();
if (explicitly)
{
derOut.WriteEncoded(Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo, bytes);
}
else
{
//
// need to mark constructed types... (preserve Constructed tag)
//
int flags = (bytes[0] & Asn1Tags.Constructed) | Asn1Tags.Tagged;
derOut.WriteTag(flags, tagNo);
derOut.Write(bytes, 1, bytes.Length - 1);
}
}
else
{
derOut.WriteEncoded(Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo, new byte[0]);
}
}
}
}

View File

@@ -0,0 +1,259 @@
using System;
using System.Globalization;
using System.Text;
namespace Org.BouncyCastle.Asn1
{
/**
* UTC time object.
*/
public class DerUtcTime
: Asn1Object
{
private readonly string time;
/**
* return an UTC Time from the passed in object.
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerUtcTime GetInstance(
object obj)
{
if (obj == null || obj is DerUtcTime)
{
return (DerUtcTime)obj;
}
if (obj is Asn1OctetString)
{
return new DerUtcTime(((Asn1OctetString)obj).GetOctets());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* return an UTC Time from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerUtcTime GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
/**
* The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
* never encoded. When you're creating one of these objects from scratch, that's
* what you want to use, otherwise we'll try to deal with whatever Gets read from
* the input stream... (this is why the input format is different from the GetTime()
* method output).
* <p>
* @param time the time string.</p>
*/
public DerUtcTime(
string time)
{
if (time == null)
throw new ArgumentNullException("time");
this.time = time;
try
{
ToDateTime();
}
catch (FormatException e)
{
throw new ArgumentException("invalid date string: " + e.Message);
}
}
/**
* base constructor from a DateTime object
*/
public DerUtcTime(
DateTime time)
{
this.time = time.ToString("yyMMddHHmmss") + "Z";
}
internal DerUtcTime(
byte[] bytes)
{
//
// explicitly convert to characters
//
this.time = Encoding.ASCII.GetString(bytes, 0, bytes.Length);
}
// public DateTime ToDateTime()
// {
// string tm = this.AdjustedTimeString;
//
// return new DateTime(
// Int16.Parse(tm.Substring(0, 4)),
// Int16.Parse(tm.Substring(4, 2)),
// Int16.Parse(tm.Substring(6, 2)),
// Int16.Parse(tm.Substring(8, 2)),
// Int16.Parse(tm.Substring(10, 2)),
// Int16.Parse(tm.Substring(12, 2)));
// }
/**
* return the time as a date based on whatever a 2 digit year will return. For
* standardised processing use ToAdjustedDateTime().
*
* @return the resulting date
* @exception ParseException if the date string cannot be parsed.
*/
public DateTime ToDateTime()
{
return ParseDateString(TimeString, @"yyMMddHHmmss'GMT'zzz");
}
/**
* return the time as an adjusted date
* in the range of 1950 - 2049.
*
* @return a date in the range of 1950 to 2049.
* @exception ParseException if the date string cannot be parsed.
*/
public DateTime ToAdjustedDateTime()
{
return ParseDateString(AdjustedTimeString, @"yyyyMMddHHmmss'GMT'zzz");
}
private DateTime ParseDateString(
string dateStr,
string formatStr)
{
DateTime dt = DateTime.ParseExact(
dateStr,
formatStr,
DateTimeFormatInfo.InvariantInfo);
return dt.ToUniversalTime();
}
/**
* return the time - always in the form of
* YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
* <p>
* Normally in a certificate we would expect "Z" rather than "GMT",
* however adding the "GMT" means we can just use:
* <pre>
* dateF = new SimpleDateFormat("yyMMddHHmmssz");
* </pre>
* To read in the time and Get a date which is compatible with our local
* time zone.</p>
* <p>
* <b>Note:</b> In some cases, due to the local date processing, this
* may lead to unexpected results. If you want to stick the normal
* convention of 1950 to 2049 use the GetAdjustedTime() method.</p>
*/
public string TimeString
{
get
{
//
// standardise the format.
//
if (time.IndexOf('-') < 0 && time.IndexOf('+') < 0)
{
if (time.Length == 11)
{
return time.Substring(0, 10) + "00GMT+00:00";
}
else
{
return time.Substring(0, 12) + "GMT+00:00";
}
}
else
{
int index = time.IndexOf('-');
if (index < 0)
{
index = time.IndexOf('+');
}
string d = time;
if (index == time.Length - 3)
{
d += "00";
}
if (index == 10)
{
return d.Substring(0, 10) + "00GMT" + d.Substring(10, 3) + ":" + d.Substring(13, 2);
}
else
{
return d.Substring(0, 12) + "GMT" + d.Substring(12, 3) + ":" + d.Substring(15, 2);
}
}
}
}
[Obsolete("Use 'AdjustedTimeString' property instead")]
public string AdjustedTime
{
get { return AdjustedTimeString; }
}
/// <summary>
/// Return a time string as an adjusted date with a 4 digit year.
/// This goes in the range of 1950 - 2049.
/// </summary>
public string AdjustedTimeString
{
get
{
string d = TimeString;
string c = d[0] < '5' ? "20" : "19";
return c + d;
}
}
private byte[] GetOctets()
{
return Encoding.ASCII.GetBytes(time);
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.UtcTime, GetOctets());
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerUtcTime other = asn1Object as DerUtcTime;
if (other == null)
return false;
return this.time.Equals(other.time);
}
protected override int Asn1GetHashCode()
{
return time.GetHashCode();
}
public override string ToString()
{
return time;
}
}
}

View File

@@ -0,0 +1,99 @@
using System;
using System.Text;
namespace Org.BouncyCastle.Asn1
{
/**
* Der UTF8String object.
*/
public class DerUtf8String
: DerStringBase
{
private readonly string str;
/**
* return an UTF8 string from the passed in object.
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerUtf8String GetInstance(
object obj)
{
if (obj == null || obj is DerUtf8String)
{
return (DerUtf8String)obj;
}
if (obj is Asn1OctetString)
{
return new DerUtf8String(((Asn1OctetString)obj).GetOctets());
}
if (obj is Asn1TaggedObject)
{
return GetInstance(((Asn1TaggedObject)obj).GetObject());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* return an UTF8 string from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerUtf8String GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
/**
* basic constructor - byte encoded string.
*/
internal DerUtf8String(
byte[] str)
: this(Encoding.UTF8.GetString(str, 0, str.Length))
{
}
/**
* basic constructor
*/
public DerUtf8String(
string str)
{
if (str == null)
throw new ArgumentNullException("str");
this.str = str;
}
public override string GetString()
{
return str;
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerUtf8String other = asn1Object as DerUtf8String;
if (other == null)
return false;
return this.str.Equals(other.str);
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.Utf8String, Encoding.UTF8.GetBytes(str));
}
}
}

View File

@@ -0,0 +1,105 @@
using System;
using System.Text;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
/**
* Der UniversalString object.
*/
public class DerUniversalString
: DerStringBase
{
private static readonly char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
private readonly byte[] str;
/**
* return a Universal string from the passed in object.
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerUniversalString GetInstance(
object obj)
{
if (obj == null || obj is DerUniversalString)
{
return (DerUniversalString)obj;
}
if (obj is Asn1OctetString)
{
return new DerUniversalString(((Asn1OctetString)obj).GetOctets());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* return a Universal string from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerUniversalString GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
/**
* basic constructor - byte encoded string.
*/
public DerUniversalString(
byte[] str)
{
if (str == null)
throw new ArgumentNullException("str");
this.str = str;
}
public override string GetString()
{
StringBuilder buffer = new StringBuilder("#");
byte[] enc = GetDerEncoded();
for (int i = 0; i != enc.Length; i++)
{
uint ubyte = enc[i];
buffer.Append(table[(ubyte >> 4) & 0xf]);
buffer.Append(table[enc[i] & 0xf]);
}
return buffer.ToString();
}
public byte[] GetOctets()
{
return (byte[]) str.Clone();
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.UniversalString, this.str);
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerUniversalString other = asn1Object as DerUniversalString;
if (other == null)
return false;
// return this.GetString().Equals(other.GetString());
return Arrays.AreEqual(this.str, other.str);
}
}
}

View File

@@ -0,0 +1,64 @@
using System;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
/**
* We insert one of these when we find a tag we don't recognise.
*/
public class DerUnknownTag
: Asn1Object
{
private readonly int tag;
private readonly byte[] data;
/**
* @param tag the tag value.
* @param data the contents octets.
*/
public DerUnknownTag(
int tag,
byte[] data)
{
if (data == null)
throw new ArgumentNullException("data");
this.tag = tag;
this.data = data;
}
public int Tag
{
get { return tag; }
}
public byte[] GetData()
{
return data;
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(tag, data);
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerUnknownTag other = asn1Object as DerUnknownTag;
if (other == null)
return false;
return this.tag == other.tag
&& Arrays.AreEqual(this.data, other.data);
}
protected override int Asn1GetHashCode()
{
return tag.GetHashCode() ^ Arrays.GetHashCode(data);
}
}
}

View File

@@ -0,0 +1,109 @@
using System;
using System.Text;
namespace Org.BouncyCastle.Asn1
{
/**
* Der VisibleString object.
*/
public class DerVisibleString
: DerStringBase
{
private readonly string str;
/**
* return a Visible string from the passed in object.
*
* @exception ArgumentException if the object cannot be converted.
*/
public static DerVisibleString GetInstance(
object obj)
{
if (obj == null || obj is DerVisibleString)
{
return (DerVisibleString)obj;
}
if (obj is Asn1OctetString)
{
return new DerVisibleString(((Asn1OctetString)obj).GetOctets());
}
if (obj is Asn1TaggedObject)
{
return GetInstance(((Asn1TaggedObject)obj).GetObject());
}
throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
}
/**
* return a Visible string from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the tagged object cannot
* be converted.
*/
public static DerVisibleString GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(obj.GetObject());
}
/**
* basic constructor - byte encoded string.
*/
public DerVisibleString(
byte[] str)
: this(Encoding.ASCII.GetString(str, 0, str.Length))
{
}
/**
* basic constructor
*/
public DerVisibleString(
string str)
{
if (str == null)
throw new ArgumentNullException("str");
this.str = str;
}
public override string GetString()
{
return str;
}
public byte[] GetOctets()
{
return Encoding.ASCII.GetBytes(str);
}
internal override void Encode(
DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.VisibleString, GetOctets());
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
DerVisibleString other = asn1Object as DerVisibleString;
if (other == null)
return false;
return this.str.Equals(other.str);
}
protected override int Asn1GetHashCode()
{
return this.str.GetHashCode();
}
}
}

View File

@@ -0,0 +1,7 @@
namespace Org.BouncyCastle.Asn1
{
public interface IAsn1Convertible
{
Asn1Object ToAsn1Object();
}
}

View File

@@ -0,0 +1,10 @@
namespace Org.BouncyCastle.Asn1
{
/**
* basic interface for Der string objects.
*/
public interface IAsn1String
{
string GetString();
}
}

View File

@@ -0,0 +1,95 @@
using System.IO;
namespace Org.BouncyCastle.Asn1
{
class IndefiniteLengthInputStream
: LimitedInputStream
{
private int _b1;
private int _b2;
private bool _eofReached = false;
private bool _eofOn00 = true;
internal IndefiniteLengthInputStream(
Stream inStream)
: base(inStream)
{
_b1 = inStream.ReadByte();
_b2 = inStream.ReadByte();
_eofReached = (_b2 < 0);
}
internal void SetEofOn00(
bool eofOn00)
{
_eofOn00 = eofOn00;
}
internal bool CheckForEof()
{
if (_eofOn00 && (_b1 == 0x00 && _b2 == 0x00))
{
_eofReached = true;
SetParentEofDetect(true);
}
return _eofReached;
}
public override int Read(
byte[] buffer,
int offset,
int count)
{
// Only use this optimisation if we aren't checking for 00
if (_eofOn00 || count < 3)
return base.Read(buffer, offset, count);
if (_eofReached)
return 0;
int numRead = _in.Read(buffer, offset + 2, count - 2);
if (numRead <= 0)
{
// Corrupted stream
throw new EndOfStreamException();
}
buffer[offset] = (byte)_b1;
buffer[offset + 1] = (byte)_b2;
_b1 = _in.ReadByte();
_b2 = _in.ReadByte();
if (_b2 < 0)
{
// Corrupted stream
throw new EndOfStreamException();
}
return numRead + 2;
}
public override int ReadByte()
{
if (CheckForEof())
return -1;
int b = _in.ReadByte();
if (b < 0)
{
// Corrupted stream
throw new EndOfStreamException();
}
int v = _b1;
_b1 = _b2;
_b2 = b;
return v;
}
}
}

View File

@@ -0,0 +1,33 @@
using System;
using System.IO;
namespace Org.BouncyCastle.Asn1
{
public class LazyAsn1InputStream
: Asn1InputStream
{
public LazyAsn1InputStream(
byte[] input)
: base(input)
{
}
public LazyAsn1InputStream(
Stream inputStream)
: base(inputStream)
{
}
internal override DerSequence CreateDerSequence(
DefiniteLengthInputStream dIn)
{
return new LazyDerSequence(dIn.ToArray());
}
internal override DerSet CreateDerSet(
DefiniteLengthInputStream dIn)
{
return new LazyDerSet(dIn.ToArray());
}
}
}

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections;
using System.Diagnostics;
namespace Org.BouncyCastle.Asn1
{
internal class LazyDerSequence
: DerSequence
{
private byte[] encoded;
private bool parsed = false;
internal LazyDerSequence(
byte[] encoded)
{
this.encoded = encoded;
}
private void Parse()
{
Debug.Assert(parsed == false);
Asn1InputStream e = new LazyAsn1InputStream(encoded);
Asn1Object o;
while ((o = e.ReadObject()) != null)
{
AddObject(o);
}
encoded = null;
parsed = true;
}
public override Asn1Encodable this[int index]
{
get
{
if (!parsed)
{
Parse();
}
return base[index];
}
}
public override IEnumerator GetEnumerator()
{
if (!parsed)
{
Parse();
}
return base.GetEnumerator();
}
public override int Count
{
get
{
if (!parsed)
{
Parse();
}
return base.Count;
}
}
internal override void Encode(
DerOutputStream derOut)
{
if (parsed)
{
base.Encode(derOut);
}
else
{
derOut.WriteEncoded(Asn1Tags.Sequence | Asn1Tags.Constructed, encoded);
}
}
}
}

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections;
using System.Diagnostics;
namespace Org.BouncyCastle.Asn1
{
internal class LazyDerSet
: DerSet
{
private byte[] encoded;
private bool parsed = false;
internal LazyDerSet(
byte[] encoded)
{
this.encoded = encoded;
}
private void Parse()
{
Debug.Assert(parsed == false);
Asn1InputStream e = new LazyAsn1InputStream(encoded);
Asn1Object o;
while ((o = e.ReadObject()) != null)
{
AddObject(o);
}
encoded = null;
parsed = true;
}
public override Asn1Encodable this[int index]
{
get
{
if (!parsed)
{
Parse();
}
return base[index];
}
}
public override IEnumerator GetEnumerator()
{
if (!parsed)
{
Parse();
}
return base.GetEnumerator();
}
public override int Count
{
get
{
if (!parsed)
{
Parse();
}
return base.Count;
}
}
internal override void Encode(
DerOutputStream derOut)
{
if (parsed)
{
base.Encode(derOut);
}
else
{
derOut.WriteEncoded(Asn1Tags.Set | Asn1Tags.Constructed, encoded);
}
}
}
}

View File

@@ -0,0 +1,26 @@
using System.IO;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Asn1
{
internal abstract class LimitedInputStream
: BaseInputStream
{
protected readonly Stream _in;
internal LimitedInputStream(
Stream inStream)
{
this._in = inStream;
}
protected virtual void SetParentEofDetect(bool on)
{
if (_in is IndefiniteLengthInputStream)
{
((IndefiniteLengthInputStream)_in).SetEofOn00(on);
}
}
}
}

View File

@@ -0,0 +1,45 @@
namespace Org.BouncyCastle.Asn1
{
/**
* class for breaking up an Oid into it's component tokens, ala
* java.util.StringTokenizer. We need this class as some of the
* lightweight Java environment don't support classes like
* StringTokenizer.
*/
public class OidTokenizer
{
private string oid;
private int index;
public OidTokenizer(
string oid)
{
this.oid = oid;
}
public bool HasMoreTokens
{
get { return index != -1; }
}
public string NextToken()
{
if (index == -1)
{
return null;
}
int end = oid.IndexOf('.', index);
if (end == -1)
{
string lastToken = oid.Substring(index);
index = -1;
return lastToken;
}
string nextToken = oid.Substring(index, end - index);
index = end + 1;
return nextToken;
}
}
}

View File

@@ -0,0 +1,73 @@
using System;
namespace Org.BouncyCastle.Asn1.Cmp
{
/**
* <pre>
* PKIFailureInfo ::= BIT STRING {
* badAlg (0),
* -- unrecognized or unsupported Algorithm Identifier
* badMessageCheck (1), -- integrity check failed (e.g., signature did not verify)
* badRequest (2),
* -- transaction not permitted or supported
* badTime (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
* badCertId (4), -- no certificate could be found matching the provided criteria
* badDataFormat (5),
* -- the data submitted has the wrong format
* wrongAuthority (6), -- the authority indicated in the request is different from the one creating the response token
* incorrectData (7), -- the requester's data is incorrect (for notary services)
* missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
* badPOP (9) -- the proof-of-possession failed
* timeNotAvailable (14),
* -- the TSA's time source is not available
* unacceptedPolicy (15),
* -- the requested TSA policy is not supported by the TSA
* unacceptedExtension (16),
* -- the requested extension is not supported by the TSA
* addInfoNotAvailable (17)
* -- the additional information requested could not be understood
* -- or is not available
* systemFailure (25)
* -- the request cannot be handled due to system failure
* </pre>
*/
public class PkiFailureInfo
: DerBitString
{
public const int BadAlg = (1 << 7); // unrecognized or unsupported Algorithm Identifier
public const int BadMessageCheck = (1 << 6); // integrity check failed (e.g., signature did not verify)
public const int BadRequest = (1 << 5);
public const int BadTime = (1 << 4); // -- messageTime was not sufficiently close to the system time, as defined by local policy
public const int BadCertId = (1 << 3); // no certificate could be found matching the provided criteria
public const int BadDataFormat = (1 << 2);
public const int WrongAuthority = (1 << 1); // the authority indicated in the request is different from the one creating the response token
public const int IncorrectData = 1; // the requester's data is incorrect (for notary services)
public const int MissingTimeStamp = (1 << 15); // when the timestamp is missing but should be there (by policy)
public const int BadPop = (1 << 14); // the proof-of-possession failed
public const int TimeNotAvailable = (1 << 9); // the TSA's time source is not available
public const int UnacceptedPolicy = (1 << 8); // the requested TSA policy is not supported by the TSA
public const int UnacceptedExtension = (1 << 23); //the requested extension is not supported by the TSA
public const int AddInfoNotAvailable = (1 << 22); //the additional information requested could not be understood or is not available
public const int SystemFailure = (1 << 30); //the request cannot be handled due to system failure
/**
* Basic constructor.
*/
public PkiFailureInfo(
int info)
: base(GetBytes(info), GetPadBits(info))
{
}
public PkiFailureInfo(
DerBitString info)
: base(info.GetBytes(), info.PadBits)
{
}
public override string ToString()
{
return "PkiFailureInfo: 0x" + this.IntValue.ToString("X");
}
}
}

View File

@@ -0,0 +1,97 @@
using System;
using System.Collections;
namespace Org.BouncyCastle.Asn1.Cmp
{
public class PkiFreeText
: Asn1Encodable
{
internal Asn1Sequence strings;
public static PkiFreeText GetInstance(
Asn1TaggedObject obj,
bool isExplicit)
{
return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
}
public static PkiFreeText GetInstance(
object obj)
{
if (obj is PkiFreeText)
{
return (PkiFreeText)obj;
}
else if (obj is Asn1Sequence)
{
return new PkiFreeText((Asn1Sequence)obj);
}
throw new ArgumentException("Unknown object in factory: " + obj.GetType().Name, "obj");
}
public PkiFreeText(
Asn1Sequence seq)
{
foreach (object o in seq)
{
if (!(o is DerUtf8String))
{
throw new ArgumentException("attempt to insert non UTF8 STRING into PkiFreeText");
}
}
this.strings = seq;
}
public PkiFreeText(
DerUtf8String p)
{
strings = new DerSequence(p);
}
/**
* Return the number of string elements present.
*
* @return number of elements present.
*/
[Obsolete("Use 'Count' property instead")]
public int Size
{
get { return strings.Count; }
}
public int Count
{
get { return strings.Count; }
}
/**
* Return the UTF8STRING at index.
*
* @param index index of the string of interest
* @return the string at index.
*/
public DerUtf8String this[int index]
{
get { return (DerUtf8String) strings[index]; }
}
[Obsolete("Use 'object[index]' syntax instead")]
public DerUtf8String GetStringAt(
int index)
{
return this[index];
}
/**
* <pre>
* PkiFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
return strings;
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
namespace Org.BouncyCastle.Asn1.Cmp
{
public enum PkiStatus
{
Granted = 0,
GrantedWithMods = 1,
Rejection = 2,
Waiting = 3,
RevocationWarning = 4,
RevocationNotification = 5,
}
}

View File

@@ -0,0 +1,165 @@
using System;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Asn1.Cmp
{
public class PkiStatusInfo
: Asn1Encodable
{
DerInteger status;
PkiFreeText statusString;
DerBitString failInfo;
public static PkiStatusInfo GetInstance(
Asn1TaggedObject obj,
bool isExplicit)
{
return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
}
public static PkiStatusInfo GetInstance(
object obj)
{
if (obj is PkiStatusInfo)
{
return (PkiStatusInfo)obj;
}
else if (obj is Asn1Sequence)
{
return new PkiStatusInfo((Asn1Sequence)obj);
}
throw new ArgumentException("Unknown object in factory: " + obj.GetType().Name, "obj");
}
public PkiStatusInfo(
Asn1Sequence seq)
{
this.status = DerInteger.GetInstance(seq[0]);
this.statusString = null;
this.failInfo = null;
if (seq.Count > 2)
{
this.statusString = PkiFreeText.GetInstance(seq[1]);
this.failInfo = DerBitString.GetInstance(seq[2]);
}
else if (seq.Count > 1)
{
object obj = seq[1];
if (obj is DerBitString)
{
this.failInfo = DerBitString.GetInstance(obj);
}
else
{
this.statusString = PkiFreeText.GetInstance(obj);
}
}
}
/**
* @param status
*/
public PkiStatusInfo(int status)
{
this.status = new DerInteger(status);
}
/**
* @param status
* @param statusString
*/
public PkiStatusInfo(
int status,
PkiFreeText statusString)
{
this.status = new DerInteger(status);
this.statusString = statusString;
}
public PkiStatusInfo(
int status,
PkiFreeText statusString,
PkiFailureInfo failInfo)
{
this.status = new DerInteger(status);
this.statusString = statusString;
this.failInfo = failInfo;
}
public BigInteger Status
{
get
{
return status.Value;
}
}
public PkiFreeText StatusString
{
get
{
return statusString;
}
}
public DerBitString FailInfo
{
get
{
return failInfo;
}
}
/**
* <pre>
* PkiStatusInfo ::= SEQUENCE {
* status PKIStatus, (INTEGER)
* statusString PkiFreeText OPTIONAL,
* failInfo PkiFailureInfo OPTIONAL (BIT STRING)
* }
*
* PKIStatus:
* granted (0), -- you got exactly what you asked for
* grantedWithMods (1), -- you got something like what you asked for
* rejection (2), -- you don't get it, more information elsewhere in the message
* waiting (3), -- the request body part has not yet been processed, expect to hear more later
* revocationWarning (4), -- this message contains a warning that a revocation is imminent
* revocationNotification (5), -- notification that a revocation has occurred
* keyUpdateWarning (6) -- update already done for the oldCertId specified in CertReqMsg
*
* PkiFailureInfo:
* badAlg (0), -- unrecognized or unsupported Algorithm Identifier
* badMessageCheck (1), -- integrity check failed (e.g., signature did not verify)
* badRequest (2), -- transaction not permitted or supported
* badTime (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
* badCertId (4), -- no certificate could be found matching the provided criteria
* badDataFormat (5), -- the data submitted has the wrong format
* wrongAuthority (6), -- the authority indicated in the request is different from the one creating the response token
* incorrectData (7), -- the requester's data is incorrect (for notary services)
* missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
* badPOP (9) -- the proof-of-possession failed
*
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
Asn1EncodableVector v = new Asn1EncodableVector(status);
if (statusString != null)
{
v.Add(statusString);
}
if (failInfo!= null)
{
v.Add(failInfo);
}
return new DerSequence(v);
}
}
}

View File

@@ -0,0 +1,68 @@
using System;
using Org.BouncyCastle.Asn1;
namespace Org.BouncyCastle.Asn1.Cms
{
public class Attribute
: Asn1Encodable
{
private DerObjectIdentifier attrType;
private Asn1Set attrValues;
/**
* return an Attribute object from the given object.
*
* @param o the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static Attribute GetInstance(
object obj)
{
if (obj == null || obj is Attribute)
{
return (Attribute) obj;
}
if (obj is Asn1Sequence)
{
return new Attribute((Asn1Sequence) obj);
}
throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
}
public Attribute(
Asn1Sequence seq)
{
attrType = (DerObjectIdentifier)seq[0];
attrValues = (Asn1Set)seq[1];
}
public Attribute(
DerObjectIdentifier attrType,
Asn1Set attrValues)
{
this.attrType = attrType;
this.attrValues = attrValues;
}
public DerObjectIdentifier AttrType { get { return attrType; } }
public Asn1Set AttrValues { get { return attrValues; } }
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* Attribute ::= SEQUENCE {
* attrType OBJECT IDENTIFIER,
* attrValues SET OF AttributeValue
* }
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
return new DerSequence(attrType, attrValues);
}
}
}

View File

@@ -0,0 +1,155 @@
using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
namespace Org.BouncyCastle.Asn1.Cms
{
public class AttributeTable
{
private readonly Hashtable attributes;
public AttributeTable(
Hashtable attrs)
{
this.attributes = new Hashtable(attrs);
}
public AttributeTable(
Asn1EncodableVector v)
{
this.attributes = new Hashtable(v.Count);
foreach (Asn1Encodable o in v)
{
Attribute a = Attribute.GetInstance(o);
AddAttribute(a);
}
}
public AttributeTable(
Asn1Set s)
{
this.attributes = new Hashtable(s.Count);
for (int i = 0; i != s.Count; i++)
{
Attribute a = Attribute.GetInstance(s[i]);
AddAttribute(a);
}
}
private void AddAttribute(
Attribute a)
{
DerObjectIdentifier oid = a.AttrType;
object obj = attributes[oid];
if (obj == null)
{
attributes[oid] = a;
}
else
{
ArrayList v;
if (obj is Attribute)
{
v = new ArrayList();
v.Add(obj);
v.Add(a);
}
else
{
v = (ArrayList) obj;
v.Add(a);
}
attributes[oid] = v;
}
}
/// <summary>Return the first attribute matching the given OBJECT IDENTIFIER</summary>
public Attribute this[DerObjectIdentifier oid]
{
get
{
object obj = attributes[oid];
if (obj is ArrayList)
{
return (Attribute)((ArrayList)obj)[0];
}
return (Attribute) obj;
}
}
[Obsolete("Use 'object[oid]' syntax instead")]
public Attribute Get(
DerObjectIdentifier oid)
{
return this[oid];
}
/**
* Return all the attributes matching the OBJECT IDENTIFIER oid. The vector will be
* empty if there are no attributes of the required type present.
*
* @param oid type of attribute required.
* @return a vector of all the attributes found of type oid.
*/
public Asn1EncodableVector GetAll(
DerObjectIdentifier oid)
{
Asn1EncodableVector v = new Asn1EncodableVector();
object obj = attributes[oid];
if (obj is ArrayList)
{
foreach (Attribute a in (ArrayList)obj)
{
v.Add(a);
}
}
else if (obj != null)
{
v.Add((Attribute) obj);
}
return v;
}
public Hashtable ToHashtable()
{
return new Hashtable(attributes);
}
public Asn1EncodableVector ToAsn1EncodableVector()
{
Asn1EncodableVector v = new Asn1EncodableVector();
foreach (object obj in attributes.Values)
{
if (obj is ArrayList)
{
foreach (object el in (ArrayList)obj)
{
v.Add(Attribute.GetInstance(el));
}
}
else
{
v.Add(Attribute.GetInstance(obj));
}
}
return v;
}
}
}

View File

@@ -0,0 +1,13 @@
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
namespace Org.BouncyCastle.Asn1.Cms
{
public abstract class CmsAttributes
{
public static readonly DerObjectIdentifier ContentType = PkcsObjectIdentifiers.Pkcs9AtContentType;
public static readonly DerObjectIdentifier MessageDigest = PkcsObjectIdentifiers.Pkcs9AtMessageDigest;
public static readonly DerObjectIdentifier SigningTime = PkcsObjectIdentifiers.Pkcs9AtSigningTime;
public static readonly DerObjectIdentifier CounterSignature = PkcsObjectIdentifiers.Pkcs9AtCounterSignature;
}
}

View File

@@ -0,0 +1,15 @@
using Org.BouncyCastle.Asn1.Pkcs;
namespace Org.BouncyCastle.Asn1.Cms
{
public abstract class CmsObjectIdentifiers
{
public static readonly DerObjectIdentifier Data = PkcsObjectIdentifiers.Data;
public static readonly DerObjectIdentifier SignedData = PkcsObjectIdentifiers.SignedData;
public static readonly DerObjectIdentifier EnvelopedData = PkcsObjectIdentifiers.EnvelopedData;
public static readonly DerObjectIdentifier SignedAndEnvelopedData = PkcsObjectIdentifiers.SignedAndEnvelopedData;
public static readonly DerObjectIdentifier DigestedData = PkcsObjectIdentifiers.DigestedData;
public static readonly DerObjectIdentifier EncryptedData = PkcsObjectIdentifiers.EncryptedData;
public static readonly DerObjectIdentifier CompressedData = PkcsObjectIdentifiers.IdCTCompressedData;
}
}

View File

@@ -0,0 +1,100 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Asn1.Cms
{
/**
* RFC 3274 - CMS Compressed Data.
* <pre>
* CompressedData ::= Sequence {
* version CMSVersion,
* compressionAlgorithm CompressionAlgorithmIdentifier,
* encapContentInfo EncapsulatedContentInfo
* }
* </pre>
*/
public class CompressedData
: Asn1Encodable
{
private DerInteger version;
private AlgorithmIdentifier compressionAlgorithm;
private ContentInfo encapContentInfo;
public CompressedData(
AlgorithmIdentifier compressionAlgorithm,
ContentInfo encapContentInfo)
{
this.version = new DerInteger(0);
this.compressionAlgorithm = compressionAlgorithm;
this.encapContentInfo = encapContentInfo;
}
public CompressedData(
Asn1Sequence seq)
{
this.version = (DerInteger) seq[0];
this.compressionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
this.encapContentInfo = ContentInfo.GetInstance(seq[2]);
}
/**
* return a CompressedData object from a tagged object.
*
* @param ato the tagged object holding the object we want.
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the object held by the
* tagged object cannot be converted.
*/
public static CompressedData GetInstance(
Asn1TaggedObject ato,
bool explicitly)
{
return GetInstance(Asn1Sequence.GetInstance(ato, explicitly));
}
/**
* return a CompressedData object from the given object.
*
* @param _obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static CompressedData GetInstance(
object obj)
{
if (obj == null || obj is CompressedData)
{
return (CompressedData)obj;
}
if (obj is Asn1Sequence)
{
return new CompressedData((Asn1Sequence) obj);
}
throw new ArgumentException("Invalid CompressedData: " + obj.GetType().Name);
}
public DerInteger Version
{
get { return version; }
}
public AlgorithmIdentifier CompressionAlgorithmIdentifier
{
get { return compressionAlgorithm; }
}
public ContentInfo EncapContentInfo
{
get { return encapContentInfo; }
}
public override Asn1Object ToAsn1Object()
{
return new BerSequence(version, compressionAlgorithm, encapContentInfo);
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Asn1.Cms
{
/**
* RFC 3274 - CMS Compressed Data.
* <pre>
* CompressedData ::= SEQUENCE {
* version CMSVersion,
* compressionAlgorithm CompressionAlgorithmIdentifier,
* encapContentInfo EncapsulatedContentInfo
* }
* </pre>
*/
public class CompressedDataParser
{
private DerInteger _version;
private AlgorithmIdentifier _compressionAlgorithm;
private ContentInfoParser _encapContentInfo;
public CompressedDataParser(
Asn1SequenceParser seq)
{
this._version = (DerInteger)seq.ReadObject();
this._compressionAlgorithm = AlgorithmIdentifier.GetInstance(seq.ReadObject().ToAsn1Object());
this._encapContentInfo = new ContentInfoParser((Asn1SequenceParser)seq.ReadObject());
}
public DerInteger Version
{
get { return _version; }
}
public AlgorithmIdentifier CompressionAlgorithmIdentifier
{
get { return _compressionAlgorithm; }
}
public ContentInfoParser GetEncapContentInfo()
{
return _encapContentInfo;
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
namespace Org.BouncyCastle.Asn1.Cms
{
public class ContentInfo
: Asn1Encodable
{
private readonly DerObjectIdentifier contentType;
private readonly Asn1Encodable content;
public static ContentInfo GetInstance(
object obj)
{
if (obj == null || obj is ContentInfo)
{
return (ContentInfo) obj;
}
if (obj is Asn1Sequence)
{
return new ContentInfo((Asn1Sequence) obj);
}
throw new ArgumentException("unknown object in factory: " + obj.GetType().Name);
}
private ContentInfo(
Asn1Sequence seq)
{
if (seq.Count < 1 || seq.Count > 2)
throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
contentType = (DerObjectIdentifier) seq[0];
if (seq.Count > 1)
{
Asn1TaggedObject optOcts = (Asn1TaggedObject) seq[1];
if (optOcts.TagNo != 0)
throw new ArgumentException("Tag number for 'content' must be 0");
content = optOcts.GetObject();
}
}
public ContentInfo(
DerObjectIdentifier contentType,
Asn1Encodable content)
{
this.contentType = contentType;
this.content = content;
}
public DerObjectIdentifier ContentType
{
get { return contentType; }
}
public Asn1Encodable Content
{
get { return content; }
}
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* ContentInfo ::= Sequence {
* contentType ContentType,
* content
* [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
Asn1EncodableVector v = new Asn1EncodableVector(contentType);
if (content != null)
{
v.Add(new BerTaggedObject(0, content));
}
return new BerSequence(v);
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
namespace Org.BouncyCastle.Asn1.Cms
{
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* ContentInfo ::= SEQUENCE {
* contentType ContentType,
* content
* [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
* </pre>
*/
public class ContentInfoParser
{
private DerObjectIdentifier contentType;
private Asn1TaggedObjectParser content;
public ContentInfoParser(
Asn1SequenceParser seq)
{
contentType = (DerObjectIdentifier)seq.ReadObject();
content = (Asn1TaggedObjectParser)seq.ReadObject();
}
public DerObjectIdentifier ContentType
{
get { return contentType; }
}
public IAsn1Convertible GetContent(
int tag)
{
if (content == null)
return null;
return content.GetObjectParser(tag, true);
}
}
}

View File

@@ -0,0 +1,98 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Asn1.Cms
{
public class EncryptedContentInfo
: Asn1Encodable
{
private DerObjectIdentifier contentType;
private AlgorithmIdentifier contentEncryptionAlgorithm;
private Asn1OctetString encryptedContent;
public EncryptedContentInfo(
DerObjectIdentifier contentType,
AlgorithmIdentifier contentEncryptionAlgorithm,
Asn1OctetString encryptedContent)
{
this.contentType = contentType;
this.contentEncryptionAlgorithm = contentEncryptionAlgorithm;
this.encryptedContent = encryptedContent;
}
public EncryptedContentInfo(
Asn1Sequence seq)
{
contentType = (DerObjectIdentifier) seq[0];
contentEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
if (seq.Count > 2)
{
encryptedContent = Asn1OctetString.GetInstance(
(Asn1TaggedObject) seq[2], false);
}
}
/**
* return an EncryptedContentInfo object from the given object.
*
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static EncryptedContentInfo GetInstance(
object obj)
{
if (obj == null || obj is EncryptedContentInfo)
{
return (EncryptedContentInfo)obj;
}
if (obj is Asn1Sequence)
{
return new EncryptedContentInfo((Asn1Sequence)obj);
}
throw new ArgumentException("Invalid EncryptedContentInfo: " + obj.GetType().Name);
}
public DerObjectIdentifier ContentType
{
get { return contentType; }
}
public AlgorithmIdentifier ContentEncryptionAlgorithm
{
get { return contentEncryptionAlgorithm; }
}
public Asn1OctetString EncryptedContent
{
get { return encryptedContent; }
}
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* EncryptedContentInfo ::= Sequence {
* contentType ContentType,
* contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
* }
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
Asn1EncodableVector v = new Asn1EncodableVector(
contentType, contentEncryptionAlgorithm);
if (encryptedContent != null)
{
v.Add(new BerTaggedObject(false, 0, encryptedContent));
}
return new BerSequence(v);
}
}
}

View File

@@ -0,0 +1,46 @@
using System;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Asn1.Cms
{
/**
* <pre>
* EncryptedContentInfo ::= SEQUENCE {
* contentType ContentType,
* contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
* }
* </pre>
*/
public class EncryptedContentInfoParser
{
private DerObjectIdentifier _contentType;
private AlgorithmIdentifier _contentEncryptionAlgorithm;
private Asn1TaggedObjectParser _encryptedContent;
public EncryptedContentInfoParser(
Asn1SequenceParser seq)
{
_contentType = (DerObjectIdentifier)seq.ReadObject();
_contentEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq.ReadObject().ToAsn1Object());
_encryptedContent = (Asn1TaggedObjectParser)seq.ReadObject();
}
public DerObjectIdentifier ContentType
{
get { return _contentType; }
}
public AlgorithmIdentifier ContentEncryptionAlgorithm
{
get { return _contentEncryptionAlgorithm; }
}
public IAsn1Convertible GetEncryptedContent(
int tag)
{
return _encryptedContent.GetObjectParser(tag, false);
}
}
}

View File

@@ -0,0 +1,95 @@
using System;
namespace Org.BouncyCastle.Asn1.Cms
{
public class EncryptedData
: Asn1Encodable
{
private readonly DerInteger version;
private readonly EncryptedContentInfo encryptedContentInfo;
private readonly Asn1Set unprotectedAttrs;
public static EncryptedData GetInstance(
object obj)
{
if (obj is EncryptedData)
return (EncryptedData) obj;
if (obj is Asn1Sequence)
return new EncryptedData((Asn1Sequence) obj);
throw new ArgumentException("Invalid EncryptedData: " + obj.GetType().Name);
}
public EncryptedData(
EncryptedContentInfo encInfo)
: this(encInfo, null)
{
}
public EncryptedData(
EncryptedContentInfo encInfo,
Asn1Set unprotectedAttrs)
{
if (encInfo == null)
throw new ArgumentNullException("encInfo");
this.version = new DerInteger((unprotectedAttrs == null) ? 0 : 2);
this.encryptedContentInfo = encInfo;
this.unprotectedAttrs = unprotectedAttrs;
}
private EncryptedData(
Asn1Sequence seq)
{
if (seq == null)
throw new ArgumentNullException("seq");
if (seq.Count < 2 || seq.Count > 3)
throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
this.version = DerInteger.GetInstance(seq[0]);
this.encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[1]);
if (seq.Count > 2)
{
this.unprotectedAttrs = Asn1Set.GetInstance(seq[2]);
}
}
public virtual DerInteger Version
{
get { return version; }
}
public virtual EncryptedContentInfo EncryptedContentInfo
{
get { return encryptedContentInfo; }
}
public virtual Asn1Set UnprotectedAttrs
{
get { return unprotectedAttrs; }
}
/**
* <pre>
* EncryptedData ::= SEQUENCE {
* version CMSVersion,
* encryptedContentInfo EncryptedContentInfo,
* unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
* </pre>
* @return a basic ASN.1 object representation.
*/
public override Asn1Object ToAsn1Object()
{
Asn1EncodableVector v = new Asn1EncodableVector(version, encryptedContentInfo);
if (unprotectedAttrs != null)
{
v.Add(new BerTaggedObject(false, 1, unprotectedAttrs));
}
return new BerSequence(v);
}
}
}

View File

@@ -0,0 +1,152 @@
using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
namespace Org.BouncyCastle.Asn1.Cms
{
public class EnvelopedData
: Asn1Encodable
{
private DerInteger version;
private OriginatorInfo originatorInfo;
private Asn1Set recipientInfos;
private EncryptedContentInfo encryptedContentInfo;
private Asn1Set unprotectedAttrs;
public EnvelopedData(
OriginatorInfo originatorInfo,
Asn1Set recipientInfos,
EncryptedContentInfo encryptedContentInfo,
Asn1Set unprotectedAttrs)
{
if (originatorInfo != null || unprotectedAttrs != null)
{
version = new DerInteger(2);
}
else
{
version = new DerInteger(0);
foreach (object o in recipientInfos)
{
RecipientInfo ri = RecipientInfo.GetInstance(o);
if (!ri.Version.Equals(version))
{
version = new DerInteger(2);
break;
}
}
}
this.originatorInfo = originatorInfo;
this.recipientInfos = recipientInfos;
this.encryptedContentInfo = encryptedContentInfo;
this.unprotectedAttrs = unprotectedAttrs;
}
public EnvelopedData(
Asn1Sequence seq)
{
int index = 0;
version = (DerInteger) seq[index++];
object tmp = seq[index++];
if (tmp is Asn1TaggedObject)
{
originatorInfo = OriginatorInfo.GetInstance((Asn1TaggedObject) tmp, false);
tmp = seq[index++];
}
recipientInfos = Asn1Set.GetInstance(tmp);
encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[index++]);
if (seq.Count > index)
{
unprotectedAttrs = Asn1Set.GetInstance((Asn1TaggedObject) seq[index], false);
}
}
/**
* return an EnvelopedData object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the object held by the
* tagged object cannot be converted.
*/
public static EnvelopedData GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
}
/**
* return an EnvelopedData object from the given object.
*
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static EnvelopedData GetInstance(
object obj)
{
if (obj == null || obj is EnvelopedData)
{
return (EnvelopedData)obj;
}
if (obj is Asn1Sequence)
{
return new EnvelopedData((Asn1Sequence)obj);
}
throw new ArgumentException("Invalid EnvelopedData: " + obj.GetType().Name);
}
public DerInteger Version { get { return version; } }
public OriginatorInfo OriginatorInfo { get { return originatorInfo; } }
public Asn1Set RecipientInfos { get { return recipientInfos; } }
public EncryptedContentInfo EncryptedContentInfo { get { return encryptedContentInfo; } }
public Asn1Set UnprotectedAttrs { get { return unprotectedAttrs; } }
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* EnvelopedData ::= Sequence {
* version CMSVersion,
* originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
* recipientInfos RecipientInfos,
* encryptedContentInfo EncryptedContentInfo,
* unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
* }
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
Asn1EncodableVector v = new Asn1EncodableVector(version);
if (originatorInfo != null)
{
v.Add(new DerTaggedObject(false, 0, originatorInfo));
}
v.Add(recipientInfos, encryptedContentInfo);
if (unprotectedAttrs != null)
{
v.Add(new DerTaggedObject(false, 1, unprotectedAttrs));
}
return new BerSequence(v);
}
}
}

View File

@@ -0,0 +1,106 @@
using System;
namespace Org.BouncyCastle.Asn1.Cms
{
/**
* <pre>
* EnvelopedData ::= SEQUENCE {
* version CMSVersion,
* originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
* recipientInfos RecipientInfos,
* encryptedContentInfo EncryptedContentInfo,
* unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
* }
* </pre>
*/
public class EnvelopedDataParser
{
private Asn1SequenceParser _seq;
private DerInteger _version;
private IAsn1Convertible _nextObject;
private bool _originatorInfoCalled;
public EnvelopedDataParser(
Asn1SequenceParser seq)
{
this._seq = seq;
this._version = (DerInteger)seq.ReadObject();
}
public DerInteger Version
{
get { return _version; }
}
public OriginatorInfo GetOriginatorInfo()
{
_originatorInfoCalled = true;
if (_nextObject == null)
{
_nextObject = _seq.ReadObject();
}
if (_nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)_nextObject).TagNo == 0)
{
Asn1SequenceParser originatorInfo = (Asn1SequenceParser)
((Asn1TaggedObjectParser)_nextObject).GetObjectParser(Asn1Tags.Sequence, false);
_nextObject = null;
return OriginatorInfo.GetInstance(originatorInfo.ToAsn1Object());
}
return null;
}
public Asn1SetParser GetRecipientInfos()
{
if (!_originatorInfoCalled)
{
GetOriginatorInfo();
}
if (_nextObject == null)
{
_nextObject = _seq.ReadObject();
}
Asn1SetParser recipientInfos = (Asn1SetParser)_nextObject;
_nextObject = null;
return recipientInfos;
}
public EncryptedContentInfoParser GetEncryptedContentInfo()
{
if (_nextObject == null)
{
_nextObject = _seq.ReadObject();
}
if (_nextObject != null)
{
Asn1SequenceParser o = (Asn1SequenceParser) _nextObject;
_nextObject = null;
return new EncryptedContentInfoParser(o);
}
return null;
}
public Asn1SetParser GetUnprotectedAttrs()
{
if (_nextObject == null)
{
_nextObject = _seq.ReadObject();
}
if (_nextObject != null)
{
IAsn1Convertible o = _nextObject;
_nextObject = null;
return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false);
}
return null;
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Asn1.Cms
{
public class IssuerAndSerialNumber
: Asn1Encodable
{
X509Name name;
DerInteger serialNumber;
public static IssuerAndSerialNumber GetInstance(
object obj)
{
if (obj is IssuerAndSerialNumber)
{
return (IssuerAndSerialNumber)obj;
}
if (obj is Asn1Sequence)
{
return new IssuerAndSerialNumber((Asn1Sequence)obj);
}
throw new ArgumentException(
"Illegal object in IssuerAndSerialNumber: " + obj.GetType().Name);
}
public IssuerAndSerialNumber(
Asn1Sequence seq)
{
this.name = X509Name.GetInstance(seq[0]);
this.serialNumber = (DerInteger) seq[1];
}
public IssuerAndSerialNumber(
X509Name name,
BigInteger serialNumber)
{
this.name = name;
this.serialNumber = new DerInteger(serialNumber);
}
public IssuerAndSerialNumber(
X509Name name,
DerInteger serialNumber)
{
this.name = name;
this.serialNumber = serialNumber;
}
public X509Name Name
{
get { return name; }
}
public DerInteger SerialNumber
{
get { return serialNumber; }
}
public override Asn1Object ToAsn1Object()
{
return new DerSequence(name, serialNumber);
}
}
}

View File

@@ -0,0 +1,133 @@
using System;
using Org.BouncyCastle.Asn1;
namespace Org.BouncyCastle.Asn1.Cms
{
public class KekIdentifier
: Asn1Encodable
{
private Asn1OctetString keyIdentifier;
private DerGeneralizedTime date;
private OtherKeyAttribute other;
public KekIdentifier(
byte[] keyIdentifier,
DerGeneralizedTime date,
OtherKeyAttribute other)
{
this.keyIdentifier = new DerOctetString(keyIdentifier);
this.date = date;
this.other = other;
}
public KekIdentifier(
Asn1Sequence seq)
{
keyIdentifier = (Asn1OctetString) seq[0];
switch (seq.Count)
{
case 1:
break;
case 2:
if (seq[1] is DerGeneralizedTime)
{
date = (DerGeneralizedTime) seq[1];
}
else
{
other = OtherKeyAttribute.GetInstance(seq[2]);
}
break;
case 3:
date = (DerGeneralizedTime) seq[1];
other = OtherKeyAttribute.GetInstance(seq[2]);
break;
default:
throw new ArgumentException("Invalid KekIdentifier");
}
}
/**
* return a KekIdentifier object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the object held by the
* tagged object cannot be converted.
*/
public static KekIdentifier GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
}
/**
* return a KekIdentifier object from the given object.
*
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static KekIdentifier GetInstance(
object obj)
{
if (obj == null || obj is KekIdentifier)
{
return (KekIdentifier)obj;
}
if (obj is Asn1Sequence)
{
return new KekIdentifier((Asn1Sequence)obj);
}
throw new ArgumentException("Invalid KekIdentifier: " + obj.GetType().Name);
}
public Asn1OctetString KeyIdentifier
{
get { return keyIdentifier; }
}
public DerGeneralizedTime Date
{
get { return date; }
}
public OtherKeyAttribute Other
{
get { return other; }
}
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* KekIdentifier ::= Sequence {
* keyIdentifier OCTET STRING,
* date GeneralizedTime OPTIONAL,
* other OtherKeyAttribute OPTIONAL
* }
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
Asn1EncodableVector v = new Asn1EncodableVector(keyIdentifier);
if (date != null)
{
v.Add(date);
}
if (other != null)
{
v.Add(other);
}
return new DerSequence(v);
}
}
}

View File

@@ -0,0 +1,110 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Asn1.Cms
{
public class KekRecipientInfo
: Asn1Encodable
{
private DerInteger version;
private KekIdentifier kekID;
private AlgorithmIdentifier keyEncryptionAlgorithm;
private Asn1OctetString encryptedKey;
public KekRecipientInfo(
KekIdentifier kekID,
AlgorithmIdentifier keyEncryptionAlgorithm,
Asn1OctetString encryptedKey)
{
this.version = new DerInteger(4);
this.kekID = kekID;
this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
this.encryptedKey = encryptedKey;
}
public KekRecipientInfo(
Asn1Sequence seq)
{
version = (DerInteger) seq[0];
kekID = KekIdentifier.GetInstance(seq[1]);
keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]);
encryptedKey = (Asn1OctetString) seq[3];
}
/**
* return a KekRecipientInfo object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the object held by the
* tagged object cannot be converted.
*/
public static KekRecipientInfo GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
}
/**
* return a KekRecipientInfo object from the given object.
*
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static KekRecipientInfo GetInstance(
object obj)
{
if (obj == null || obj is KekRecipientInfo)
{
return (KekRecipientInfo)obj;
}
if(obj is Asn1Sequence)
{
return new KekRecipientInfo((Asn1Sequence)obj);
}
throw new ArgumentException("Invalid KekRecipientInfo: " + obj.GetType().Name);
}
public DerInteger Version
{
get { return version; }
}
public KekIdentifier KekID
{
get { return kekID; }
}
public AlgorithmIdentifier KeyEncryptionAlgorithm
{
get { return keyEncryptionAlgorithm; }
}
public Asn1OctetString EncryptedKey
{
get { return encryptedKey; }
}
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* KekRecipientInfo ::= Sequence {
* version CMSVersion, -- always set to 4
* kekID KekIdentifier,
* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
* encryptedKey EncryptedKey
* }
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
return new DerSequence(version, kekID, keyEncryptionAlgorithm, encryptedKey);
}
}
}

View File

@@ -0,0 +1,90 @@
using System;
namespace Org.BouncyCastle.Asn1.Cms
{
public class KeyAgreeRecipientIdentifier
: Asn1Encodable
{
/**
* return an KeyAgreeRecipientIdentifier object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param isExplicit true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the object held by the
* tagged object cannot be converted.
*/
public static KeyAgreeRecipientIdentifier GetInstance(
Asn1TaggedObject obj,
bool isExplicit)
{
return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
}
/**
* return an KeyAgreeRecipientIdentifier object from the given object.
*
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static KeyAgreeRecipientIdentifier GetInstance(
object obj)
{
if (obj == null || obj is KeyAgreeRecipientIdentifier)
{
return (KeyAgreeRecipientIdentifier)obj;
}
if (obj is Asn1Sequence)
{
return new KeyAgreeRecipientIdentifier((Asn1Sequence)obj);
}
throw new ArgumentException("Invalid KeyAgreeRecipientIdentifier: " + obj.GetType().FullName, "obj");
}
private readonly IssuerAndSerialNumber issuerSerial;
private const RecipientKeyIdentifier rKeyID = null;
public KeyAgreeRecipientIdentifier(
IssuerAndSerialNumber issuerSerial)
{
this.issuerSerial = issuerSerial;
}
private KeyAgreeRecipientIdentifier(
Asn1Sequence seq)
{
this.issuerSerial = IssuerAndSerialNumber.GetInstance(seq);
}
public IssuerAndSerialNumber IssuerAndSerialNumber
{
get { return issuerSerial; }
}
public RecipientKeyIdentifier RKeyID
{
get { return rKeyID; }
}
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* KeyAgreeRecipientIdentifier ::= CHOICE {
* issuerAndSerialNumber IssuerAndSerialNumber,
* rKeyId [0] IMPLICIT RecipientKeyIdentifier
* }
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
if (issuerSerial != null)
{
return issuerSerial.ToAsn1Object();
}
return new DerTaggedObject(false, 0, rKeyID);
}
}
}

View File

@@ -0,0 +1,143 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Asn1.Cms
{
public class KeyAgreeRecipientInfo
: Asn1Encodable
{
private DerInteger version;
private OriginatorIdentifierOrKey originator;
private Asn1OctetString ukm;
private AlgorithmIdentifier keyEncryptionAlgorithm;
private Asn1Sequence recipientEncryptedKeys;
public KeyAgreeRecipientInfo(
OriginatorIdentifierOrKey originator,
Asn1OctetString ukm,
AlgorithmIdentifier keyEncryptionAlgorithm,
Asn1Sequence recipientEncryptedKeys)
{
this.version = new DerInteger(3);
this.originator = originator;
this.ukm = ukm;
this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
this.recipientEncryptedKeys = recipientEncryptedKeys;
}
public KeyAgreeRecipientInfo(
Asn1Sequence seq)
{
int index = 0;
version = (DerInteger) seq[index++];
originator = OriginatorIdentifierOrKey.GetInstance(
(Asn1TaggedObject) seq[index++], true);
if (seq[index] is Asn1TaggedObject)
{
ukm = Asn1OctetString.GetInstance(
(Asn1TaggedObject) seq[index++], true);
}
keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(
seq[index++]);
recipientEncryptedKeys = (Asn1Sequence) seq[index++];
}
/**
* return a KeyAgreeRecipientInfo object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the object held by the
* tagged object cannot be converted.
*/
public static KeyAgreeRecipientInfo GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
}
/**
* return a KeyAgreeRecipientInfo object from the given object.
*
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static KeyAgreeRecipientInfo GetInstance(
object obj)
{
if (obj == null || obj is KeyAgreeRecipientInfo)
{
return (KeyAgreeRecipientInfo)obj;
}
if (obj is Asn1Sequence)
{
return new KeyAgreeRecipientInfo((Asn1Sequence)obj);
}
throw new ArgumentException(
"Illegal object in KeyAgreeRecipientInfo: " + obj.GetType().Name);
}
public DerInteger Version
{
get { return version; }
}
public OriginatorIdentifierOrKey Originator
{
get { return originator; }
}
public Asn1OctetString UserKeyingMaterial
{
get { return ukm; }
}
public AlgorithmIdentifier KeyEncryptionAlgorithm
{
get { return keyEncryptionAlgorithm; }
}
public Asn1Sequence RecipientEncryptedKeys
{
get { return recipientEncryptedKeys; }
}
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* KeyAgreeRecipientInfo ::= Sequence {
* version CMSVersion, -- always set to 3
* originator [0] EXPLICIT OriginatorIdentifierOrKey,
* ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL,
* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
* recipientEncryptedKeys RecipientEncryptedKeys
* }
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
Asn1EncodableVector v = new Asn1EncodableVector(
version, new DerTaggedObject(true, 0, originator));
if (ukm != null)
{
v.Add(new DerTaggedObject(true, 1, ukm));
}
v.Add(keyEncryptionAlgorithm, recipientEncryptedKeys);
return new DerSequence(v);
}
}
}

View File

@@ -0,0 +1,103 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Asn1.Cms
{
public class KeyTransRecipientInfo
: Asn1Encodable
{
private DerInteger version;
private RecipientIdentifier rid;
private AlgorithmIdentifier keyEncryptionAlgorithm;
private Asn1OctetString encryptedKey;
public KeyTransRecipientInfo(
RecipientIdentifier rid,
AlgorithmIdentifier keyEncryptionAlgorithm,
Asn1OctetString encryptedKey)
{
if (rid.ToAsn1Object() is Asn1TaggedObject)
{
this.version = new DerInteger(2);
}
else
{
this.version = new DerInteger(0);
}
this.rid = rid;
this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
this.encryptedKey = encryptedKey;
}
public KeyTransRecipientInfo(
Asn1Sequence seq)
{
this.version = (DerInteger) seq[0];
this.rid = RecipientIdentifier.GetInstance(seq[1]);
this.keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]);
this.encryptedKey = (Asn1OctetString) seq[3];
}
/**
* return a KeyTransRecipientInfo object from the given object.
*
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static KeyTransRecipientInfo GetInstance(
object obj)
{
if (obj == null || obj is KeyTransRecipientInfo)
{
return (KeyTransRecipientInfo) obj;
}
if(obj is Asn1Sequence)
{
return new KeyTransRecipientInfo((Asn1Sequence) obj);
}
throw new ArgumentException(
"Illegal object in KeyTransRecipientInfo: " + obj.GetType().Name);
}
public DerInteger Version
{
get { return version; }
}
public RecipientIdentifier RecipientIdentifier
{
get { return rid; }
}
public AlgorithmIdentifier KeyEncryptionAlgorithm
{
get { return keyEncryptionAlgorithm; }
}
public Asn1OctetString EncryptedKey
{
get { return encryptedKey; }
}
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* KeyTransRecipientInfo ::= Sequence {
* version CMSVersion, -- always set to 0 or 2
* rid RecipientIdentifier,
* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
* encryptedKey EncryptedKey
* }
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
return new DerSequence(version, rid, keyEncryptionAlgorithm, encryptedKey);
}
}
}

View File

@@ -0,0 +1,115 @@
using System;
using Org.BouncyCastle.Asn1;
namespace Org.BouncyCastle.Asn1.Cms
{
public class OriginatorIdentifierOrKey
: Asn1Encodable
{
private Asn1Encodable id;
public OriginatorIdentifierOrKey(
IssuerAndSerialNumber id)
{
this.id = id;
}
public OriginatorIdentifierOrKey(
Asn1OctetString id)
{
this.id = new DerTaggedObject(false, 0, id);
}
public OriginatorIdentifierOrKey(
OriginatorPublicKey id)
{
this.id = new DerTaggedObject(false, 1, id);
}
public OriginatorIdentifierOrKey(
Asn1Object id)
{
this.id = id;
}
/**
* return an OriginatorIdentifierOrKey object from a tagged object.
*
* @param o the tagged object holding the object we want.
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the object held by the
* tagged object cannot be converted.
*/
public static OriginatorIdentifierOrKey GetInstance(
Asn1TaggedObject o,
bool explicitly)
{
if (!explicitly)
{
throw new ArgumentException(
"Can't implicitly tag OriginatorIdentifierOrKey");
}
return GetInstance(o.GetObject());
}
/**
* return an OriginatorIdentifierOrKey object from the given object.
*
* @param o the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static OriginatorIdentifierOrKey GetInstance(
object o)
{
if (o == null || o is OriginatorIdentifierOrKey)
{
return (OriginatorIdentifierOrKey)o;
}
if (o is Asn1Object)
{
return new OriginatorIdentifierOrKey((Asn1Object)o);
}
throw new ArgumentException("Invalid OriginatorIdentifierOrKey: " + o.GetType().Name);
}
public Asn1Encodable ID
{
get { return id; }
}
public OriginatorPublicKey OriginatorKey
{
get
{
if (id is Asn1TaggedObject && ((Asn1TaggedObject)id).TagNo == 1)
{
return OriginatorPublicKey.GetInstance((Asn1TaggedObject)id, false);
}
return null;
}
}
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* OriginatorIdentifierOrKey ::= CHOICE {
* issuerAndSerialNumber IssuerAndSerialNumber,
* subjectKeyIdentifier [0] SubjectKeyIdentifier,
* originatorKey [1] OriginatorPublicKey
* }
*
* SubjectKeyIdentifier ::= OCTET STRING
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
return id.ToAsn1Object();
}
}
}

View File

@@ -0,0 +1,125 @@
using System;
using Org.BouncyCastle.Asn1;
namespace Org.BouncyCastle.Asn1.Cms
{
public class OriginatorInfo
: Asn1Encodable
{
private Asn1Set certs;
private Asn1Set crls;
public OriginatorInfo(
Asn1Set certs,
Asn1Set crls)
{
this.certs = certs;
this.crls = crls;
}
public OriginatorInfo(
Asn1Sequence seq)
{
switch (seq.Count)
{
case 0: // empty
break;
case 1:
Asn1TaggedObject o = (Asn1TaggedObject) seq[0];
switch (o.TagNo)
{
case 0 :
certs = Asn1Set.GetInstance(o, false);
break;
case 1 :
crls = Asn1Set.GetInstance(o, false);
break;
default:
throw new ArgumentException("Bad tag in OriginatorInfo: " + o.TagNo);
}
break;
case 2:
certs = Asn1Set.GetInstance((Asn1TaggedObject) seq[0], false);
crls = Asn1Set.GetInstance((Asn1TaggedObject) seq[1], false);
break;
default:
throw new ArgumentException("OriginatorInfo too big");
}
}
/**
* return an OriginatorInfo object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the object held by the
* tagged object cannot be converted.
*/
public static OriginatorInfo GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
}
/**
* return an OriginatorInfo object from the given object.
*
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static OriginatorInfo GetInstance(
object obj)
{
if (obj == null || obj is OriginatorInfo)
{
return (OriginatorInfo)obj;
}
if (obj is Asn1Sequence)
{
return new OriginatorInfo((Asn1Sequence)obj);
}
throw new ArgumentException("Invalid OriginatorInfo: " + obj.GetType().Name);
}
public Asn1Set Certificates
{
get { return certs; }
}
public Asn1Set Crls
{
get { return crls; }
}
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* OriginatorInfo ::= Sequence {
* certs [0] IMPLICIT CertificateSet OPTIONAL,
* crls [1] IMPLICIT CertificateRevocationLists OPTIONAL
* }
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
Asn1EncodableVector v = new Asn1EncodableVector();
if (certs != null)
{
v.Add(new DerTaggedObject(false, 0, certs));
}
if (crls != null)
{
v.Add(new DerTaggedObject(false, 1, crls));
}
return new DerSequence(v);
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Asn1.Cms
{
public class OriginatorPublicKey
: Asn1Encodable
{
private AlgorithmIdentifier algorithm;
private DerBitString publicKey;
public OriginatorPublicKey(
AlgorithmIdentifier algorithm,
byte[] publicKey)
{
this.algorithm = algorithm;
this.publicKey = new DerBitString(publicKey);
}
public OriginatorPublicKey(
Asn1Sequence seq)
{
algorithm = AlgorithmIdentifier.GetInstance(seq[0]);
publicKey = (DerBitString) seq[1];
}
/**
* return an OriginatorPublicKey object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicitly true if the object is meant to be explicitly
* tagged false otherwise.
* @exception ArgumentException if the object held by the
* tagged object cannot be converted.
*/
public static OriginatorPublicKey GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
}
/**
* return an OriginatorPublicKey object from the given object.
*
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static OriginatorPublicKey GetInstance(
object obj)
{
if (obj == null || obj is OriginatorPublicKey)
{
return (OriginatorPublicKey)obj;
}
if (obj is Asn1Sequence)
{
return new OriginatorPublicKey((Asn1Sequence) obj);
}
throw new ArgumentException("Invalid OriginatorPublicKey: " + obj.GetType().Name);
}
public AlgorithmIdentifier Algorithm
{
get { return algorithm; }
}
public DerBitString PublicKey
{
get { return publicKey; }
}
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* OriginatorPublicKey ::= Sequence {
* algorithm AlgorithmIdentifier,
* publicKey BIT STRING
* }
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
return new DerSequence(algorithm, publicKey);
}
}
}

View File

@@ -0,0 +1,74 @@
using System;
using Org.BouncyCastle.Asn1;
namespace Org.BouncyCastle.Asn1.Cms
{
public class OtherKeyAttribute
: Asn1Encodable
{
private DerObjectIdentifier keyAttrId;
private Asn1Encodable keyAttr;
/**
* return an OtherKeyAttribute object from the given object.
*
* @param o the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
public static OtherKeyAttribute GetInstance(
object obj)
{
if (obj == null || obj is OtherKeyAttribute)
{
return (OtherKeyAttribute) obj;
}
if (obj is Asn1Sequence)
{
return new OtherKeyAttribute((Asn1Sequence) obj);
}
throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
}
public OtherKeyAttribute(
Asn1Sequence seq)
{
keyAttrId = (DerObjectIdentifier) seq[0];
keyAttr = seq[1];
}
public OtherKeyAttribute(
DerObjectIdentifier keyAttrId,
Asn1Encodable keyAttr)
{
this.keyAttrId = keyAttrId;
this.keyAttr = keyAttr;
}
public DerObjectIdentifier KeyAttrId
{
get { return keyAttrId; }
}
public Asn1Encodable KeyAttr
{
get { return keyAttr; }
}
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* OtherKeyAttribute ::= Sequence {
* keyAttrId OBJECT IDENTIFIER,
* keyAttr ANY DEFINED BY keyAttrId OPTIONAL
* }
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
return new DerSequence(keyAttrId, keyAttr);
}
}
}

Some files were not shown because too many files have changed in this diff Show More