diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj
index 40f468144..c13fd13aa 100644
--- a/crypto/BouncyCastle.Android.csproj
+++ b/crypto/BouncyCastle.Android.csproj
@@ -76,8 +76,12 @@
<Compile Include="src\asn1\Asn1RelativeOid.cs" />
<Compile Include="src\asn1\Asn1Sequence.cs" />
<Compile Include="src\asn1\Asn1Set.cs" />
+ <Compile Include="src\asn1\Asn1Tag.cs" />
<Compile Include="src\asn1\Asn1TaggedObject.cs" />
<Compile Include="src\asn1\Asn1Tags.cs" />
+ <Compile Include="src\asn1\Asn1Type.cs" />
+ <Compile Include="src\asn1\Asn1UniversalType.cs" />
+ <Compile Include="src\asn1\Asn1UniversalTypes.cs" />
<Compile Include="src\asn1\Asn1Utilities.cs" />
<Compile Include="src\asn1\BERBitString.cs" />
<Compile Include="src\asn1\BERGenerator.cs" />
diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj
index 387e634ca..9745dca60 100644
--- a/crypto/BouncyCastle.csproj
+++ b/crypto/BouncyCastle.csproj
@@ -70,8 +70,12 @@
<Compile Include="src\asn1\Asn1RelativeOid.cs" />
<Compile Include="src\asn1\Asn1Sequence.cs" />
<Compile Include="src\asn1\Asn1Set.cs" />
+ <Compile Include="src\asn1\Asn1Tag.cs" />
<Compile Include="src\asn1\Asn1TaggedObject.cs" />
<Compile Include="src\asn1\Asn1Tags.cs" />
+ <Compile Include="src\asn1\Asn1Type.cs" />
+ <Compile Include="src\asn1\Asn1UniversalType.cs" />
+ <Compile Include="src\asn1\Asn1UniversalTypes.cs" />
<Compile Include="src\asn1\Asn1Utilities.cs" />
<Compile Include="src\asn1\BERBitString.cs" />
<Compile Include="src\asn1\BERGenerator.cs" />
diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj
index 8c964d6e6..f718b9238 100644
--- a/crypto/BouncyCastle.iOS.csproj
+++ b/crypto/BouncyCastle.iOS.csproj
@@ -71,8 +71,12 @@
<Compile Include="src\asn1\Asn1RelativeOid.cs" />
<Compile Include="src\asn1\Asn1Sequence.cs" />
<Compile Include="src\asn1\Asn1Set.cs" />
+ <Compile Include="src\asn1\Asn1Tag.cs" />
<Compile Include="src\asn1\Asn1TaggedObject.cs" />
<Compile Include="src\asn1\Asn1Tags.cs" />
+ <Compile Include="src\asn1\Asn1Type.cs" />
+ <Compile Include="src\asn1\Asn1UniversalType.cs" />
+ <Compile Include="src\asn1\Asn1UniversalTypes.cs" />
<Compile Include="src\asn1\Asn1Utilities.cs" />
<Compile Include="src\asn1\BERBitString.cs" />
<Compile Include="src\asn1\BERGenerator.cs" />
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index 55686e355..69a44f9dc 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -244,11 +244,31 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\asn1\ASN1Tag.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\asn1\ASN1Tags.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
+ RelPath = "src\asn1\Asn1Type.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\asn1\Asn1UniversalType.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\asn1\Asn1UniversalTypes.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\asn1\Asn1Utilities.cs"
SubType = "Code"
BuildAction = "Compile"
diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index 3f7a65cc9..d03c7a6b5 100644
--- a/crypto/src/asn1/Asn1InputStream.cs
+++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -401,11 +401,12 @@ namespace Org.BouncyCastle.Asn1
switch (tagNo)
{
case Asn1Tags.BmpString:
- return new DerBmpString(GetBmpCharBuffer(defIn));
+ return DerBmpString.CreatePrimitive(GetBmpCharBuffer(defIn));
case Asn1Tags.Boolean:
- return DerBoolean.FromOctetString(GetBuffer(defIn, tmpBuffers));
+ return DerBoolean.CreatePrimitive(GetBuffer(defIn, tmpBuffers));
case Asn1Tags.Enumerated:
- return DerEnumerated.FromOctetString(GetBuffer(defIn, tmpBuffers));
+ // TODO Ideally only clone if we used a buffer
+ return DerEnumerated.CreatePrimitive(GetBuffer(defIn, tmpBuffers), true);
case Asn1Tags.ObjectIdentifier:
// TODO Ideally only clone if we used a buffer
return DerObjectIdentifier.CreatePrimitive(GetBuffer(defIn, tmpBuffers), true);
@@ -418,44 +419,39 @@ namespace Org.BouncyCastle.Asn1
case Asn1Tags.BitString:
return DerBitString.CreatePrimitive(bytes);
case Asn1Tags.GeneralizedTime:
- return new DerGeneralizedTime(bytes);
+ return DerGeneralizedTime.CreatePrimitive(bytes);
case Asn1Tags.GeneralString:
- return new DerGeneralString(bytes);
+ return DerGeneralString.CreatePrimitive(bytes);
case Asn1Tags.GraphicString:
return DerGraphicString.CreatePrimitive(bytes);
case Asn1Tags.IA5String:
- return new DerIA5String(bytes);
+ return DerIA5String.CreatePrimitive(bytes);
case Asn1Tags.Integer:
- return new DerInteger(bytes, false);
+ return DerInteger.CreatePrimitive(bytes);
case Asn1Tags.Null:
- {
- if (0 != bytes.Length)
- throw new InvalidOperationException("malformed NULL encoding encountered");
-
- return DerNull.Instance;
- }
+ return Asn1Null.CreatePrimitive(bytes);
case Asn1Tags.NumericString:
- return new DerNumericString(bytes);
+ return DerNumericString.CreatePrimitive(bytes);
case Asn1Tags.ObjectDescriptor:
return Asn1ObjectDescriptor.CreatePrimitive(bytes);
case Asn1Tags.OctetString:
- return new DerOctetString(bytes);
+ return Asn1OctetString.CreatePrimitive(bytes);
case Asn1Tags.PrintableString:
- return new DerPrintableString(bytes);
+ return DerPrintableString.CreatePrimitive(bytes);
case Asn1Tags.RelativeOid:
return Asn1RelativeOid.CreatePrimitive(bytes, false);
case Asn1Tags.T61String:
- return new DerT61String(bytes);
+ return DerT61String.CreatePrimitive(bytes);
case Asn1Tags.UniversalString:
- return new DerUniversalString(bytes);
+ return DerUniversalString.CreatePrimitive(bytes);
case Asn1Tags.UtcTime:
- return new DerUtcTime(bytes);
+ return DerUtcTime.CreatePrimitive(bytes);
case Asn1Tags.Utf8String:
- return new DerUtf8String(bytes);
+ return DerUtf8String.CreatePrimitive(bytes);
case Asn1Tags.VideotexString:
- return new DerVideotexString(bytes);
+ return DerVideotexString.CreatePrimitive(bytes);
case Asn1Tags.VisibleString:
- return new DerVisibleString(bytes);
+ return DerVisibleString.CreatePrimitive(bytes);
default:
throw new IOException("unknown tag " + tagNo + " encountered");
}
diff --git a/crypto/src/asn1/Asn1Null.cs b/crypto/src/asn1/Asn1Null.cs
index d54019f67..9ea9b4375 100644
--- a/crypto/src/asn1/Asn1Null.cs
+++ b/crypto/src/asn1/Asn1Null.cs
@@ -1,3 +1,8 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
namespace Org.BouncyCastle.Asn1
{
/**
@@ -6,13 +11,65 @@ namespace Org.BouncyCastle.Asn1
public abstract class Asn1Null
: Asn1Object
{
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(Asn1Null), Asn1Tags.Null) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
+
+ public static Asn1Null GetInstance(object obj)
+ {
+ if (obj == null || obj is Asn1Null)
+ {
+ return (Asn1Null)obj;
+ }
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is Asn1Null)
+ return (Asn1Null)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (Asn1Null)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct NULL from byte[]: " + e.Message);
+ }
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
+ }
+
+ public static Asn1Null GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+ {
+ return (Asn1Null)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
+ }
+
internal Asn1Null()
{
}
- public override string ToString()
- {
- return "NULL";
- }
+ public override string ToString()
+ {
+ return "NULL";
+ }
+
+ internal static Asn1Null CreatePrimitive(byte[] contents)
+ {
+ if (0 != contents.Length)
+ throw new InvalidOperationException("malformed NULL encoding encountered");
+
+ return DerNull.Instance;
+ }
}
}
diff --git a/crypto/src/asn1/Asn1ObjectDescriptor.cs b/crypto/src/asn1/Asn1ObjectDescriptor.cs
index 289a0e16f..9c99f441e 100644
--- a/crypto/src/asn1/Asn1ObjectDescriptor.cs
+++ b/crypto/src/asn1/Asn1ObjectDescriptor.cs
@@ -8,6 +8,25 @@ namespace Org.BouncyCastle.Asn1
public sealed class Asn1ObjectDescriptor
: Asn1Object
{
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(Asn1ObjectDescriptor), Asn1Tags.ObjectDescriptor) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return new Asn1ObjectDescriptor(
+ (DerGraphicString)DerGraphicString.Meta.Instance.FromImplicitPrimitive(octetString));
+ }
+
+ internal override Asn1Object FromImplicitConstructed(Asn1Sequence sequence)
+ {
+ return new Asn1ObjectDescriptor(
+ (DerGraphicString)DerGraphicString.Meta.Instance.FromImplicitConstructed(sequence));
+ }
+ }
+
/**
* Return an ObjectDescriptor from the passed in object.
*
@@ -31,7 +50,7 @@ namespace Org.BouncyCastle.Asn1
{
try
{
- return GetInstance(FromByteArray((byte[])obj));
+ return (Asn1ObjectDescriptor)Meta.Instance.FromByteArray((byte[])obj);
}
catch (IOException e)
{
@@ -46,21 +65,13 @@ namespace Org.BouncyCastle.Asn1
* Return an ObjectDescriptor from a tagged object.
*
* @param taggedObject the tagged object holding the object we want.
- * @param explicit true if the object is meant to be explicitly tagged,
- * false otherwise.
+ * @param declaredExplicit true if the object is meant to be explicitly tagged, false otherwise.
* @exception IllegalArgumentException if the tagged object cannot be converted.
* @return an ASN1ObjectDescriptor instance, or null.
*/
- public static Asn1ObjectDescriptor GetInstance(Asn1TaggedObject taggedObject, bool isExplicit)
+ public static Asn1ObjectDescriptor GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object baseObject = taggedObject.GetObject();
-
- if (isExplicit || baseObject is Asn1ObjectDescriptor)
- {
- return GetInstance(baseObject);
- }
-
- return new Asn1ObjectDescriptor(new DerGraphicString(((Asn1OctetString)baseObject).GetOctets()));
+ return (Asn1ObjectDescriptor)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
private readonly DerGraphicString m_baseGraphicString;
diff --git a/crypto/src/asn1/Asn1OctetString.cs b/crypto/src/asn1/Asn1OctetString.cs
index 66d6fb8d1..d34686134 100644
--- a/crypto/src/asn1/Asn1OctetString.cs
+++ b/crypto/src/asn1/Asn1OctetString.cs
@@ -9,6 +9,23 @@ namespace Org.BouncyCastle.Asn1
public abstract class Asn1OctetString
: Asn1Object, Asn1OctetStringParser
{
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(Asn1OctetString), Asn1Tags.OctetString) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return octetString;
+ }
+
+ internal override Asn1Object FromImplicitConstructed(Asn1Sequence sequence)
+ {
+ return sequence.ToAsn1OctetString();
+ }
+ }
+
internal static readonly byte[] EmptyOctets = new byte[0];
/**
@@ -28,15 +45,13 @@ namespace Org.BouncyCastle.Asn1
{
Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
if (asn1Object is Asn1OctetString)
- {
return (Asn1OctetString)asn1Object;
- }
}
else if (obj is byte[])
{
try
{
- return GetInstance(FromByteArray((byte[])obj));
+ return (Asn1OctetString)Meta.Instance.FromByteArray((byte[])obj);
}
catch (IOException e)
{
@@ -48,46 +63,15 @@ namespace Org.BouncyCastle.Asn1
}
/**
- * return an Octet string from a tagged object.
+ * 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.
+ * @param taggedObject the tagged object holding the object we want.
+ * @param declaredExplicit 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 taggedObject, bool declaredExplicit)
{
- if (declaredExplicit)
- {
- if (!taggedObject.IsExplicit())
- throw new ArgumentException("object implicit - explicit expected.");
-
- return GetInstance(taggedObject.GetObject());
- }
-
- Asn1Object baseObject = taggedObject.GetObject();
-
- // If parsed as explicit though declared implicit, it should have been a set of one
- if (taggedObject.IsExplicit())
- {
- Asn1OctetString singleSegment = GetInstance(baseObject);
-
- if (taggedObject is BerTaggedObject)
- return new BerOctetString(new Asn1OctetString[]{ singleSegment });
-
- return singleSegment;
- }
-
- if (baseObject is Asn1OctetString)
- return (Asn1OctetString)baseObject;
-
- // Parser assumes implicit constructed encodings are sequences
- if (baseObject is Asn1Sequence)
- return ((Asn1Sequence)baseObject).ToAsn1OctetString();
-
- throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(taggedObject),
- "taggedObject");
+ return (Asn1OctetString)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
internal readonly byte[] contents;
@@ -138,5 +122,10 @@ namespace Org.BouncyCastle.Asn1
{
return "#" + Hex.ToHexString(contents);
}
- }
+
+ internal static Asn1OctetString CreatePrimitive(byte[] contents)
+ {
+ return new DerOctetString(contents);
+ }
+ }
}
diff --git a/crypto/src/asn1/Asn1RelativeOid.cs b/crypto/src/asn1/Asn1RelativeOid.cs
index a960b50bf..9c4f917f2 100644
--- a/crypto/src/asn1/Asn1RelativeOid.cs
+++ b/crypto/src/asn1/Asn1RelativeOid.cs
@@ -10,6 +10,18 @@ namespace Org.BouncyCastle.Asn1
public class Asn1RelativeOid
: Asn1Object
{
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(Asn1RelativeOid), Asn1Tags.RelativeOid) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets(), false);
+ }
+ }
+
public static Asn1RelativeOid FromContents(byte[] contents)
{
return CreatePrimitive(contents, true);
@@ -31,7 +43,7 @@ namespace Org.BouncyCastle.Asn1
{
try
{
- return GetInstance(FromByteArray((byte[])obj));
+ return (Asn1RelativeOid)FromByteArray((byte[])obj);
}
catch (IOException e)
{
@@ -44,14 +56,7 @@ namespace Org.BouncyCastle.Asn1
public static Asn1RelativeOid GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object baseObject = taggedObject.GetObject();
-
- if (declaredExplicit || baseObject is Asn1RelativeOid)
- {
- return GetInstance(baseObject);
- }
-
- return FromContents(Asn1OctetString.GetInstance(baseObject).GetOctets());
+ return (Asn1RelativeOid)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
private const long LongLimit = (Int64.MaxValue >> 7) - 0x7F;
diff --git a/crypto/src/asn1/Asn1Sequence.cs b/crypto/src/asn1/Asn1Sequence.cs
index cfe0d37aa..d7f84d3e4 100644
--- a/crypto/src/asn1/Asn1Sequence.cs
+++ b/crypto/src/asn1/Asn1Sequence.cs
@@ -10,6 +10,18 @@ namespace Org.BouncyCastle.Asn1
public abstract class Asn1Sequence
: Asn1Object, IEnumerable
{
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(Asn1Sequence), Asn1Tags.Sequence) {}
+
+ internal override Asn1Object FromImplicitConstructed(Asn1Sequence sequence)
+ {
+ return sequence;
+ }
+ }
+
/**
* return an Asn1Sequence from the given object.
*
@@ -33,7 +45,7 @@ namespace Org.BouncyCastle.Asn1
{
try
{
- return GetInstance(FromByteArray((byte[])obj));
+ return (Asn1Sequence)Meta.Instance.FromByteArray((byte[])obj);
}
catch (IOException e)
{
@@ -55,37 +67,12 @@ namespace Org.BouncyCastle.Asn1
* be using this method.
*
* @param taggedObject the tagged object.
- * @param declaredExplicit true if the object is meant to be explicitly tagged,
- * false otherwise.
- * @exception ArgumentException if the tagged object cannot
- * be converted.
+ * @param declaredExplicit 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 taggedObject, bool declaredExplicit)
{
- if (declaredExplicit)
- {
- if (!taggedObject.IsExplicit())
- throw new ArgumentException("object implicit - explicit expected.");
-
- return GetInstance(taggedObject.GetObject());
- }
-
- Asn1Object baseObject = taggedObject.GetObject();
-
- // If parsed as explicit though declared implicit, it should have been a sequence of one
- if (taggedObject.IsExplicit())
- {
- if (taggedObject is BerTaggedObject)
- return new BerSequence(baseObject);
-
- return new DLSequence(baseObject);
- }
-
- if (baseObject is Asn1Sequence)
- return (Asn1Sequence)baseObject;
-
- throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(taggedObject),
- "taggedObject");
+ return (Asn1Sequence)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
// NOTE: Only non-readonly to support LazyDLSequence
diff --git a/crypto/src/asn1/Asn1Set.cs b/crypto/src/asn1/Asn1Set.cs
index 42180fd71..f3b94121b 100644
--- a/crypto/src/asn1/Asn1Set.cs
+++ b/crypto/src/asn1/Asn1Set.cs
@@ -16,6 +16,18 @@ namespace Org.BouncyCastle.Asn1
public abstract class Asn1Set
: Asn1Object, IEnumerable
{
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(Asn1Set), Asn1Tags.Set) {}
+
+ internal override Asn1Object FromImplicitConstructed(Asn1Sequence sequence)
+ {
+ return sequence.ToAsn1Set();
+ }
+ }
+
/**
* return an ASN1Set from the given object.
*
@@ -39,7 +51,7 @@ namespace Org.BouncyCastle.Asn1
{
try
{
- return GetInstance(FromByteArray((byte[])obj));
+ return (Asn1Set)Meta.Instance.FromByteArray((byte[])obj);
}
catch (IOException e)
{
@@ -61,41 +73,12 @@ namespace Org.BouncyCastle.Asn1
* be using this method.
*
* @param taggedObject the tagged object.
- * @param declaredExplicit true if the object is meant to be explicitly tagged
- * false otherwise.
- * @exception ArgumentException if the tagged object cannot
- * be converted.
+ * @param declaredExplicit 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 taggedObject, bool declaredExplicit)
{
- if (declaredExplicit)
- {
- if (!taggedObject.IsExplicit())
- throw new ArgumentException("object implicit - explicit expected.");
-
- return GetInstance(taggedObject.GetObject());
- }
-
- Asn1Object baseObject = taggedObject.GetObject();
-
- // If parsed as explicit though declared implicit, it should have been a set of one
- if (taggedObject.IsExplicit())
- {
- if (taggedObject is BerTaggedObject)
- return new BerSet(baseObject);
-
- return new DLSet(baseObject);
- }
-
- if (baseObject is Asn1Set)
- return (Asn1Set)baseObject;
-
- // Parser assumes implicit constructed encodings are sequences
- if (baseObject is Asn1Sequence)
- return ((Asn1Sequence)baseObject).ToAsn1Set();
-
- throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(taggedObject),
- "taggedObject");
+ return (Asn1Set)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
// NOTE: Only non-readonly to support LazyDLSet
diff --git a/crypto/src/asn1/Asn1Tag.cs b/crypto/src/asn1/Asn1Tag.cs
new file mode 100644
index 000000000..b57174bdb
--- /dev/null
+++ b/crypto/src/asn1/Asn1Tag.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+ internal sealed class Asn1Tag
+ {
+ internal static Asn1Tag Create(int tagClass, int tagNo)
+ {
+ return new Asn1Tag(tagClass, tagNo);
+ }
+
+ private readonly int m_tagClass;
+ private readonly int m_tagNo;
+
+ private Asn1Tag(int tagClass, int tagNo)
+ {
+ m_tagClass = tagClass;
+ m_tagNo = tagNo;
+ }
+
+ internal int TagClass
+ {
+ get { return m_tagClass; }
+ }
+
+ internal int TagNo
+ {
+ get { return m_tagNo; }
+ }
+ }
+}
diff --git a/crypto/src/asn1/Asn1TaggedObject.cs b/crypto/src/asn1/Asn1TaggedObject.cs
index 7fafa4c52..66835ac14 100644
--- a/crypto/src/asn1/Asn1TaggedObject.cs
+++ b/crypto/src/asn1/Asn1TaggedObject.cs
@@ -238,19 +238,19 @@ namespace Org.BouncyCastle.Asn1
{
switch (explicitness)
{
- case DeclaredImplicit:
- {
- Asn1Object baseObject = obj.ToAsn1Object();
- if (baseObject is Asn1Sequence || baseObject is Asn1Set)
- return true;
-
- Asn1TaggedObject baseTagged = baseObject as Asn1TaggedObject;
- return null != baseTagged && baseTagged.IsConstructed();
- }
- case ParsedImplicit:
- return obj is Asn1Sequence;
- default:
+ case DeclaredImplicit:
+ {
+ Asn1Object baseObject = obj.ToAsn1Object();
+ if (baseObject is Asn1Sequence || baseObject is Asn1Set)
return true;
+
+ Asn1TaggedObject baseTagged = baseObject as Asn1TaggedObject;
+ return null != baseTagged && baseTagged.IsConstructed();
+ }
+ case ParsedImplicit:
+ return obj is Asn1Sequence;
+ default:
+ return true;
}
}
@@ -315,13 +315,7 @@ namespace Org.BouncyCastle.Asn1
case DeclaredImplicit:
{
Asn1TaggedObject declared = CheckedCast(obj.ToAsn1Object());
- if (!declared.HasTag(baseTagClass, baseTagNo))
- {
- string expected = Asn1Utilities.GetTagText(baseTagClass, baseTagNo);
- string found = Asn1Utilities.GetTagText(declared);
- throw new InvalidOperationException("Expected " + expected + " tag but found " + found);
- }
- return declared;
+ return Asn1Utilities.CheckTag(declared, baseTagClass, baseTagNo);
}
// Parsed; return a virtual tag (i.e. that couldn't have been present in the encoding)
@@ -330,6 +324,45 @@ namespace Org.BouncyCastle.Asn1
}
}
+ public Asn1Object GetBaseUniversal(bool declaredExplicit, int tagNo)
+ {
+ Asn1UniversalType universalType = Asn1UniversalTypes.Get(tagNo);
+ if (null == universalType)
+ throw new ArgumentException("unsupported UNIVERSAL tag number: " + tagNo, "tagNo");
+
+ return GetBaseUniversal(declaredExplicit, universalType);
+ }
+
+ internal Asn1Object GetBaseUniversal(bool declaredExplicit, Asn1UniversalType universalType)
+ {
+ if (declaredExplicit)
+ {
+ if (!IsExplicit())
+ throw new InvalidOperationException("object explicit - implicit expected.");
+
+ return universalType.CheckedCast(obj.ToAsn1Object());
+ }
+
+ if (DeclaredExplicit == explicitness)
+ throw new InvalidOperationException("object explicit - implicit expected.");
+
+ Asn1Object baseObject = obj.ToAsn1Object();
+ switch (explicitness)
+ {
+ case ParsedExplicit:
+ return universalType.FromImplicitConstructed(RebuildConstructed(baseObject));
+ case ParsedImplicit:
+ {
+ if (baseObject is Asn1Sequence)
+ return universalType.FromImplicitConstructed((Asn1Sequence)baseObject);
+
+ return universalType.FromImplicitPrimitive((DerOctetString)baseObject);
+ }
+ default:
+ return universalType.CheckedCast(baseObject);
+ }
+ }
+
/**
* 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
diff --git a/crypto/src/asn1/Asn1Type.cs b/crypto/src/asn1/Asn1Type.cs
new file mode 100644
index 000000000..f44b74e64
--- /dev/null
+++ b/crypto/src/asn1/Asn1Type.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+ internal abstract class Asn1Type
+ {
+ internal readonly Type m_platformType;
+
+ internal Asn1Type(Type platformType)
+ {
+ m_platformType = platformType;
+ }
+
+ internal Type PlatformType
+ {
+ get { return m_platformType; }
+ }
+
+ public sealed override bool Equals(object that)
+ {
+ return this == that;
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+}
diff --git a/crypto/src/asn1/Asn1UniversalType.cs b/crypto/src/asn1/Asn1UniversalType.cs
new file mode 100644
index 000000000..46cacb436
--- /dev/null
+++ b/crypto/src/asn1/Asn1UniversalType.cs
@@ -0,0 +1,56 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ internal abstract class Asn1UniversalType
+ : Asn1Type
+ {
+ internal readonly Asn1Tag m_tag;
+
+ internal Asn1UniversalType(Type platformType, int tagNo)
+ : base(platformType)
+ {
+ m_tag = Asn1Tag.Create(Asn1Tags.Universal, tagNo);
+ }
+
+ internal Asn1Object CheckedCast(Asn1Object asn1Object)
+ {
+ if (PlatformType.IsInstanceOfType(asn1Object))
+ return asn1Object;
+
+ throw new InvalidOperationException("unexpected object: " + Platform.GetTypeName(asn1Object));
+ }
+
+ internal virtual Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ throw new InvalidOperationException("unexpected implicit primitive encoding");
+ }
+
+ internal virtual Asn1Object FromImplicitConstructed(Asn1Sequence sequence)
+ {
+ throw new InvalidOperationException("unexpected implicit constructed encoding");
+ }
+
+ /// <exception cref="IOException"/>
+ internal Asn1Object FromByteArray(byte[] bytes)
+ {
+ return CheckedCast(Asn1Object.FromByteArray(bytes));
+ }
+
+ internal Asn1Object GetContextInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+ {
+ if (Asn1Tags.ContextSpecific != taggedObject.TagClass)
+ throw new InvalidOperationException("this method only valid for CONTEXT_SPECIFIC tags");
+
+ return CheckedCast(taggedObject.GetBaseUniversal(declaredExplicit, this));
+ }
+
+ internal Asn1Tag Tag
+ {
+ get { return m_tag; }
+ }
+ }
+}
diff --git a/crypto/src/asn1/Asn1UniversalTypes.cs b/crypto/src/asn1/Asn1UniversalTypes.cs
new file mode 100644
index 000000000..214918bcd
--- /dev/null
+++ b/crypto/src/asn1/Asn1UniversalTypes.cs
@@ -0,0 +1,74 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+ internal sealed class Asn1UniversalTypes
+ {
+ private Asn1UniversalTypes()
+ {
+ }
+
+ internal static Asn1UniversalType Get(int tagNo)
+ {
+ switch (tagNo)
+ {
+ case Asn1Tags.Boolean:
+ return DerBoolean.Meta.Instance;
+ case Asn1Tags.Integer:
+ return DerInteger.Meta.Instance;
+ case Asn1Tags.BitString:
+ return DerBitString.Meta.Instance;
+ case Asn1Tags.OctetString:
+ return Asn1OctetString.Meta.Instance;
+ case Asn1Tags.Null:
+ return Asn1Null.Meta.Instance;
+ case Asn1Tags.ObjectIdentifier:
+ return DerObjectIdentifier.Meta.Instance;
+ case Asn1Tags.ObjectDescriptor: // [UNIVERSAL 7] IMPLICIT GraphicString
+ return Asn1ObjectDescriptor.Meta.Instance;
+ case Asn1Tags.External:
+ return DerExternal.Meta.Instance;
+ case Asn1Tags.Enumerated:
+ return DerEnumerated.Meta.Instance;
+ case Asn1Tags.Utf8String: // [UNIVERSAL 12] IMPLICIT OCTET STRING (encode as if)
+ return DerUtf8String.Meta.Instance;
+ case Asn1Tags.RelativeOid:
+ return Asn1RelativeOid.Meta.Instance;
+ case Asn1Tags.Sequence:
+ return Asn1Sequence.Meta.Instance;
+ case Asn1Tags.Set:
+ return Asn1Set.Meta.Instance;
+ case Asn1Tags.NumericString: // [UNIVERSAL 18] IMPLICIT OCTET STRING (encode as if)
+ return DerNumericString.Meta.Instance;
+ case Asn1Tags.PrintableString: // [UNIVERSAL 19] IMPLICIT OCTET STRING (encode as if)
+ return DerPrintableString.Meta.Instance;
+ case Asn1Tags.T61String: // [UNIVERSAL 20] IMPLICIT OCTET STRING (encode as if)
+ return DerT61String.Meta.Instance;
+ case Asn1Tags.VideotexString: // [UNIVERSAL 21] IMPLICIT OCTET STRING (encode as if)
+ return DerVideotexString.Meta.Instance;
+ case Asn1Tags.IA5String: // [UNIVERSAL 22] IMPLICIT OCTET STRING (encode as if)
+ return DerIA5String.Meta.Instance;
+ case Asn1Tags.UtcTime: // [UNIVERSAL 23] IMPLICIT VisibleString (restricted values)
+ return DerUtcTime.Meta.Instance;
+ case Asn1Tags.GeneralizedTime: // [UNIVERSAL 24] IMPLICIT VisibleString (restricted values)
+ return DerGeneralizedTime.Meta.Instance;
+ case Asn1Tags.GraphicString: // [UNIVERSAL 25] IMPLICIT OCTET STRING (encode as if)
+ return DerGraphicString.Meta.Instance;
+ case Asn1Tags.VisibleString: // [UNIVERSAL 26] IMPLICIT OCTET STRING (encode as if)
+ return DerVisibleString.Meta.Instance;
+ case Asn1Tags.GeneralString: // [UNIVERSAL 27] IMPLICIT OCTET STRING (encode as if)
+ return DerGeneralString.Meta.Instance;
+ case Asn1Tags.UniversalString: // [UNIVERSAL 28] IMPLICIT OCTET STRING (encode as if)
+ return DerUniversalString.Meta.Instance;
+ case Asn1Tags.BmpString: // [UNIVERSAL 30] IMPLICIT OCTET STRING (encode as if)
+ return DerBmpString.Meta.Instance;
+
+ case Asn1Tags.Real:
+ case Asn1Tags.EmbeddedPdv:
+ case Asn1Tags.UnrestrictedString:
+ default:
+ return null;
+ }
+ }
+ }
+}
diff --git a/crypto/src/asn1/Asn1Utilities.cs b/crypto/src/asn1/Asn1Utilities.cs
index fe6db2df7..7b014ef00 100644
--- a/crypto/src/asn1/Asn1Utilities.cs
+++ b/crypto/src/asn1/Asn1Utilities.cs
@@ -4,6 +4,23 @@ namespace Org.BouncyCastle.Asn1
{
public abstract class Asn1Utilities
{
+ internal static Asn1TaggedObject CheckTag(Asn1TaggedObject taggedObject, int tagClass, int tagNo)
+ {
+ if (!taggedObject.HasTag(tagClass, tagNo))
+ {
+ string expected = GetTagText(tagClass, tagNo);
+ string found = GetTagText(taggedObject);
+ throw new InvalidOperationException("Expected " + expected + " tag but found " + found);
+ }
+ return taggedObject;
+ }
+
+
+ internal static string GetTagText(Asn1Tag tag)
+ {
+ return GetTagText(tag.TagClass, tag.TagNo);
+ }
+
public static string GetTagText(Asn1TaggedObject taggedObject)
{
return GetTagText(taggedObject.TagClass, taggedObject.TagNo);
@@ -24,20 +41,14 @@ namespace Org.BouncyCastle.Asn1
}
}
+
/*
* Wrappers for Asn1TaggedObject.GetExplicitBaseObject
*/
public static Asn1Encodable GetExplicitBaseObject(Asn1TaggedObject taggedObject, int tagClass, int tagNo)
{
- if (!taggedObject.HasTag(tagClass, tagNo))
- {
- string expected = GetTagText(tagClass, tagNo);
- string found = GetTagText(taggedObject);
- throw new InvalidOperationException("Expected " + expected + " tag but found " + found);
- }
-
- return taggedObject.GetExplicitBaseObject();
+ return CheckTag(taggedObject, tagClass, tagNo).GetExplicitBaseObject();
}
public static Asn1Encodable GetExplicitContextBaseObject(Asn1TaggedObject taggedObject, int tagNo)
@@ -65,14 +76,7 @@ namespace Org.BouncyCastle.Asn1
public static Asn1TaggedObject GetExplicitBaseTagged(Asn1TaggedObject taggedObject, int tagClass, int tagNo)
{
- if (!taggedObject.HasTag(tagClass, tagNo))
- {
- string expected = GetTagText(tagClass, tagNo);
- string found = GetTagText(taggedObject);
- throw new InvalidOperationException("Expected " + expected + " tag but found " + found);
- }
-
- return taggedObject.GetExplicitBaseTagged();
+ return CheckTag(taggedObject, tagClass, tagNo).GetExplicitBaseTagged();
}
public static Asn1TaggedObject GetExplicitContextBaseTagged(Asn1TaggedObject taggedObject, int tagNo)
@@ -92,5 +96,73 @@ namespace Org.BouncyCastle.Asn1
{
return TryGetExplicitBaseTagged(taggedObject, Asn1Tags.ContextSpecific, tagNo);
}
+
+
+ /*
+ * Wrappers for Asn1TaggedObject.GetImplicitBaseTagged
+ */
+
+ public static Asn1TaggedObject GetImplicitBaseTagged(Asn1TaggedObject taggedObject, int tagClass, int tagNo,
+ int baseTagClass, int baseTagNo)
+ {
+ return CheckTag(taggedObject, tagClass, tagNo).GetImplicitBaseTagged(baseTagClass, baseTagNo);
+ }
+
+ public static Asn1TaggedObject GetImplicitContextBaseTagged(Asn1TaggedObject taggedObject, int tagNo,
+ int baseTagClass, int baseTagNo)
+ {
+ return GetImplicitBaseTagged(taggedObject, Asn1Tags.ContextSpecific, tagNo, baseTagClass, baseTagNo);
+ }
+
+ public static Asn1TaggedObject TryGetImplicitBaseTagged(Asn1TaggedObject taggedObject, int tagClass, int tagNo,
+ int baseTagClass, int baseTagNo)
+ {
+ if (!taggedObject.HasTag(tagClass, tagNo))
+ {
+ return null;
+ }
+
+ return taggedObject.GetImplicitBaseTagged(baseTagClass, baseTagNo);
+ }
+
+ public static Asn1TaggedObject TryGetImplicitContextBaseTagged(Asn1TaggedObject taggedObject, int tagNo,
+ int baseTagClass, int baseTagNo)
+ {
+ return TryGetImplicitBaseTagged(taggedObject, Asn1Tags.ContextSpecific, tagNo, baseTagClass, baseTagNo);
+ }
+
+
+ /*
+ * Wrappers for Asn1TaggedObject.GetBaseUniversal
+ */
+
+ public static Asn1Object GetBaseUniversal(Asn1TaggedObject taggedObject, int tagClass, int tagNo,
+ bool declaredExplicit, int baseTagNo)
+ {
+ return CheckTag(taggedObject, tagClass, tagNo).GetBaseUniversal(declaredExplicit, baseTagNo);
+ }
+
+ public static Asn1Object GetContextBaseUniversal(Asn1TaggedObject taggedObject, int tagNo,
+ bool declaredExplicit, int baseTagNo)
+ {
+ return GetBaseUniversal(taggedObject, Asn1Tags.ContextSpecific, tagNo, declaredExplicit, baseTagNo);
+ }
+
+ public static Asn1Object TryGetBaseUniversal(Asn1TaggedObject taggedObject, int tagClass, int tagNo,
+ bool declaredExplicit, int baseTagNo)
+ {
+ if (!taggedObject.HasTag(tagClass, tagNo))
+ {
+ return null;
+ }
+
+ return taggedObject.GetBaseUniversal(declaredExplicit, baseTagNo);
+ }
+
+ public static Asn1Object TryGetContextBaseUniversal(Asn1TaggedObject taggedObject, int tagNo,
+ bool declaredExplicit, int baseTagNo)
+ {
+ return TryGetBaseUniversal(taggedObject, Asn1Tags.ContextSpecific, tagNo, declaredExplicit, baseTagNo);
+ }
}
}
diff --git a/crypto/src/asn1/DERExternal.cs b/crypto/src/asn1/DERExternal.cs
index 67dad0534..28d5cc46a 100644
--- a/crypto/src/asn1/DERExternal.cs
+++ b/crypto/src/asn1/DERExternal.cs
@@ -11,6 +11,18 @@ namespace Org.BouncyCastle.Asn1
public class DerExternal
: Asn1Object
{
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerExternal), Asn1Tags.External) {}
+
+ internal override Asn1Object FromImplicitConstructed(Asn1Sequence sequence)
+ {
+ return sequence.ToAsn1External();
+ }
+ }
+
public static DerExternal GetInstance(object obj)
{
if (obj == null || obj is DerExternal)
@@ -27,7 +39,7 @@ namespace Org.BouncyCastle.Asn1
{
try
{
- return GetInstance(FromByteArray((byte[])obj));
+ return (DerExternal)Meta.Instance.FromByteArray((byte[])obj);
}
catch (IOException e)
{
@@ -38,16 +50,9 @@ namespace Org.BouncyCastle.Asn1
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj");
}
- public static DerExternal GetInstance(Asn1TaggedObject taggedObject, bool isExplicit)
+ public static DerExternal GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object baseObject = taggedObject.GetObject();
-
- if (isExplicit || baseObject is DerExternal)
- {
- return GetInstance(baseObject);
- }
-
- return Asn1Sequence.GetInstance(baseObject).ToAsn1External();
+ return (DerExternal)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
private readonly DerObjectIdentifier directReference;
diff --git a/crypto/src/asn1/DerApplicationSpecific.cs b/crypto/src/asn1/DerApplicationSpecific.cs
index 13b725325..15a4cdcc2 100644
--- a/crypto/src/asn1/DerApplicationSpecific.cs
+++ b/crypto/src/asn1/DerApplicationSpecific.cs
@@ -94,6 +94,7 @@ namespace Org.BouncyCastle.Asn1
get { return m_taggedObject.TagNo; }
}
+ [Obsolete("Will be removed")]
public byte[] GetContents()
{
return m_taggedObject.GetContents();
@@ -112,21 +113,7 @@ namespace Org.BouncyCastle.Asn1
public Asn1Object GetObject(int tagNo)
{
- // TODO[asn1] Implement Asn1TaggedObject.GetBaseUniversal
- //return taggedObject.GetBaseUniversal(false, tagNo);
-
- if (tagNo >= 0x1F)
- throw new IOException("unsupported tag number");
-
- byte[] orig = this.GetEncoded();
- byte[] tmp = ReplaceTagNumber(tagNo, orig);
-
- if ((orig[0] & Asn1Tags.Constructed) != 0)
- {
- tmp[0] |= Asn1Tags.Constructed;
- }
-
- return FromByteArray(tmp);
+ return m_taggedObject.GetBaseUniversal(false, tagNo);
}
public bool HasApplicationTag(int tagNo)
@@ -186,34 +173,6 @@ namespace Org.BouncyCastle.Asn1
return m_taggedObject.GetEncodingImplicit(encoding, tagClass, tagNo);
}
- private byte[] ReplaceTagNumber(int newTag, byte[] input)
- {
- int tagNo = input[0] & 0x1f;
- int index = 1;
-
- // with tagged object tag number is bottom 5 bits, or stored at the start of the content
- if (tagNo == 0x1f)
- {
- int b = input[index++];
-
- // 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 & 0x80) != 0)
- {
- b = input[index++];
- }
- }
-
- int remaining = input.Length - index;
- byte[] tmp = new byte[1 + remaining];
- tmp[0] = (byte)newTag;
- Array.Copy(input, index, tmp, 1, remaining);
- return tmp;
- }
-
private static int CheckTagClass(int tagClass)
{
if (Asn1Tags.Application != tagClass)
diff --git a/crypto/src/asn1/DerBMPString.cs b/crypto/src/asn1/DerBMPString.cs
index 4e35dfff8..a289eed1b 100644
--- a/crypto/src/asn1/DerBMPString.cs
+++ b/crypto/src/asn1/DerBMPString.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using Org.BouncyCastle.Utilities;
@@ -10,7 +11,17 @@ namespace Org.BouncyCastle.Asn1
public class DerBmpString
: DerStringBase
{
- private readonly string str;
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerBmpString), Asn1Tags.BmpString) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
/**
* return a BMP string from the given object.
@@ -18,13 +29,29 @@ namespace Org.BouncyCastle.Asn1
* @param obj the object we want converted.
* @exception ArgumentException if the object cannot be converted.
*/
- public static DerBmpString GetInstance(
- object obj)
+ public static DerBmpString GetInstance(object obj)
{
if (obj == null || obj is DerBmpString)
{
return (DerBmpString)obj;
}
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerBmpString)
+ return (DerBmpString)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (DerBmpString)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct BMP string from byte[]: " + e.Message);
+ }
+ }
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
@@ -32,48 +59,35 @@ namespace Org.BouncyCastle.Asn1
/**
* 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.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit 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 isExplicit)
+ public static DerBmpString GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
-
- if (isExplicit || o is DerBmpString)
- {
- return GetInstance(o);
- }
-
- return new DerBmpString(Asn1OctetString.GetInstance(o).GetOctets());
+ return (DerBmpString)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
- /**
- * basic constructor - byte encoded string.
- */
- [Obsolete("Will become internal")]
- public DerBmpString(byte[] str)
+ private readonly string m_str;
+
+ internal DerBmpString(byte[] contents)
{
- if (str == null)
- throw new ArgumentNullException("str");
+ if (null == contents)
+ throw new ArgumentNullException("contents");
- int byteLen = str.Length;
+ int byteLen = contents.Length;
if (0 != (byteLen & 1))
- throw new ArgumentException("malformed BMPString encoding encountered", "str");
+ throw new ArgumentException("malformed BMPString encoding encountered", "contents");
int charLen = byteLen / 2;
char[] cs = new char[charLen];
for (int i = 0; i != charLen; i++)
{
- cs[i] = (char)((str[2 * i] << 8) | (str[2 * i + 1] & 0xff));
+ cs[i] = (char)((contents[2 * i] << 8) | (contents[2 * i + 1] & 0xff));
}
- this.str = new string(cs);
+ m_str = new string(cs);
}
internal DerBmpString(char[] str)
@@ -81,7 +95,7 @@ namespace Org.BouncyCastle.Asn1
if (str == null)
throw new ArgumentNullException("str");
- this.str = new string(str);
+ m_str = new string(str);
}
/**
@@ -92,23 +106,24 @@ namespace Org.BouncyCastle.Asn1
if (str == null)
throw new ArgumentNullException("str");
- this.str = str;
+ m_str = str;
}
public override string GetString()
{
- return str;
+ return m_str;
}
- protected override bool Asn1Equals(
- Asn1Object asn1Object)
+ protected override bool Asn1Equals(Asn1Object asn1Object)
{
- DerBmpString other = asn1Object as DerBmpString;
-
- if (other == null)
- return false;
+ DerBmpString that = asn1Object as DerBmpString;
+ return null != that
+ && this.m_str.Equals(that.m_str);
+ }
- return this.str.Equals(other.str);
+ protected override int Asn1GetHashCode()
+ {
+ return m_str.GetHashCode();
}
internal override IAsn1Encoding GetEncoding(int encoding)
@@ -123,7 +138,7 @@ namespace Org.BouncyCastle.Asn1
private byte[] GetContents()
{
- char[] c = str.ToCharArray();
+ char[] c = m_str.ToCharArray();
byte[] b = new byte[c.Length * 2];
for (int i = 0; i != c.Length; i++)
@@ -134,5 +149,16 @@ namespace Org.BouncyCastle.Asn1
return b;
}
+
+ internal static DerBmpString CreatePrimitive(byte[] contents)
+ {
+ return new DerBmpString(contents);
+ }
+
+ internal static DerBmpString CreatePrimitive(char[] str)
+ {
+ // TODO[asn1] Asn1InputStream has a validator/converter that should be unified in this class somehow
+ return new DerBmpString(str);
+ }
}
}
diff --git a/crypto/src/asn1/DerBitString.cs b/crypto/src/asn1/DerBitString.cs
index 375abb479..4596fbbc8 100644
--- a/crypto/src/asn1/DerBitString.cs
+++ b/crypto/src/asn1/DerBitString.cs
@@ -11,7 +11,24 @@ namespace Org.BouncyCastle.Asn1
public class DerBitString
: DerStringBase
{
- private static readonly char[] table
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerBitString), Asn1Tags.BitString) { }
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+
+ internal override Asn1Object FromImplicitConstructed(Asn1Sequence sequence)
+ {
+ return sequence.ToAsn1BitString();
+ }
+ }
+
+ private static readonly char[] table
= { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
/**
@@ -323,9 +340,7 @@ namespace Org.BouncyCastle.Asn1
byte finalOctet = contents[length - 1];
if (finalOctet != (byte)(finalOctet & (0xFF << padBits)))
- {
return new BerBitString(contents, false);
- }
}
return new DerBitString(contents, false);
diff --git a/crypto/src/asn1/DerBoolean.cs b/crypto/src/asn1/DerBoolean.cs
index 29e2d8bd9..ad578ae80 100644
--- a/crypto/src/asn1/DerBoolean.cs
+++ b/crypto/src/asn1/DerBoolean.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using Org.BouncyCastle.Utilities;
@@ -7,7 +8,17 @@ namespace Org.BouncyCastle.Asn1
public class DerBoolean
: Asn1Object
{
- private readonly byte value;
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerBoolean), Asn1Tags.Boolean) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
public static readonly DerBoolean False = new DerBoolean(false);
public static readonly DerBoolean True = new DerBoolean(true);
@@ -17,49 +28,57 @@ namespace Org.BouncyCastle.Asn1
*
* @exception ArgumentException if the object cannot be converted.
*/
- public static DerBoolean GetInstance(
- object obj)
+ public static DerBoolean GetInstance(object obj)
{
if (obj == null || obj is DerBoolean)
{
- return (DerBoolean) obj;
+ return (DerBoolean)obj;
+ }
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerBoolean)
+ return (DerBoolean)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (DerBoolean)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct boolean from byte[]: " + e.Message);
+ }
}
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
- /**
- * return a DerBoolean from the passed in bool.
- */
- public static DerBoolean GetInstance(
- bool value)
+ public static DerBoolean GetInstance(bool value)
{
return value ? True : False;
}
+ public static DerBoolean GetInstance(int value)
+ {
+ return value != 0 ? 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.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit 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 isExplicit)
+ public static DerBoolean GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
-
- if (isExplicit || o is DerBoolean)
- {
- return GetInstance(o);
- }
-
- return FromOctetString(((Asn1OctetString)o).GetOctets());
+ return (DerBoolean)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
+ private readonly byte value;
+
public DerBoolean(
byte[] val)
{
@@ -112,16 +131,14 @@ namespace Org.BouncyCastle.Asn1
return IsTrue ? "TRUE" : "FALSE";
}
- internal static DerBoolean FromOctetString(byte[] value)
+ internal static DerBoolean CreatePrimitive(byte[] contents)
{
- if (value.Length != 1)
- {
- throw new ArgumentException("BOOLEAN value should have 1 byte in it", "value");
- }
+ if (contents.Length != 1)
+ throw new ArgumentException("BOOLEAN value should have 1 byte in it", "contents");
- byte b = value[0];
+ byte b = contents[0];
- return b == 0 ? False : b == 0xFF ? True : new DerBoolean(value);
+ return b == 0 ? False : b == 0xFF ? True : new DerBoolean(contents);
}
private byte[] GetContents(int encoding)
diff --git a/crypto/src/asn1/DerEnumerated.cs b/crypto/src/asn1/DerEnumerated.cs
index 6fd2f9b62..920b3dc8e 100644
--- a/crypto/src/asn1/DerEnumerated.cs
+++ b/crypto/src/asn1/DerEnumerated.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Utilities;
@@ -8,21 +9,46 @@ namespace Org.BouncyCastle.Asn1
public class DerEnumerated
: Asn1Object
{
- private readonly byte[] bytes;
- private readonly int start;
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerEnumerated), Asn1Tags.Enumerated) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets(), false);
+ }
+ }
/**
* return an integer from the passed in object
*
* @exception ArgumentException if the object cannot be converted.
*/
- public static DerEnumerated GetInstance(
- object obj)
+ public static DerEnumerated GetInstance(object obj)
{
if (obj == null || obj is DerEnumerated)
{
return (DerEnumerated)obj;
}
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerEnumerated)
+ return (DerEnumerated)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (DerEnumerated)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct enumerated from byte[]: " + e.Message);
+ }
+ }
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
@@ -30,32 +56,24 @@ namespace Org.BouncyCastle.Asn1
/**
* 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.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit 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 isExplicit)
+ public static DerEnumerated GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
-
- if (isExplicit || o is DerEnumerated)
- {
- return GetInstance(o);
- }
-
- return FromOctetString(((Asn1OctetString)o).GetOctets());
+ return (DerEnumerated)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
+ private readonly byte[] contents;
+ private readonly int start;
+
public DerEnumerated(int val)
{
if (val < 0)
throw new ArgumentException("enumerated must be non-negative", "val");
- this.bytes = BigInteger.ValueOf(val).ToByteArray();
+ this.contents = BigInteger.ValueOf(val).ToByteArray();
this.start = 0;
}
@@ -64,7 +82,7 @@ namespace Org.BouncyCastle.Asn1
if (val < 0L)
throw new ArgumentException("enumerated must be non-negative", "val");
- this.bytes = BigInteger.ValueOf(val).ToByteArray();
+ this.contents = BigInteger.ValueOf(val).ToByteArray();
this.start = 0;
}
@@ -73,37 +91,42 @@ namespace Org.BouncyCastle.Asn1
if (val.SignValue < 0)
throw new ArgumentException("enumerated must be non-negative", "val");
- this.bytes = val.ToByteArray();
+ this.contents = val.ToByteArray();
this.start = 0;
}
- public DerEnumerated(byte[] bytes)
+ public DerEnumerated(byte[] contents)
+ : this(contents, true)
+ {
+ }
+
+ internal DerEnumerated(byte[] contents, bool clone)
{
- if (DerInteger.IsMalformed(bytes))
- throw new ArgumentException("malformed enumerated", "bytes");
- if (0 != (bytes[0] & 0x80))
- throw new ArgumentException("enumerated must be non-negative", "bytes");
+ if (DerInteger.IsMalformed(contents))
+ throw new ArgumentException("malformed enumerated", "contents");
+ if (0 != (contents[0] & 0x80))
+ throw new ArgumentException("enumerated must be non-negative", "contents");
- this.bytes = Arrays.Clone(bytes);
- this.start = DerInteger.SignBytesToSkip(bytes);
+ this.contents = clone ? Arrays.Clone(contents) : contents;
+ this.start = DerInteger.SignBytesToSkip(this.contents);
}
public BigInteger Value
{
- get { return new BigInteger(bytes); }
+ get { return new BigInteger(contents); }
}
public bool HasValue(int x)
{
- return (bytes.Length - start) <= 4
- && DerInteger.IntValue(bytes, start, DerInteger.SignExtSigned) == x;
+ return (contents.Length - start) <= 4
+ && DerInteger.IntValue(contents, start, DerInteger.SignExtSigned) == x;
}
public bool HasValue(BigInteger x)
{
return null != x
// Fast check to avoid allocation
- && DerInteger.IntValue(bytes, start, DerInteger.SignExtSigned) == x.IntValue
+ && DerInteger.IntValue(contents, start, DerInteger.SignExtSigned) == x.IntValue
&& Value.Equals(x);
}
@@ -111,22 +134,22 @@ namespace Org.BouncyCastle.Asn1
{
get
{
- int count = bytes.Length - start;
+ int count = contents.Length - start;
if (count > 4)
throw new ArithmeticException("ASN.1 Enumerated out of int range");
- return DerInteger.IntValue(bytes, start, DerInteger.SignExtSigned);
+ return DerInteger.IntValue(contents, start, DerInteger.SignExtSigned);
}
}
internal override IAsn1Encoding GetEncoding(int encoding)
{
- return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.Enumerated, bytes);
+ return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.Enumerated, contents);
}
internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
{
- return new PrimitiveEncoding(tagClass, tagNo, bytes);
+ return new PrimitiveEncoding(tagClass, tagNo, contents);
}
protected override bool Asn1Equals(Asn1Object asn1Object)
@@ -135,31 +158,31 @@ namespace Org.BouncyCastle.Asn1
if (other == null)
return false;
- return Arrays.AreEqual(this.bytes, other.bytes);
+ return Arrays.AreEqual(this.contents, other.contents);
}
protected override int Asn1GetHashCode()
{
- return Arrays.GetHashCode(bytes);
+ return Arrays.GetHashCode(contents);
}
private static readonly DerEnumerated[] cache = new DerEnumerated[12];
- internal static DerEnumerated FromOctetString(byte[] enc)
+ internal static DerEnumerated CreatePrimitive(byte[] contents, bool clone)
{
- if (enc.Length > 1)
- return new DerEnumerated(enc);
- if (enc.Length == 0)
- throw new ArgumentException("ENUMERATED has zero length", "enc");
+ if (contents.Length > 1)
+ return new DerEnumerated(contents, clone);
+ if (contents.Length == 0)
+ throw new ArgumentException("ENUMERATED has zero length", "contents");
- int value = enc[0];
+ int value = contents[0];
if (value >= cache.Length)
- return new DerEnumerated(enc);
+ return new DerEnumerated(contents, clone);
DerEnumerated possibleMatch = cache[value];
if (possibleMatch == null)
{
- cache[value] = possibleMatch = new DerEnumerated(enc);
+ cache[value] = possibleMatch = new DerEnumerated(contents, clone);
}
return possibleMatch;
}
diff --git a/crypto/src/asn1/DerGeneralString.cs b/crypto/src/asn1/DerGeneralString.cs
index f2a47c370..e6637732a 100644
--- a/crypto/src/asn1/DerGeneralString.cs
+++ b/crypto/src/asn1/DerGeneralString.cs
@@ -1,5 +1,5 @@
using System;
-using System.Text;
+using System.IO;
using Org.BouncyCastle.Utilities;
@@ -8,78 +8,108 @@ namespace Org.BouncyCastle.Asn1
public class DerGeneralString
: DerStringBase
{
- private readonly string str;
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerGeneralString), Asn1Tags.GeneralString) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
- public static DerGeneralString GetInstance(
- object obj)
+ public static DerGeneralString GetInstance(object obj)
{
if (obj == null || obj is DerGeneralString)
{
return (DerGeneralString) obj;
}
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerGeneralString)
+ return (DerGeneralString)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (DerGeneralString)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct general string from byte[]: " + e.Message);
+ }
+ }
- throw new ArgumentException("illegal object in GetInstance: "
- + Platform.GetTypeName(obj));
+ throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
- public static DerGeneralString GetInstance(
- Asn1TaggedObject obj,
- bool isExplicit)
+ public static DerGeneralString GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
+ return (DerGeneralString)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
+ }
- if (isExplicit || o is DerGeneralString)
- {
- return GetInstance(o);
- }
+ private readonly byte[] m_contents;
- return new DerGeneralString(((Asn1OctetString)o).GetOctets());
+ public DerGeneralString(string str)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+
+ m_contents = Strings.ToAsciiByteArray(str);
}
- public DerGeneralString(
- byte[] str)
- : this(Strings.FromAsciiByteArray(str))
+ public DerGeneralString(byte[] contents)
+ : this(contents, true)
{
}
- public DerGeneralString(
- string str)
+ internal DerGeneralString(byte[] contents, bool clone)
{
- if (str == null)
- throw new ArgumentNullException("str");
+ if (null == contents)
+ throw new ArgumentNullException("contents");
- this.str = str;
+ m_contents = clone ? Arrays.Clone(contents) : contents;
}
public override string GetString()
{
- return str;
+ return Strings.FromAsciiByteArray(m_contents);
}
public byte[] GetOctets()
{
- return Strings.ToAsciiByteArray(str);
+ return Arrays.Clone(m_contents);
}
internal override IAsn1Encoding GetEncoding(int encoding)
{
- return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.GeneralString, GetOctets());
+ return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.GeneralString, m_contents);
}
internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
{
- return new PrimitiveEncoding(tagClass, tagNo, GetOctets());
+ return new PrimitiveEncoding(tagClass, tagNo, m_contents);
}
- protected override bool Asn1Equals(
- Asn1Object asn1Object)
+ protected override bool Asn1Equals(Asn1Object asn1Object)
{
- DerGeneralString other = asn1Object as DerGeneralString;
+ DerGeneralString that = asn1Object as DerGeneralString;
+ return null != that
+ && Arrays.AreEqual(this.m_contents, that.m_contents);
+ }
- if (other == null)
- return false;
+ protected override int Asn1GetHashCode()
+ {
+ return Arrays.GetHashCode(m_contents);
+ }
- return this.str.Equals(other.str);
+ internal static DerGeneralString CreatePrimitive(byte[] contents)
+ {
+ return new DerGeneralString(contents, false);
}
}
}
diff --git a/crypto/src/asn1/DerGeneralizedTime.cs b/crypto/src/asn1/DerGeneralizedTime.cs
index 41c897751..ed2cb5e62 100644
--- a/crypto/src/asn1/DerGeneralizedTime.cs
+++ b/crypto/src/asn1/DerGeneralizedTime.cs
@@ -1,5 +1,6 @@
using System;
using System.Globalization;
+using System.IO;
using System.Text;
using Org.BouncyCastle.Utilities;
@@ -12,47 +13,64 @@ namespace Org.BouncyCastle.Asn1
public class DerGeneralizedTime
: Asn1Object
{
- private readonly string time;
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerGeneralizedTime), Asn1Tags.GeneralizedTime) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
/**
* return a generalized time from the passed in object
*
* @exception ArgumentException if the object cannot be converted.
*/
- public static DerGeneralizedTime GetInstance(
- object obj)
+ public static DerGeneralizedTime GetInstance(object obj)
{
if (obj == null || obj is DerGeneralizedTime)
{
return (DerGeneralizedTime)obj;
}
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerGeneralizedTime)
+ return (DerGeneralizedTime)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (DerGeneralizedTime)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct generalized time from byte[]: " + e.Message);
+ }
+ }
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj");
}
/**
- * return a Generalized Time object from a tagged object.
+ * 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.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit 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 isExplicit)
+ public static DerGeneralizedTime GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
-
- if (isExplicit || o is DerGeneralizedTime)
- {
- return GetInstance(o);
- }
-
- return new DerGeneralizedTime(((Asn1OctetString)o).GetOctets());
+ return (DerGeneralizedTime)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
+ private readonly string time;
+
/**
* 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
@@ -305,20 +323,21 @@ namespace Org.BouncyCastle.Asn1
return new PrimitiveEncoding(tagClass, tagNo, GetOctets());
}
- protected override bool Asn1Equals(
- Asn1Object asn1Object)
+ protected override bool Asn1Equals(Asn1Object asn1Object)
{
- DerGeneralizedTime other = asn1Object as DerGeneralizedTime;
-
- if (other == null)
- return false;
-
- return this.time.Equals(other.time);
+ DerGeneralizedTime that = asn1Object as DerGeneralizedTime;
+ return null != that
+ && this.time.Equals(that.time);
}
protected override int Asn1GetHashCode()
{
return time.GetHashCode();
}
+
+ internal static DerGeneralizedTime CreatePrimitive(byte[] contents)
+ {
+ return new DerGeneralizedTime(contents);
+ }
}
}
diff --git a/crypto/src/asn1/DerGraphicString.cs b/crypto/src/asn1/DerGraphicString.cs
index 52ccb7e93..cb32d14eb 100644
--- a/crypto/src/asn1/DerGraphicString.cs
+++ b/crypto/src/asn1/DerGraphicString.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using Org.BouncyCastle.Utilities;
@@ -7,6 +8,18 @@ namespace Org.BouncyCastle.Asn1
public class DerGraphicString
: DerStringBase
{
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerGraphicString), Asn1Tags.GraphicString) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
+
/**
* return a Graphic String from the passed in object
*
@@ -20,16 +33,21 @@ namespace Org.BouncyCastle.Asn1
{
return (DerGraphicString)obj;
}
-
- if (obj is byte[])
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerGraphicString)
+ return (DerGraphicString)asn1Object;
+ }
+ else if (obj is byte[])
{
try
{
- return (DerGraphicString)FromByteArray((byte[])obj);
+ return (DerGraphicString)Meta.Instance.FromByteArray((byte[])obj);
}
- catch (Exception e)
+ catch (IOException e)
{
- throw new ArgumentException("encoding error in GetInstance: " + e.ToString(), "obj");
+ throw new ArgumentException("failed to construct graphic string from byte[]: " + e.Message);
}
}
@@ -39,23 +57,14 @@ namespace Org.BouncyCastle.Asn1
/**
* return a Graphic String from a tagged object.
*
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit true if the object is meant to be explicitly tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot be converted.
* @return a DerGraphicString instance, or null.
*/
- public static DerGraphicString GetInstance(Asn1TaggedObject obj, bool isExplicit)
+ public static DerGraphicString GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
-
- if (isExplicit || o is DerGraphicString)
- {
- return GetInstance(o);
- }
-
- return new DerGraphicString(((Asn1OctetString)o).GetOctets());
+ return (DerGraphicString)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
private readonly byte[] m_contents;
diff --git a/crypto/src/asn1/DerIA5String.cs b/crypto/src/asn1/DerIA5String.cs
index d608930fd..a56879831 100644
--- a/crypto/src/asn1/DerIA5String.cs
+++ b/crypto/src/asn1/DerIA5String.cs
@@ -1,30 +1,56 @@
using System;
-using System.Text;
+using System.IO;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
/**
- * Der IA5String object - this is an ascii string.
+ * IA5String object - this is an Ascii string.
*/
public class DerIA5String
: DerStringBase
{
- private readonly string str;
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerIA5String), Asn1Tags.IA5String) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
/**
- * return a IA5 string from the passed in object
+ * return an IA5 string from the passed in object
*
* @exception ArgumentException if the object cannot be converted.
*/
- public static DerIA5String GetInstance(
- object obj)
+ public static DerIA5String GetInstance(object obj)
{
if (obj == null || obj is DerIA5String)
{
return (DerIA5String)obj;
}
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerIA5String)
+ return (DerIA5String)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (DerIA5String)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct IA5 string from byte[]: " + e.Message);
+ }
+ }
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
@@ -32,40 +58,18 @@ namespace Org.BouncyCastle.Asn1
/**
* 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.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit 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 isExplicit)
+ public static DerIA5String GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
-
- if (isExplicit || o is DerIA5String)
- {
- return GetInstance(o);
- }
-
- return new DerIA5String(((Asn1OctetString)o).GetOctets());
+ return (DerIA5String)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
- /**
- * basic constructor - with bytes.
- */
- public DerIA5String(
- byte[] str)
- : this(Strings.FromAsciiByteArray(str), false)
- {
- }
+ private readonly byte[] m_contents;
- /**
- * basic constructor - without validation.
- */
- public DerIA5String(
- string str)
+ public DerIA5String(string str)
: this(str, false)
{
}
@@ -78,72 +82,81 @@ namespace Org.BouncyCastle.Asn1
* @throws ArgumentException if validate is true and the string
* contains characters that should not be in an IA5String.
*/
- public DerIA5String(
- string str,
- bool validate)
+ 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;
+ m_contents = Strings.ToAsciiByteArray(str);
}
- public override string GetString()
+ public DerIA5String(byte[] contents)
+ : this(contents, true)
+ {
+ }
+
+ internal DerIA5String(byte[] contents, bool clone)
+ {
+ if (null == contents)
+ throw new ArgumentNullException("contents");
+
+ m_contents = clone ? Arrays.Clone(contents) : contents;
+ }
+
+ public override string GetString()
{
- return str;
+ return Strings.FromAsciiByteArray(m_contents);
}
public byte[] GetOctets()
{
- return Strings.ToAsciiByteArray(str);
+ return Arrays.Clone(m_contents);
}
internal override IAsn1Encoding GetEncoding(int encoding)
{
- return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.IA5String, GetOctets());
+ return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.IA5String, m_contents);
}
internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
{
- return new PrimitiveEncoding(tagClass, tagNo, GetOctets());
+ return new PrimitiveEncoding(tagClass, tagNo, m_contents);
}
- protected override int Asn1GetHashCode()
- {
- return this.str.GetHashCode();
+ protected override bool Asn1Equals(Asn1Object asn1Object)
+ {
+ DerIA5String that = asn1Object as DerIA5String;
+ return null != that
+ && Arrays.AreEqual(this.m_contents, that.m_contents);
}
- protected override bool Asn1Equals(
- Asn1Object asn1Object)
+ protected override int Asn1GetHashCode()
{
- DerIA5String other = asn1Object as DerIA5String;
-
- if (other == null)
- return false;
-
- return this.str.Equals(other.str);
+ return Arrays.GetHashCode(m_contents);
}
- /**
+ /**
* 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)
+ public static bool IsIA5String(string str)
{
foreach (char ch in str)
{
if (ch > 0x007f)
- {
return false;
- }
}
return true;
}
- }
+
+ internal static DerIA5String CreatePrimitive(byte[] contents)
+ {
+ return new DerIA5String(contents, false);
+ }
+ }
}
diff --git a/crypto/src/asn1/DerInteger.cs b/crypto/src/asn1/DerInteger.cs
index 8b112f693..c8d4e47df 100644
--- a/crypto/src/asn1/DerInteger.cs
+++ b/crypto/src/asn1/DerInteger.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Utilities;
@@ -8,6 +9,18 @@ namespace Org.BouncyCastle.Asn1
public class DerInteger
: Asn1Object
{
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerInteger), Asn1Tags.Integer) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
+
public const string AllowUnsafeProperty = "Org.BouncyCastle.Asn1.AllowUnsafeInteger";
internal static bool AllowUnsafe()
@@ -27,13 +40,29 @@ namespace Org.BouncyCastle.Asn1
*
* @exception ArgumentException if the object cannot be converted.
*/
- public static DerInteger GetInstance(
- object obj)
+ public static DerInteger GetInstance(object obj)
{
if (obj == null || obj is DerInteger)
{
return (DerInteger)obj;
}
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerInteger)
+ return (DerInteger)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (DerInteger)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct integer from byte[]: " + e.Message);
+ }
+ }
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
@@ -41,27 +70,13 @@ namespace Org.BouncyCastle.Asn1
/**
* return an Integer 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 tagged object cannot
- * be converted.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit 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 isExplicit)
+ public static DerInteger GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- if (obj == null)
- throw new ArgumentNullException("obj");
-
- Asn1Object o = obj.GetObject();
-
- if (isExplicit || o is DerInteger)
- {
- return GetInstance(o);
- }
-
- return new DerInteger(Asn1OctetString.GetInstance(o).GetOctets());
+ return (DerInteger)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
public DerInteger(int value)
@@ -198,6 +213,11 @@ namespace Org.BouncyCastle.Asn1
return Value.ToString();
}
+ internal static DerInteger CreatePrimitive(byte[] contents)
+ {
+ return new DerInteger(contents, false);
+ }
+
internal static int IntValue(byte[] bytes, int start, int signExt)
{
int length = bytes.Length;
diff --git a/crypto/src/asn1/DerNumericString.cs b/crypto/src/asn1/DerNumericString.cs
index bec0c3a52..693ff7d6e 100644
--- a/crypto/src/asn1/DerNumericString.cs
+++ b/crypto/src/asn1/DerNumericString.cs
@@ -1,5 +1,5 @@
using System;
-using System.Text;
+using System.IO;
using Org.BouncyCastle.Utilities;
@@ -11,66 +11,70 @@ namespace Org.BouncyCastle.Asn1
public class DerNumericString
: DerStringBase
{
- private readonly string str;
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerNumericString), Asn1Tags.NumericString) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
/**
- * return a Numeric string from the passed in object
+ * return a numeric string from the passed in object
*
* @exception ArgumentException if the object cannot be converted.
*/
- public static DerNumericString GetInstance(
- object obj)
+ public static DerNumericString GetInstance(object obj)
{
if (obj == null || obj is DerNumericString)
{
return (DerNumericString)obj;
}
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerNumericString)
+ return (DerNumericString)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (DerNumericString)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct numeric string from byte[]: " + e.Message);
+ }
+ }
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
/**
- * return an Numeric string from a tagged object.
+ * return a 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.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit 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 isExplicit)
+ public static DerNumericString GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
-
- if (isExplicit || o is DerNumericString)
- {
- return GetInstance(o);
- }
-
- return new DerNumericString(Asn1OctetString.GetInstance(o).GetOctets());
+ return (DerNumericString)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
- /**
- * basic constructor - with bytes.
- */
- public DerNumericString(
- byte[] str)
- : this(Strings.FromAsciiByteArray(str), false)
- {
- }
+ private readonly byte[] m_contents;
- /**
- * basic constructor - without validation..
- */
- public DerNumericString(
- string str)
- : this(str, false)
- {
- }
+ public DerNumericString(string str)
+ : this(str, false)
+ {
+ }
- /**
+ /**
* Constructor with optional validation.
*
* @param string the base string to wrap.
@@ -78,57 +82,68 @@ namespace Org.BouncyCastle.Asn1
* @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");
+ 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");
+
+ m_contents = Strings.ToAsciiByteArray(str);
+ }
- this.str = str;
+ public DerNumericString(byte[] contents)
+ : this(contents, true)
+ {
}
- public override string GetString()
+ internal DerNumericString(byte[] contents, bool clone)
+ {
+ if (null == contents)
+ throw new ArgumentNullException("contents");
+
+ m_contents = clone ? Arrays.Clone(contents) : contents;
+ }
+
+ public override string GetString()
{
- return str;
+ return Strings.FromAsciiByteArray(m_contents);
}
public byte[] GetOctets()
{
- return Strings.ToAsciiByteArray(str);
+ return Arrays.Clone(m_contents);
}
internal override IAsn1Encoding GetEncoding(int encoding)
{
- return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.NumericString, GetOctets());
+ return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.NumericString, m_contents);
}
internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
{
- return new PrimitiveEncoding(tagClass, tagNo, GetOctets());
+ return new PrimitiveEncoding(tagClass, tagNo, m_contents);
}
- protected override bool Asn1Equals(
- Asn1Object asn1Object)
+ protected override bool Asn1Equals(Asn1Object asn1Object)
{
- DerNumericString other = asn1Object as DerNumericString;
-
- if (other == null)
- return false;
+ DerNumericString that = asn1Object as DerNumericString;
+ return null != that
+ && Arrays.AreEqual(this.m_contents, that.m_contents);
+ }
- return this.str.Equals(other.str);
+ protected override int Asn1GetHashCode()
+ {
+ return Arrays.GetHashCode(m_contents);
}
- /**
+ /**
* 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)
+ public static bool IsNumericString(string str)
{
foreach (char ch in str)
{
@@ -138,5 +153,39 @@ namespace Org.BouncyCastle.Asn1
return true;
}
- }
+
+ internal static bool IsNumericString(byte[] contents)
+ {
+ for (int i = 0; i < contents.Length; ++i)
+ {
+ switch (contents[i])
+ {
+ case 0x20:
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ case 0x38:
+ case 0x39:
+ break;
+ default:
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ internal static DerNumericString CreatePrimitive(byte[] contents)
+ {
+ // TODO Validation - sort out exception types
+ //if (!IsNumericString(contents))
+
+ return new DerNumericString(contents, false);
+ }
+ }
}
diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs
index f91ad2150..8b77f966c 100644
--- a/crypto/src/asn1/DerObjectIdentifier.cs
+++ b/crypto/src/asn1/DerObjectIdentifier.cs
@@ -10,13 +10,25 @@ namespace Org.BouncyCastle.Asn1
public class DerObjectIdentifier
: Asn1Object
{
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerObjectIdentifier), Asn1Tags.ObjectIdentifier) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets(), false);
+ }
+ }
+
public static DerObjectIdentifier FromContents(byte[] contents)
{
return CreatePrimitive(contents, true);
}
/**
- * return an Oid from the passed in object
+ * return an OID from the passed in object
*
* @exception ArgumentException if the object cannot be converted.
*/
@@ -36,7 +48,7 @@ namespace Org.BouncyCastle.Asn1
{
try
{
- return GetInstance(FromByteArray((byte[])obj));
+ return (DerObjectIdentifier)Meta.Instance.FromByteArray((byte[])obj);
}
catch (IOException e)
{
@@ -49,14 +61,19 @@ namespace Org.BouncyCastle.Asn1
public static DerObjectIdentifier GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object baseObject = taggedObject.GetObject();
-
- if (declaredExplicit || baseObject is DerObjectIdentifier)
+ /*
+ * TODO[asn1] This block here is for backward compatibility, but should eventually be removed.
+ *
+ * - see https://github.com/bcgit/bc-java/issues/1015
+ */
+ if (!declaredExplicit && !taggedObject.IsParsed())
{
- return GetInstance(baseObject);
+ Asn1Object baseObject = taggedObject.GetObject();
+ if (!(baseObject is DerObjectIdentifier))
+ return FromContents(Asn1OctetString.GetInstance(baseObject).GetOctets());
}
- return FromContents(Asn1OctetString.GetInstance(baseObject).GetOctets());
+ return (DerObjectIdentifier)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
private const long LongLimit = (Int64.MaxValue >> 7) - 0x7F;
diff --git a/crypto/src/asn1/DerPrintableString.cs b/crypto/src/asn1/DerPrintableString.cs
index 30358e219..3c44a2d52 100644
--- a/crypto/src/asn1/DerPrintableString.cs
+++ b/crypto/src/asn1/DerPrintableString.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using Org.BouncyCastle.Utilities;
@@ -10,61 +11,65 @@ namespace Org.BouncyCastle.Asn1
public class DerPrintableString
: DerStringBase
{
- private readonly string str;
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerPrintableString), Asn1Tags.PrintableString) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
/**
* return a printable string from the passed in object.
*
* @exception ArgumentException if the object cannot be converted.
*/
- public static DerPrintableString GetInstance(
- object obj)
+ public static DerPrintableString GetInstance(object obj)
{
if (obj == null || obj is DerPrintableString)
{
return (DerPrintableString)obj;
}
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerPrintableString)
+ return (DerPrintableString)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (DerPrintableString)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct printable string from byte[]: " + e.Message);
+ }
+ }
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
/**
- * return a Printable string from a tagged object.
+ * 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.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit 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 isExplicit)
+ public static DerPrintableString GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
-
- if (isExplicit || o is DerPrintableString)
- {
- return GetInstance(o);
- }
-
- return new DerPrintableString(Asn1OctetString.GetInstance(o).GetOctets());
+ return (DerPrintableString)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
- /**
- * basic constructor - byte encoded string.
- */
- public DerPrintableString(
- byte[] str)
- : this(Strings.FromAsciiByteArray(str), false)
- {
- }
+ private readonly byte[] m_contents;
- /**
- * basic constructor - this does not validate the string
- */
- public DerPrintableString(
- string str)
+ public DerPrintableString(string str)
: this(str, false)
{
}
@@ -77,57 +82,69 @@ namespace Org.BouncyCastle.Asn1
* @throws ArgumentException if validate is true and the string
* contains characters that should not be in a PrintableString.
*/
- public DerPrintableString(
- string str,
- bool validate)
+ 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;
+ m_contents = Strings.ToAsciiByteArray(str);
}
- public override string GetString()
+ public DerPrintableString(byte[] contents)
+ : this(contents, true)
+ {
+ }
+
+ internal DerPrintableString(byte[] contents, bool clone)
+ {
+ if (null == contents)
+ throw new ArgumentNullException("contents");
+
+ m_contents = clone ? Arrays.Clone(contents) : contents;
+ }
+
+ public override string GetString()
{
- return str;
+ return Strings.FromAsciiByteArray(m_contents);
}
- public byte[] GetOctets()
+ public byte[] GetOctets()
{
- return Strings.ToAsciiByteArray(str);
+ return Arrays.Clone(m_contents);
}
internal override IAsn1Encoding GetEncoding(int encoding)
{
- return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.PrintableString, GetOctets());
+ return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.PrintableString, m_contents);
}
internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
{
- return new PrimitiveEncoding(tagClass, tagNo, GetOctets());
+ return new PrimitiveEncoding(tagClass, tagNo, m_contents);
}
protected override bool Asn1Equals(
Asn1Object asn1Object)
{
- DerPrintableString other = asn1Object as DerPrintableString;
-
- if (other == null)
- return false;
+ DerPrintableString that = asn1Object as DerPrintableString;
+ return null != that
+ && Arrays.AreEqual(this.m_contents, that.m_contents);
+ }
- return this.str.Equals(other.str);
+ protected override int Asn1GetHashCode()
+ {
+ return Arrays.GetHashCode(m_contents);
}
- /**
+ /**
* 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)
+ public static bool IsPrintableString(string str)
{
foreach (char ch in str)
{
@@ -162,5 +179,10 @@ namespace Org.BouncyCastle.Asn1
return true;
}
- }
+
+ internal static DerPrintableString CreatePrimitive(byte[] contents)
+ {
+ return new DerPrintableString(contents, false);
+ }
+ }
}
diff --git a/crypto/src/asn1/DerT61String.cs b/crypto/src/asn1/DerT61String.cs
index 64a9bd469..a0e4f1d22 100644
--- a/crypto/src/asn1/DerT61String.cs
+++ b/crypto/src/asn1/DerT61String.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using Org.BouncyCastle.Utilities;
@@ -10,97 +11,120 @@ namespace Org.BouncyCastle.Asn1
public class DerT61String
: DerStringBase
{
- private readonly string str;
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerT61String), Asn1Tags.T61String) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
/**
* return a T61 string from the passed in object.
*
* @exception ArgumentException if the object cannot be converted.
*/
- public static DerT61String GetInstance(
- object obj)
+ public static DerT61String GetInstance(object obj)
{
if (obj == null || obj is DerT61String)
{
return (DerT61String)obj;
}
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerT61String)
+ return (DerT61String)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (DerT61String)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct T61 string from byte[]: " + e.Message);
+ }
+ }
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
/**
- * return an T61 string from a tagged object.
+ * return a 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.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit 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 isExplicit)
+ public static DerT61String GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
+ return (DerT61String)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
+ }
- if (isExplicit || o is DerT61String)
- {
- return GetInstance(o);
- }
+ private readonly byte[] m_contents;
- return new DerT61String(Asn1OctetString.GetInstance(o).GetOctets());
+ public DerT61String(string str)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+
+ m_contents = Strings.ToByteArray(str);
}
- /**
- * basic constructor - with bytes.
- */
- public DerT61String(
- byte[] str)
- : this(Strings.FromByteArray(str))
- {
+ public DerT61String(byte[] contents)
+ : this(contents, true)
+ {
}
- /**
- * basic constructor - with string.
- */
- public DerT61String(
- string str)
+ internal DerT61String(byte[] contents, bool clone)
{
- if (str == null)
- throw new ArgumentNullException("str");
+ if (null == contents)
+ throw new ArgumentNullException("contents");
- this.str = str;
+ m_contents = clone ? Arrays.Clone(contents) : contents;
}
- public override string GetString()
+ public override string GetString()
{
- return str;
+ return Strings.FromByteArray(m_contents);
}
internal override IAsn1Encoding GetEncoding(int encoding)
{
- return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.T61String, GetOctets());
+ return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.T61String, m_contents);
}
internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
{
- return new PrimitiveEncoding(tagClass, tagNo, GetOctets());
+ return new PrimitiveEncoding(tagClass, tagNo, m_contents);
}
public byte[] GetOctets()
{
- return Strings.ToByteArray(str);
+ return Arrays.Clone(m_contents);
}
- protected override bool Asn1Equals(
- Asn1Object asn1Object)
- {
- DerT61String other = asn1Object as DerT61String;
+ protected override bool Asn1Equals(Asn1Object asn1Object)
+ {
+ DerT61String that = asn1Object as DerT61String;
+ return null != that
+ && Arrays.AreEqual(this.m_contents, that.m_contents);
+ }
- if (other == null)
- return false;
+ protected override int Asn1GetHashCode()
+ {
+ return Arrays.GetHashCode(m_contents);
+ }
- return this.str.Equals(other.str);
+ internal static DerT61String CreatePrimitive(byte[] contents)
+ {
+ return new DerT61String(contents, false);
}
- }
+ }
}
diff --git a/crypto/src/asn1/DerUTCTime.cs b/crypto/src/asn1/DerUTCTime.cs
index eaa902e71..cb3f13353 100644
--- a/crypto/src/asn1/DerUTCTime.cs
+++ b/crypto/src/asn1/DerUTCTime.cs
@@ -1,6 +1,6 @@
using System;
using System.Globalization;
-using System.Text;
+using System.IO;
using Org.BouncyCastle.Utilities;
@@ -12,47 +12,64 @@ namespace Org.BouncyCastle.Asn1
public class DerUtcTime
: Asn1Object
{
- private readonly string time;
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerUtcTime), Asn1Tags.UtcTime) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
/**
- * return an UTC Time from the passed in object.
+ * return a UTC Time from the passed in object.
*
* @exception ArgumentException if the object cannot be converted.
*/
- public static DerUtcTime GetInstance(
- object obj)
+ public static DerUtcTime GetInstance(object obj)
{
if (obj == null || obj is DerUtcTime)
{
return (DerUtcTime)obj;
}
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerUtcTime)
+ return (DerUtcTime)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (DerUtcTime)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct UTC time from byte[]: " + e.Message);
+ }
+ }
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
/**
- * return an UTC Time from a tagged object.
+ * return a 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.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit 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 isExplicit)
+ public static DerUtcTime GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
-
- if (isExplicit || o is DerUtcTime)
- {
- return GetInstance(o);
- }
-
- return new DerUtcTime(((Asn1OctetString)o).GetOctets());
+ return (DerUtcTime)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
+ private readonly string time;
+
/**
* 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
@@ -62,8 +79,7 @@ namespace Org.BouncyCastle.Asn1
* <p>
* @param time the time string.</p>
*/
- public DerUtcTime(
- string time)
+ public DerUtcTime(string time)
{
if (time == null)
throw new ArgumentNullException("time");
@@ -83,8 +99,7 @@ namespace Org.BouncyCastle.Asn1
/**
* base constructor from a DateTime object
*/
- public DerUtcTime(
- DateTime time)
+ public DerUtcTime(DateTime time)
{
#if PORTABLE
this.time = time.ToUniversalTime().ToString("yyMMddHHmmss", CultureInfo.InvariantCulture) + "Z";
@@ -93,13 +108,12 @@ namespace Org.BouncyCastle.Asn1
#endif
}
- internal DerUtcTime(
- byte[] bytes)
+ internal DerUtcTime(byte[] contents)
{
//
// explicitly convert to characters
//
- this.time = Strings.FromAsciiByteArray(bytes);
+ this.time = Strings.FromAsciiByteArray(contents);
}
// public DateTime ToDateTime()
@@ -139,9 +153,7 @@ namespace Org.BouncyCastle.Asn1
return ParseDateString(AdjustedTimeString, @"yyyyMMddHHmmss'GMT'zzz");
}
- private DateTime ParseDateString(
- string dateStr,
- string formatStr)
+ private DateTime ParseDateString(string dateStr, string formatStr)
{
DateTime dt = DateTime.ParseExact(
dateStr,
@@ -247,15 +259,11 @@ namespace Org.BouncyCastle.Asn1
return new PrimitiveEncoding(tagClass, tagNo, GetOctets());
}
- protected override bool Asn1Equals(
- Asn1Object asn1Object)
+ protected override bool Asn1Equals(Asn1Object asn1Object)
{
- DerUtcTime other = asn1Object as DerUtcTime;
-
- if (other == null)
- return false;
-
- return this.time.Equals(other.time);
+ DerUtcTime that = asn1Object as DerUtcTime;
+ return null != that
+ && this.time.Equals(that.time);
}
protected override int Asn1GetHashCode()
@@ -267,5 +275,10 @@ namespace Org.BouncyCastle.Asn1
{
return time;
}
- }
+
+ internal static DerUtcTime CreatePrimitive(byte[] contents)
+ {
+ return new DerUtcTime(contents);
+ }
+ }
}
diff --git a/crypto/src/asn1/DerUTF8String.cs b/crypto/src/asn1/DerUTF8String.cs
index 24023cd6c..d15a19d39 100644
--- a/crypto/src/asn1/DerUTF8String.cs
+++ b/crypto/src/asn1/DerUTF8String.cs
@@ -1,5 +1,5 @@
using System;
-using System.Text;
+using System.IO;
using Org.BouncyCastle.Utilities;
@@ -11,92 +11,112 @@ namespace Org.BouncyCastle.Asn1
public class DerUtf8String
: DerStringBase
{
- private readonly string str;
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerUtf8String), Asn1Tags.Utf8String) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
/**
* return an UTF8 string from the passed in object.
*
* @exception ArgumentException if the object cannot be converted.
*/
- public static DerUtf8String GetInstance(
- object obj)
+ public static DerUtf8String GetInstance(object obj)
{
if (obj == null || obj is DerUtf8String)
{
return (DerUtf8String)obj;
}
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerUtf8String)
+ return (DerUtf8String)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (DerUtf8String)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct UTF8 string from byte[]: " + e.Message);
+ }
+ }
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
/**
- * return an UTF8 string from a tagged object.
+ * return a 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.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit 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 isExplicit)
+ public static DerUtf8String GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
+ return (DerUtf8String)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
+ }
- if (isExplicit || o is DerUtf8String)
- {
- return GetInstance(o);
- }
+ private readonly byte[] m_contents;
- return new DerUtf8String(Asn1OctetString.GetInstance(o).GetOctets());
+ public DerUtf8String(string str)
+ : this(Strings.ToUtf8ByteArray(str), false)
+ {
}
- /**
- * basic constructor - byte encoded string.
- */
- public DerUtf8String(
- byte[] str)
- : this(Encoding.UTF8.GetString(str, 0, str.Length))
+ public DerUtf8String(byte[] contents)
+ : this(contents, true)
{
}
- /**
- * basic constructor
- */
- public DerUtf8String(
- string str)
+ internal DerUtf8String(byte[] contents, bool clone)
{
- if (str == null)
- throw new ArgumentNullException("str");
+ if (null == contents)
+ throw new ArgumentNullException("contents");
- this.str = str;
+ m_contents = clone ? Arrays.Clone(contents) : contents;
}
- public override string GetString()
+ public override string GetString()
{
- return str;
+ return Strings.FromUtf8ByteArray(m_contents);
}
- protected override bool Asn1Equals(
- Asn1Object asn1Object)
+ protected override bool Asn1Equals(Asn1Object asn1Object)
{
- DerUtf8String other = asn1Object as DerUtf8String;
-
- if (other == null)
- return false;
+ DerUtf8String that = asn1Object as DerUtf8String;
+ return null != that
+ && Arrays.AreEqual(this.m_contents, that.m_contents);
+ }
- return this.str.Equals(other.str);
+ protected override int Asn1GetHashCode()
+ {
+ return Arrays.GetHashCode(m_contents);
}
internal override IAsn1Encoding GetEncoding(int encoding)
{
- return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.Utf8String, Encoding.UTF8.GetBytes(str));
+ return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.Utf8String, m_contents);
}
internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
{
- return new PrimitiveEncoding(tagClass, tagNo, Encoding.UTF8.GetBytes(str));
+ return new PrimitiveEncoding(tagClass, tagNo, m_contents);
+ }
+
+ internal static DerUtf8String CreatePrimitive(byte[] contents)
+ {
+ return new DerUtf8String(contents, false);
}
}
}
diff --git a/crypto/src/asn1/DerUniversalString.cs b/crypto/src/asn1/DerUniversalString.cs
index 1ae989f93..e4e93bd7d 100644
--- a/crypto/src/asn1/DerUniversalString.cs
+++ b/crypto/src/asn1/DerUniversalString.cs
@@ -1,4 +1,6 @@
using System;
+using System.Diagnostics;
+using System.IO;
using System.Text;
using Org.BouncyCastle.Utilities;
@@ -6,17 +8,27 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
/**
- * Der UniversalString object.
+ * 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' };
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerUniversalString), Asn1Tags.UniversalString) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
- private readonly byte[] str;
+ private static readonly char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
/**
- * return a Universal string from the passed in object.
+ * return a universal string from the passed in object.
*
* @exception ArgumentException if the object cannot be converted.
*/
@@ -27,85 +39,134 @@ namespace Org.BouncyCastle.Asn1
{
return (DerUniversalString)obj;
}
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerUniversalString)
+ return (DerUniversalString)asn1Object;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return (DerUniversalString)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct universal string from byte[]: " + e.Message);
+ }
+ }
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
/**
- * return a Universal string from a tagged object.
+ * 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.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit 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 isExplicit)
+ public static DerUniversalString GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
+ return (DerUniversalString)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
+ }
- if (isExplicit || o is DerUniversalString)
- {
- return GetInstance(o);
- }
+ private readonly byte[] m_contents;
- return new DerUniversalString(Asn1OctetString.GetInstance(o).GetOctets());
+ public DerUniversalString(byte[] contents)
+ : this(contents, true)
+ {
}
- /**
- * basic constructor - byte encoded string.
- */
- public DerUniversalString(
- byte[] str)
+ internal DerUniversalString(byte[] contents, bool clone)
{
- if (str == null)
- throw new ArgumentNullException("str");
+ if (null == contents)
+ throw new ArgumentNullException("contents");
- this.str = str;
+ m_contents = clone ? Arrays.Clone(contents) : contents;
}
public override string GetString()
{
- StringBuilder buffer = new StringBuilder("#");
- byte[] enc = GetDerEncoded();
+ int dl = m_contents.Length;
+ int capacity = 3 + 2 * (Asn1OutputStream.GetLengthOfDL(dl) + dl);
+ StringBuilder buf = new StringBuilder("#1C", capacity);
+ EncodeHexDL(buf, dl);
- for (int i = 0; i != enc.Length; i++)
- {
- uint ubyte = enc[i];
- buffer.Append(table[(ubyte >> 4) & 0xf]);
- buffer.Append(table[enc[i] & 0xf]);
- }
+ for (int i = 0; i < dl; ++i)
+ {
+ EncodeHexByte(buf, m_contents[i]);
+ }
- return buffer.ToString();
+ Debug.Assert(buf.Length == capacity);
+ return buf.ToString();
}
- public byte[] GetOctets()
+ public byte[] GetOctets()
{
- return (byte[]) str.Clone();
+ return Arrays.Clone(m_contents);
}
internal override IAsn1Encoding GetEncoding(int encoding)
{
- return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.UniversalString, this.str);
+ return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.UniversalString, m_contents);
}
internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
{
- return new PrimitiveEncoding(tagClass, tagNo, this.str);
+ return new PrimitiveEncoding(tagClass, tagNo, m_contents);
+ }
+
+ protected override bool Asn1Equals(Asn1Object asn1Object)
+ {
+ DerUniversalString that = asn1Object as DerUniversalString;
+ return null != that
+ && Arrays.AreEqual(this.m_contents, that.m_contents);
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return Arrays.GetHashCode(m_contents);
+ }
+
+ internal static DerUniversalString CreatePrimitive(byte[] contents)
+ {
+ return new DerUniversalString(contents, false);
+ }
+
+ private static void EncodeHexByte(StringBuilder buf, int i)
+ {
+ buf.Append(table[(i >> 4) & 0xF]);
+ buf.Append(table[i & 0xF]);
}
- protected override bool Asn1Equals(
- Asn1Object asn1Object)
- {
- DerUniversalString other = asn1Object as DerUniversalString;
+ private static void EncodeHexDL(StringBuilder buf, int dl)
+ {
+ if (dl < 128)
+ {
+ EncodeHexByte(buf, dl);
+ return;
+ }
+
+ byte[] stack = new byte[5];
+ int pos = 5;
- if (other == null)
- return false;
+ do
+ {
+ stack[--pos] = (byte)dl;
+ dl >>= 8;
+ }
+ while (dl != 0);
+
+ int count = stack.Length - pos;
+ stack[--pos] = (byte)(0x80 | count);
-// return this.GetString().Equals(other.GetString());
- return Arrays.AreEqual(this.str, other.str);
+ do
+ {
+ EncodeHexByte(buf, stack[pos++]);
+ }
+ while (pos < stack.Length);
}
}
}
diff --git a/crypto/src/asn1/DerVideotexString.cs b/crypto/src/asn1/DerVideotexString.cs
index 3511663d2..a5fbe0602 100644
--- a/crypto/src/asn1/DerVideotexString.cs
+++ b/crypto/src/asn1/DerVideotexString.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using Org.BouncyCastle.Utilities;
@@ -7,10 +8,20 @@ namespace Org.BouncyCastle.Asn1
public class DerVideotexString
: DerStringBase
{
- private readonly byte[] mString;
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerVideotexString), Asn1Tags.VideotexString) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
/**
- * return a Videotex String from the passed in object
+ * return a videotex string from the passed in object
*
* @param obj a DERVideotexString or an object that can be converted into one.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -22,16 +33,21 @@ namespace Org.BouncyCastle.Asn1
{
return (DerVideotexString)obj;
}
-
- if (obj is byte[])
+ else if (obj is IAsn1Convertible)
+ {
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerVideotexString)
+ return (DerVideotexString)asn1Object;
+ }
+ else if (obj is byte[])
{
try
{
- return (DerVideotexString)FromByteArray((byte[])obj);
+ return (DerVideotexString)Meta.Instance.FromByteArray((byte[])obj);
}
- catch (Exception e)
+ catch (IOException e)
{
- throw new ArgumentException("encoding error in GetInstance: " + e.ToString(), "obj");
+ throw new ArgumentException("failed to construct videotex string from byte[]: " + e.Message);
}
}
@@ -39,70 +55,68 @@ namespace Org.BouncyCastle.Asn1
}
/**
- * return a Videotex String from a tagged object.
+ * return a videotex string from a tagged object.
*
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit true if the object is meant to be explicitly tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot be converted.
* @return a DERVideotexString instance, or null.
*/
- public static DerVideotexString GetInstance(Asn1TaggedObject obj, bool isExplicit)
+ public static DerVideotexString GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- Asn1Object o = obj.GetObject();
+ return (DerVideotexString)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
+ }
- if (isExplicit || o is DerVideotexString)
- {
- return GetInstance(o);
- }
+ private readonly byte[] m_contents;
- return new DerVideotexString(((Asn1OctetString)o).GetOctets());
+ public DerVideotexString(byte[] contents)
+ : this(contents, true)
+ {
}
- /**
- * basic constructor - with bytes.
- * @param string the byte encoding of the characters making up the string.
- */
- public DerVideotexString(byte[] encoding)
+ internal DerVideotexString(byte[] contents, bool clone)
{
- this.mString = Arrays.Clone(encoding);
+ if (null == contents)
+ throw new ArgumentNullException("contents");
+
+ m_contents = clone ? Arrays.Clone(contents) : contents;
}
public override string GetString()
{
- return Strings.FromByteArray(mString);
+ return Strings.FromByteArray(m_contents);
}
public byte[] GetOctets()
{
- return Arrays.Clone(mString);
+ return Arrays.Clone(m_contents);
}
internal override IAsn1Encoding GetEncoding(int encoding)
{
- return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.VideotexString, mString);
+ return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.VideotexString, m_contents);
}
internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
{
- return new PrimitiveEncoding(tagClass, tagNo, mString);
+ return new PrimitiveEncoding(tagClass, tagNo, m_contents);
}
- protected override int Asn1GetHashCode()
- {
- return Arrays.GetHashCode(mString);
+ protected override bool Asn1Equals(Asn1Object asn1Object)
+ {
+ DerVideotexString that = asn1Object as DerVideotexString;
+ return null != that
+ && Arrays.AreEqual(this.m_contents, that.m_contents);
}
- protected override bool Asn1Equals(
- Asn1Object asn1Object)
+ protected override int Asn1GetHashCode()
{
- DerVideotexString other = asn1Object as DerVideotexString;
-
- if (other == null)
- return false;
+ return Arrays.GetHashCode(m_contents);
+ }
- return Arrays.AreEqual(mString, other.mString);
+ internal static DerVideotexString CreatePrimitive(byte[] contents)
+ {
+ return new DerVideotexString(contents, false);
}
}
}
diff --git a/crypto/src/asn1/DerVisibleString.cs b/crypto/src/asn1/DerVisibleString.cs
index cbbd9cc98..359370040 100644
--- a/crypto/src/asn1/DerVisibleString.cs
+++ b/crypto/src/asn1/DerVisibleString.cs
@@ -1,20 +1,30 @@
using System;
-using System.Text;
+using System.IO;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
/**
- * Der VisibleString object.
+ * VisibleString object.
*/
public class DerVisibleString
: DerStringBase
{
- private readonly string str;
+ internal class Meta : Asn1UniversalType
+ {
+ internal static readonly Asn1UniversalType Instance = new Meta();
+
+ private Meta() : base(typeof(DerVisibleString), Asn1Tags.VisibleString) {}
+
+ internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+ {
+ return CreatePrimitive(octetString.GetOctets());
+ }
+ }
/**
- * return a Visible string from the passed in object.
+ * return a visible string from the passed in object.
*
* @exception ArgumentException if the object cannot be converted.
*/
@@ -25,91 +35,97 @@ namespace Org.BouncyCastle.Asn1
{
return (DerVisibleString)obj;
}
-
- if (obj is Asn1OctetString)
+ else if (obj is IAsn1Convertible)
{
- return new DerVisibleString(((Asn1OctetString)obj).GetOctets());
+ Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
+ if (asn1Object is DerVisibleString)
+ return (DerVisibleString)asn1Object;
}
-
- if (obj is Asn1TaggedObject)
+ else if (obj is byte[])
{
- return GetInstance(((Asn1TaggedObject)obj).GetObject());
+ try
+ {
+ return (DerVisibleString)Meta.Instance.FromByteArray((byte[])obj);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct visible string from byte[]: " + e.Message);
+ }
}
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
/**
- * return a Visible string from a tagged object.
+ * 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.
+ * @param taggedObject the tagged object holding the object we want
+ * @param declaredExplicit 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)
+ public static DerVisibleString GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
- return GetInstance(obj.GetObject());
+ return (DerVisibleString)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
- /**
- * basic constructor - byte encoded string.
- */
- public DerVisibleString(
- byte[] str)
- : this(Strings.FromAsciiByteArray(str))
- {
- }
+ private readonly byte[] m_contents;
- /**
- * basic constructor
- */
- public DerVisibleString(
- string str)
+ public DerVisibleString(string str)
{
if (str == null)
throw new ArgumentNullException("str");
- this.str = str;
+ m_contents = Strings.ToAsciiByteArray(str);
}
- public override string GetString()
+ public DerVisibleString(byte[] contents)
+ : this(contents, true)
{
- return str;
+ }
+
+ internal DerVisibleString(byte[] contents, bool clone)
+ {
+ if (null == contents)
+ throw new ArgumentNullException("contents");
+
+ m_contents = clone ? Arrays.Clone(contents) : contents;
+ }
+
+ public override string GetString()
+ {
+ return Strings.FromAsciiByteArray(m_contents);
}
public byte[] GetOctets()
{
- return Strings.ToAsciiByteArray(str);
+ return Arrays.Clone(m_contents);
}
internal override IAsn1Encoding GetEncoding(int encoding)
{
- return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.VisibleString, GetOctets());
+ return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.VisibleString, m_contents);
}
internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
{
- return new PrimitiveEncoding(tagClass, tagNo, GetOctets());
+ return new PrimitiveEncoding(tagClass, tagNo, m_contents);
}
- protected override bool Asn1Equals(
- Asn1Object asn1Object)
- {
- DerVisibleString other = asn1Object as DerVisibleString;
-
- if (other == null)
- return false;
+ protected override bool Asn1Equals(Asn1Object asn1Object)
+ {
+ DerVisibleString that = asn1Object as DerVisibleString;
+ return null != that
+ && Arrays.AreEqual(this.m_contents, that.m_contents);
+ }
- return this.str.Equals(other.str);
+ protected override int Asn1GetHashCode()
+ {
+ return Arrays.GetHashCode(m_contents);
}
- protected override int Asn1GetHashCode()
- {
- return this.str.GetHashCode();
+ internal static DerVisibleString CreatePrimitive(byte[] contents)
+ {
+ return new DerVisibleString(contents, false);
}
}
}
diff --git a/crypto/src/asn1/ocsp/CertStatus.cs b/crypto/src/asn1/ocsp/CertStatus.cs
index 7dd99b844..8a4d2242d 100644
--- a/crypto/src/asn1/ocsp/CertStatus.cs
+++ b/crypto/src/asn1/ocsp/CertStatus.cs
@@ -34,22 +34,23 @@ namespace Org.BouncyCastle.Asn1.Ocsp
this.value = value;
}
- public CertStatus(
- Asn1TaggedObject choice)
+ public CertStatus(Asn1TaggedObject choice)
{
this.tagNo = choice.TagNo;
switch (choice.TagNo)
{
- case 1:
- value = RevokedInfo.GetInstance(choice, false);
- break;
- case 0:
- case 2:
- value = DerNull.Instance;
- break;
- default:
- throw new ArgumentException("Unknown tag encountered: " + choice.TagNo);
+ case 0:
+ value = Asn1Null.GetInstance(choice, false);
+ break;
+ case 1:
+ value = RevokedInfo.GetInstance(choice, false);
+ break;
+ case 2:
+ value = Asn1Null.GetInstance(choice, false);
+ break;
+ default:
+ throw new ArgumentException("Unknown tag encountered: " + Asn1Utilities.GetTagText(choice));
}
}
diff --git a/crypto/test/src/asn1/test/DERUTF8StringTest.cs b/crypto/test/src/asn1/test/DERUTF8StringTest.cs
index be4dace79..15f98a7c4 100644
--- a/crypto/test/src/asn1/test/DERUTF8StringTest.cs
+++ b/crypto/test/src/asn1/test/DERUTF8StringTest.cs
@@ -66,8 +66,9 @@ namespace Org.BouncyCastle.Asn1.Tests
byte[] b1 = new DerUtf8String(s).GetEncoded();
byte[] temp = new byte[b1.Length - 2];
Array.Copy(b1, 2, temp, 0, b1.Length - 2);
- byte[] b2 = new DerUtf8String(new DerOctetString(temp).GetOctets()).GetEncoded();
- if (!Arrays.AreEqual(b1, b2))
+ byte[] b2 = new DerUtf8String(Strings.FromUtf8ByteArray(new DerOctetString(temp).GetOctets()))
+ .GetEncoded();
+ if (!Arrays.AreEqual(b1, b2))
{
return new SimpleTestResult(false, Name + ": failed UTF-8 encoding and decoding");
}
diff --git a/crypto/test/src/asn1/test/SetTest.cs b/crypto/test/src/asn1/test/SetTest.cs
index 57c46603d..b7da0a9b7 100644
--- a/crypto/test/src/asn1/test/SetTest.cs
+++ b/crypto/test/src/asn1/test/SetTest.cs
@@ -83,7 +83,11 @@ namespace Org.BouncyCastle.Asn1.Tests
// create an implicitly tagged "set" without sorting
Asn1TaggedObject tag = new DerTaggedObject(false, 1, new DerSequence(v));
- s = Asn1Set.GetInstance(tag, false);
+
+ // Encode/decode to get 'tag' as a parsed instance
+ tag = (Asn1TaggedObject)Asn1Object.FromByteArray(tag.GetEncoded(Asn1Encodable.Der));;
+
+ s = Asn1Set.GetInstance(tag, false);
if (s[0] is DerBoolean)
{
|