From f00f5ff42a70b110c78621b573ad85fe3812bfb5 Mon Sep 17 00:00:00 2001
From: psoares33
Date: Wed, 17 Dec 2008 11:23:50 +0000
Subject: [PATCH] BouncyCastle update.
git-svn-id: svn://svn.code.sf.net/p/itextsharp/code/trunk@18 820d3149-562b-4f88-9aa4-a8e61a3485cf
---
src/core/itextsharp.csproj | 22 +-
src/core/srcbc/asn1/Asn1TaggedObject.cs | 355 +--
.../srcbc/asn1/DefiniteLengthInputStream.cs | 170 +-
src/core/srcbc/asn1/IAsn1Choice.cs | 17 +
.../srcbc/asn1/IndefiniteLengthInputStream.cs | 199 +-
src/core/srcbc/asn1/esf/OtherHash.cs | 177 +-
.../asn1/esf/SignaturePolicyIdentifier.cs | 129 +-
src/core/srcbc/asn1/esf/SignerAttribute.cs | 96 +
src/core/srcbc/asn1/ess/ESSCertIDv2.cs | 276 +-
.../asn1/isismtt/ocsp/RequestedCertificate.cs | 373 ++-
.../isismtt/x509/DeclarationOfMajority.cs | 341 ++-
src/core/srcbc/asn1/ocsp/CertStatus.cs | 188 +-
src/core/srcbc/asn1/ocsp/ResponderID.cs | 154 +-
src/core/srcbc/asn1/ocsp/TBSRequest.cs | 298 +--
.../srcbc/asn1/oiw/OIWObjectIdentifiers.cs | 53 +-
src/core/srcbc/asn1/pkcs/PBES2Parameters.cs | 109 +-
src/core/srcbc/asn1/pkcs/PBKDF2Params.cs | 162 +-
src/core/srcbc/asn1/x500/DirectoryString.cs | 151 +-
src/core/srcbc/asn1/x509/AccessDescription.cs | 171 +-
src/core/srcbc/asn1/x509/AttCertIssuer.cs | 172 +-
.../asn1/x509/AuthorityInformationAccess.cs | 192 +-
src/core/srcbc/asn1/x509/DisplayText.cs | 344 +--
.../srcbc/asn1/x509/DistributionPointName.cs | 260 +-
src/core/srcbc/asn1/x509/GeneralName.cs | 812 +++---
src/core/srcbc/asn1/x509/GeneralNames.cs | 180 +-
src/core/srcbc/asn1/x509/RoleSyntax.cs | 468 ++--
src/core/srcbc/asn1/x509/Target.cs | 279 +-
src/core/srcbc/asn1/x509/Time.cs | 252 +-
src/core/srcbc/asn1/x509/X509Name.cs | 2112 +++++++--------
.../x509/qualified/Iso4217CurrencyCode.cs | 168 +-
.../x509/qualified/TypeOfBiometricData.cs | 182 +-
.../srcbc/asn1/x509/sigi/NameOrPseudonym.cs | 355 ++-
src/core/srcbc/asn1/x9/X962Parameters.cs | 106 +-
src/core/srcbc/asn1/x9/X9ECParameters.cs | 335 +--
src/core/srcbc/bcpg/ArmoredInputStream.cs | 1004 +++----
src/core/srcbc/bcpg/ArmoredOutputStream.cs | 658 ++---
src/core/srcbc/bcpg/SignatureSubpacketTags.cs | 63 +-
src/core/srcbc/bcpg/sig/EmbeddedSignature.cs | 18 +
src/core/srcbc/bcpg/sig/NotationData.cs | 213 +-
src/core/srcbc/bcpg/sig/TrustSignature.cs | 99 +-
src/core/srcbc/cms/CMSPBEKey.cs | 154 +-
src/core/srcbc/cms/CMSSignedDataGenerator.cs | 1069 ++++----
src/core/srcbc/cms/CMSSignedDataParser.cs | 1011 ++++----
.../srcbc/cms/CMSSignedDataStreamGenerator.cs | 1476 ++++++-----
src/core/srcbc/cms/PKCS5Scheme2PBEKey.cs | 85 +-
src/core/srcbc/cms/PKCS5Scheme2UTF8PBEKey.cs | 85 +-
.../srcbc/cms/PasswordRecipientInformation.cs | 173 +-
src/core/srcbc/cms/SignerInformation.cs | 1274 ++++-----
src/core/srcbc/crypto/BufferedBlockCipher.cs | 752 +++---
.../srcbc/crypto/encodings/Pkcs1Encoding.cs | 461 ++--
.../crypto/engines/CamelliaLightEngine.cs | 581 +++++
src/core/srcbc/crypto/io/CipherStream.cs | 458 ++--
.../srcbc/crypto/paddings/Pkcs7Padding.cs | 156 +-
.../crypto/prng/DigestRandomGenerator.cs | 236 +-
src/core/srcbc/crypto/signers/ECDsaSigner.cs | 306 +--
.../crypto/tls/TlsBlockCipherCipherSuite.cs | 392 +--
.../srcbc/crypto/tls/TlsProtocolHandler.cs | 2304 ++++++++---------
src/core/srcbc/openpgp/PgpKeyRingGenerator.cs | 332 +--
src/core/srcbc/openpgp/PgpOnePassSignature.cs | 358 +--
src/core/srcbc/openpgp/PgpPublicKey.cs | 1732 +++++++------
src/core/srcbc/openpgp/PgpPublicKeyRing.cs | 381 +--
src/core/srcbc/openpgp/PgpSecretKey.cs | 1383 +++++-----
src/core/srcbc/openpgp/PgpSecretKeyRing.cs | 516 ++--
src/core/srcbc/openpgp/PgpSignature.cs | 843 +++---
.../openpgp/PgpSignatureSubpacketGenerator.cs | 304 ++-
.../pkcs/EncryptedPrivateKeyInfoFactory.cs | 150 +-
src/core/srcbc/security/AgreementUtilities.cs | 199 +-
src/core/srcbc/security/GeneratorUtilities.cs | 705 ++---
src/core/srcbc/security/PrivateKeyFactory.cs | 391 +--
src/core/srcbc/x509/PEMParser.cs | 188 +-
.../srcbc/x509/store/X509CertStoreSelector.cs | 674 ++---
.../srcbc/x509/store/X509CrlStoreSelector.cs | 566 ++--
src/core/srcbc/x509/store/X509StoreFactory.cs | 105 +-
73 files changed, 16345 insertions(+), 15168 deletions(-)
create mode 100644 src/core/srcbc/asn1/IAsn1Choice.cs
create mode 100644 src/core/srcbc/asn1/esf/SignerAttribute.cs
create mode 100644 src/core/srcbc/bcpg/sig/EmbeddedSignature.cs
create mode 100644 src/core/srcbc/crypto/engines/CamelliaLightEngine.cs
diff --git a/src/core/itextsharp.csproj b/src/core/itextsharp.csproj
index c0e28f6..450ed7a 100644
--- a/src/core/itextsharp.csproj
+++ b/src/core/itextsharp.csproj
@@ -1,7 +1,7 @@
@@ -2517,6 +2517,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
+
+
+
+
- * Note: if the object has been read from an input stream, the only
- * time you can be sure if isExplicit is returning the true state of
- * affairs is if it returns false. An implicitly tagged object may appear
- * to be explicitly tagged, so you need to understand the context under
- * which the reading was done as well, see GetObject below.
- */
- public bool IsExplicit()
- {
- return explicitly;
- }
-
- public bool IsEmpty()
- {
- return false; //empty;
- }
-
- /**
- * return whatever was following the tag.
- *
- * Note: tagged objects are generally context dependent if you're
- * trying to extract a tagged object you should be going via the
- * appropriate GetInstance method.
- */
- public Asn1Object GetObject()
- {
- if (obj != null)
- {
- return obj.ToAsn1Object();
- }
-
- return null;
- }
-
- /**
- * Return the object held in this tagged object as a parser assuming it has
- * the type of the passed in tag. If the object doesn't have a parser
- * associated with it, the base object is returned.
- */
- public IAsn1Convertible GetObjectParser(
- int tag,
- bool isExplicit)
- {
- switch (tag)
- {
- case Asn1Tags.Set:
- return Asn1Set.GetInstance(this, isExplicit).Parser;
- case Asn1Tags.Sequence:
- return Asn1Sequence.GetInstance(this, isExplicit).Parser;
- case Asn1Tags.OctetString:
- return Asn1OctetString.GetInstance(this, isExplicit).Parser;
- }
-
- if (isExplicit)
- {
- return GetObject();
- }
-
- throw Platform.CreateNotImplementedException("implicit tagging for tag: " + tag);
- }
-
- public override string ToString()
- {
- return "[" + tagNo + "]" + obj;
- }
- }
-}
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+ public abstract class Asn1TaggedObject
+ : Asn1Object, Asn1TaggedObjectParser
+ {
+ internal int tagNo;
+// internal bool empty;
+ internal bool explicitly = true;
+ internal Asn1Encodable obj;
+
+ static public Asn1TaggedObject GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ if (explicitly)
+ {
+ return (Asn1TaggedObject) obj.GetObject();
+ }
+
+ throw new ArgumentException("implicitly tagged tagged object");
+ }
+
+ static public Asn1TaggedObject GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Asn1TaggedObject)
+ {
+ return (Asn1TaggedObject) obj;
+ }
+
+ throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ /**
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ protected Asn1TaggedObject(
+ int tagNo,
+ Asn1Encodable obj)
+ {
+ this.explicitly = true;
+ this.tagNo = tagNo;
+ this.obj = obj;
+ }
+
+ /**
+ * @param explicitly true if the object is explicitly tagged.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ protected Asn1TaggedObject(
+ bool explicitly,
+ int tagNo,
+ Asn1Encodable obj)
+ {
+ // IAsn1Choice marker interface 'insists' on explicit tagging
+ this.explicitly = explicitly || (obj is IAsn1Choice);
+ this.tagNo = tagNo;
+ this.obj = obj;
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ Asn1TaggedObject other = asn1Object as Asn1TaggedObject;
+
+ if (other == null)
+ return false;
+
+ return this.tagNo == other.tagNo
+// && this.empty == other.empty
+ && this.explicitly == other.explicitly // TODO Should this be part of equality?
+ && Platform.Equals(GetObject(), other.GetObject());
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ int code = tagNo.GetHashCode();
+
+ // TODO: actually this is wrong - the problem is that a re-encoded
+ // object may end up with a different hashCode due to implicit
+ // tagging. As implicit tagging is ambiguous if a sequence is involved
+ // it seems the only correct method for both equals and hashCode is to
+ // compare the encodings...
+// code ^= explicitly.GetHashCode();
+
+ if (obj != null)
+ {
+ code ^= obj.GetHashCode();
+ }
+
+ return code;
+ }
+
+ public int TagNo
+ {
+ get { return tagNo; }
+ }
+
+ /**
+ * return whether or not the object may be explicitly tagged.
+ *
+ * Note: if the object has been read from an input stream, the only
+ * time you can be sure if isExplicit is returning the true state of
+ * affairs is if it returns false. An implicitly tagged object may appear
+ * to be explicitly tagged, so you need to understand the context under
+ * which the reading was done as well, see GetObject below.
+ */
+ public bool IsExplicit()
+ {
+ return explicitly;
+ }
+
+ public bool IsEmpty()
+ {
+ return false; //empty;
+ }
+
+ /**
+ * return whatever was following the tag.
+ *
+ * Note: tagged objects are generally context dependent if you're
+ * trying to extract a tagged object you should be going via the
+ * appropriate GetInstance method.
+ */
+ public Asn1Object GetObject()
+ {
+ if (obj != null)
+ {
+ return obj.ToAsn1Object();
+ }
+
+ return null;
+ }
+
+ /**
+ * Return the object held in this tagged object as a parser assuming it has
+ * the type of the passed in tag. If the object doesn't have a parser
+ * associated with it, the base object is returned.
+ */
+ public IAsn1Convertible GetObjectParser(
+ int tag,
+ bool isExplicit)
+ {
+ switch (tag)
+ {
+ case Asn1Tags.Set:
+ return Asn1Set.GetInstance(this, isExplicit).Parser;
+ case Asn1Tags.Sequence:
+ return Asn1Sequence.GetInstance(this, isExplicit).Parser;
+ case Asn1Tags.OctetString:
+ return Asn1OctetString.GetInstance(this, isExplicit).Parser;
+ }
+
+ if (isExplicit)
+ {
+ return GetObject();
+ }
+
+ throw Platform.CreateNotImplementedException("implicit tagging for tag: " + tag);
+ }
+
+ public override string ToString()
+ {
+ return "[" + tagNo + "]" + obj;
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/DefiniteLengthInputStream.cs b/src/core/srcbc/asn1/DefiniteLengthInputStream.cs
index a01d9d1..2eaf360 100644
--- a/src/core/srcbc/asn1/DefiniteLengthInputStream.cs
+++ b/src/core/srcbc/asn1/DefiniteLengthInputStream.cs
@@ -1,86 +1,84 @@
-using System;
-using System.IO;
-
-using Org.BouncyCastle.Utilities.IO;
-
-namespace Org.BouncyCastle.Asn1
-{
- class DefiniteLengthInputStream
- : LimitedInputStream
- {
- private static readonly byte[] EmptyBytes = new byte[0];
-
- private int _length;
-
- internal DefiniteLengthInputStream(
- Stream inStream,
- int length)
- : base(inStream)
- {
- if (length < 0)
- throw new ArgumentException("negative lengths not allowed", "length");
-
- this._length = length;
- }
-
- public override int ReadByte()
- {
- if (_length > 0)
- {
- int b = _in.ReadByte();
-
- if (b < 0)
- throw new EndOfStreamException();
-
- --_length;
- return b;
- }
-
- SetParentEofDetect(true);
-
- return -1;
- }
-
- public override int Read(
- byte[] buf,
- int off,
- int len)
- {
- if (_length > 0)
- {
- int toRead = System.Math.Min(len, _length);
- int numRead = _in.Read(buf, off, toRead);
-
- if (numRead < 1)
- throw new EndOfStreamException();
-
- _length -= numRead;
- return numRead;
- }
-
- SetParentEofDetect(true);
-
- return 0;
- }
-
- internal byte[] ToArray()
- {
- byte[] bytes;
- if (_length > 0)
- {
- bytes = new byte[_length];
- if (Streams.ReadFully(_in, bytes) < _length)
- throw new EndOfStreamException();
- _length = 0;
- }
- else
- {
- bytes = EmptyBytes;
- }
-
- SetParentEofDetect(true);
-
- return bytes;
- }
- }
-}
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ class DefiniteLengthInputStream
+ : LimitedInputStream
+ {
+ private static readonly byte[] EmptyBytes = new byte[0];
+
+ private int _length;
+
+ internal DefiniteLengthInputStream(
+ Stream inStream,
+ int length)
+ : base(inStream)
+ {
+ if (length < 0)
+ throw new ArgumentException("negative lengths not allowed", "length");
+
+ this._length = length;
+
+ if (length == 0)
+ {
+ SetParentEofDetect(true);
+ }
+ }
+
+ public override int ReadByte()
+ {
+ if (_length == 0)
+ return -1;
+
+ int b = _in.ReadByte();
+
+ if (b < 0)
+ throw new EndOfStreamException();
+
+ if (--_length == 0)
+ {
+ SetParentEofDetect(true);
+ }
+
+ return b;
+ }
+
+ public override int Read(
+ byte[] buf,
+ int off,
+ int len)
+ {
+ if (_length == 0)
+ return 0;
+
+ int toRead = System.Math.Min(len, _length);
+ int numRead = _in.Read(buf, off, toRead);
+
+ if (numRead < 1)
+ throw new EndOfStreamException();
+
+ if ((_length -= numRead) == 0)
+ {
+ SetParentEofDetect(true);
+ }
+
+ return numRead;
+ }
+
+ internal byte[] ToArray()
+ {
+ if (_length == 0)
+ return EmptyBytes;
+
+ byte[] bytes = new byte[_length];
+ if (Streams.ReadFully(_in, bytes) < _length)
+ throw new EndOfStreamException();
+ _length = 0;
+ SetParentEofDetect(true);
+ return bytes;
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/IAsn1Choice.cs b/src/core/srcbc/asn1/IAsn1Choice.cs
new file mode 100644
index 0000000..ecd76e4
--- /dev/null
+++ b/src/core/srcbc/asn1/IAsn1Choice.cs
@@ -0,0 +1,17 @@
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * Marker interface for CHOICE objects - if you implement this in a roll-your-own
+ * object, any attempt to tag the object implicitly will convert the tag to an
+ * explicit one as the encoding rules require.
+ *
+ * If you use this interface your class should also implement the getInstance
+ * pattern which takes a tag object and the tagging mode used.
+ *
+ */
+ public interface IAsn1Choice
+ {
+ // marker interface
+ }
+}
diff --git a/src/core/srcbc/asn1/IndefiniteLengthInputStream.cs b/src/core/srcbc/asn1/IndefiniteLengthInputStream.cs
index 3c45b74..422f90a 100644
--- a/src/core/srcbc/asn1/IndefiniteLengthInputStream.cs
+++ b/src/core/srcbc/asn1/IndefiniteLengthInputStream.cs
@@ -1,95 +1,104 @@
-using System.IO;
-
-namespace Org.BouncyCastle.Asn1
-{
- class IndefiniteLengthInputStream
- : LimitedInputStream
- {
- private int _b1;
- private int _b2;
- private bool _eofReached = false;
- private bool _eofOn00 = true;
-
- internal IndefiniteLengthInputStream(
- Stream inStream)
- : base(inStream)
- {
- _b1 = inStream.ReadByte();
- _b2 = inStream.ReadByte();
- _eofReached = (_b2 < 0);
- }
-
- internal void SetEofOn00(
- bool eofOn00)
- {
- _eofOn00 = eofOn00;
- }
-
- internal bool CheckForEof()
- {
- if (_eofOn00 && (_b1 == 0x00 && _b2 == 0x00))
- {
- _eofReached = true;
- SetParentEofDetect(true);
- }
-
- return _eofReached;
- }
-
- public override int Read(
- byte[] buffer,
- int offset,
- int count)
- {
- // Only use this optimisation if we aren't checking for 00
- if (_eofOn00 || count < 3)
- return base.Read(buffer, offset, count);
-
- if (_eofReached)
- return 0;
-
- int numRead = _in.Read(buffer, offset + 2, count - 2);
-
- if (numRead <= 0)
- {
- // Corrupted stream
- throw new EndOfStreamException();
- }
-
- buffer[offset] = (byte)_b1;
- buffer[offset + 1] = (byte)_b2;
-
- _b1 = _in.ReadByte();
- _b2 = _in.ReadByte();
-
- if (_b2 < 0)
- {
- // Corrupted stream
- throw new EndOfStreamException();
- }
-
- return numRead + 2;
- }
-
- public override int ReadByte()
- {
- if (CheckForEof())
- return -1;
-
- int b = _in.ReadByte();
-
- if (b < 0)
- {
- // Corrupted stream
- throw new EndOfStreamException();
- }
-
- int v = _b1;
-
- _b1 = _b2;
- _b2 = b;
-
- return v;
- }
- }
-}
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ class IndefiniteLengthInputStream
+ : LimitedInputStream
+ {
+ private int _b1;
+ private int _b2;
+ private bool _eofReached = false;
+ private bool _eofOn00 = true;
+
+ internal IndefiniteLengthInputStream(
+ Stream inStream)
+ : base(inStream)
+ {
+ _b1 = inStream.ReadByte();
+ _b2 = inStream.ReadByte();
+
+ if (_b2 < 0)
+ {
+ // Corrupted stream
+ throw new EndOfStreamException();
+ }
+
+ CheckForEof();
+ }
+
+ internal void SetEofOn00(
+ bool eofOn00)
+ {
+ _eofOn00 = eofOn00;
+ CheckForEof();
+ }
+
+ private bool CheckForEof()
+ {
+ if (!_eofReached && _eofOn00 && (_b1 == 0x00 && _b2 == 0x00))
+ {
+ _eofReached = true;
+ SetParentEofDetect(true);
+ }
+
+ return _eofReached;
+ }
+
+ public override int Read(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ // Only use this optimisation if we aren't checking for 00
+ if (_eofOn00 || count < 3)
+ return base.Read(buffer, offset, count);
+
+ if (_eofReached)
+ return 0;
+
+ int numRead = _in.Read(buffer, offset + 2, count - 2);
+
+ if (numRead <= 0)
+ {
+ // Corrupted stream
+ throw new EndOfStreamException();
+ }
+
+ buffer[offset] = (byte)_b1;
+ buffer[offset + 1] = (byte)_b2;
+
+ _b1 = _in.ReadByte();
+ _b2 = _in.ReadByte();
+
+ if (_b2 < 0)
+ {
+ // Corrupted stream
+ throw new EndOfStreamException();
+ }
+
+ return numRead + 2;
+ }
+
+ public override int ReadByte()
+ {
+ if (CheckForEof())
+ return -1;
+
+ int b = _in.ReadByte();
+
+ if (b < 0)
+ {
+ // Corrupted stream
+ throw new EndOfStreamException();
+ }
+
+ int v = _b1;
+
+ _b1 = _b2;
+ _b2 = b;
+
+ return v;
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/esf/OtherHash.cs b/src/core/srcbc/asn1/esf/OtherHash.cs
index 8f36c20..2ee1624 100644
--- a/src/core/srcbc/asn1/esf/OtherHash.cs
+++ b/src/core/srcbc/asn1/esf/OtherHash.cs
@@ -1,89 +1,88 @@
-using System;
-
-using Org.BouncyCastle.Asn1.Oiw;
-using Org.BouncyCastle.Asn1.X509;
-
-namespace Org.BouncyCastle.Asn1.Esf
-{
- ///
- ///
- /// OtherHash ::= CHOICE {
- /// sha1Hash OtherHashValue, -- This contains a SHA-1 hash
- /// otherHash OtherHashAlgAndValue
- /// }
- ///
- /// OtherHashValue ::= OCTET STRING
- ///
- ///
- public class OtherHash
- : Asn1Encodable
- //, Asn1Choice
- {
- private readonly Asn1OctetString sha1Hash;
- private readonly OtherHashAlgAndValue otherHash;
-
- public static OtherHash GetInstance(
- object obj)
- {
- if (obj == null || obj is OtherHash)
- return (OtherHash) obj;
-
- if (obj is Asn1OctetString)
- return new OtherHash((Asn1OctetString) obj);
-
- return new OtherHash(
- OtherHashAlgAndValue.GetInstance(obj));
- }
-
- public OtherHash(
- byte[] sha1Hash)
- {
- if (sha1Hash == null)
- throw new ArgumentNullException("sha1Hash");
-
- this.sha1Hash = new DerOctetString(sha1Hash);
- }
-
- public OtherHash(
- Asn1OctetString sha1Hash)
- {
- if (sha1Hash == null)
- throw new ArgumentNullException("sha1Hash");
-
- this.sha1Hash = sha1Hash;
- }
-
- public OtherHash(
- OtherHashAlgAndValue otherHash)
- {
- if (otherHash == null)
- throw new ArgumentNullException("otherHash");
-
- this.otherHash = otherHash;
- }
-
- public AlgorithmIdentifier HashAlgorithm
- {
- get
- {
- return otherHash == null
- ? new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1)
- : otherHash.HashAlgorithm;
- }
- }
-
- public byte[] GetHashValue()
- {
- return otherHash == null
- ? sha1Hash.GetOctets()
- : otherHash.GetHashValue();
- }
-
- public override Asn1Object ToAsn1Object()
- {
- return otherHash == null
- ? sha1Hash
- : otherHash.ToAsn1Object();
- }
- }
-}
+using System;
+
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ ///
+ ///
+ /// OtherHash ::= CHOICE {
+ /// sha1Hash OtherHashValue, -- This contains a SHA-1 hash
+ /// otherHash OtherHashAlgAndValue
+ /// }
+ ///
+ /// OtherHashValue ::= OCTET STRING
+ ///
+ ///
+ public class OtherHash
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly Asn1OctetString sha1Hash;
+ private readonly OtherHashAlgAndValue otherHash;
+
+ public static OtherHash GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OtherHash)
+ return (OtherHash) obj;
+
+ if (obj is Asn1OctetString)
+ return new OtherHash((Asn1OctetString) obj);
+
+ return new OtherHash(
+ OtherHashAlgAndValue.GetInstance(obj));
+ }
+
+ public OtherHash(
+ byte[] sha1Hash)
+ {
+ if (sha1Hash == null)
+ throw new ArgumentNullException("sha1Hash");
+
+ this.sha1Hash = new DerOctetString(sha1Hash);
+ }
+
+ public OtherHash(
+ Asn1OctetString sha1Hash)
+ {
+ if (sha1Hash == null)
+ throw new ArgumentNullException("sha1Hash");
+
+ this.sha1Hash = sha1Hash;
+ }
+
+ public OtherHash(
+ OtherHashAlgAndValue otherHash)
+ {
+ if (otherHash == null)
+ throw new ArgumentNullException("otherHash");
+
+ this.otherHash = otherHash;
+ }
+
+ public AlgorithmIdentifier HashAlgorithm
+ {
+ get
+ {
+ return otherHash == null
+ ? new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1)
+ : otherHash.HashAlgorithm;
+ }
+ }
+
+ public byte[] GetHashValue()
+ {
+ return otherHash == null
+ ? sha1Hash.GetOctets()
+ : otherHash.GetHashValue();
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return otherHash == null
+ ? sha1Hash
+ : otherHash.ToAsn1Object();
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/esf/SignaturePolicyIdentifier.cs b/src/core/srcbc/asn1/esf/SignaturePolicyIdentifier.cs
index 0093e40..3a639f4 100644
--- a/src/core/srcbc/asn1/esf/SignaturePolicyIdentifier.cs
+++ b/src/core/srcbc/asn1/esf/SignaturePolicyIdentifier.cs
@@ -1,65 +1,64 @@
-using System;
-
-namespace Org.BouncyCastle.Asn1.Esf
-{
- ///
- ///
- /// SignaturePolicyIdentifier ::= CHOICE {
- /// SignaturePolicyId SignaturePolicyId,
- /// SignaturePolicyImplied SignaturePolicyImplied
- /// }
- ///
- /// SignaturePolicyImplied ::= NULL
- ///
- ///
- public class SignaturePolicyIdentifier
- : Asn1Encodable
- //, Asn1Choice
- {
- private readonly SignaturePolicyId sigPolicy;
-
- public static SignaturePolicyIdentifier GetInstance(
- object obj)
- {
- if (obj == null || obj is SignaturePolicyIdentifier)
- return (SignaturePolicyIdentifier) obj;
-
- if (obj is SignaturePolicyId)
- return new SignaturePolicyIdentifier((SignaturePolicyId) obj);
-
- if (obj is Asn1Null)
- return new SignaturePolicyIdentifier();
-
- throw new ArgumentException(
- "Unknown object in 'SignaturePolicyIdentifier' factory: "
- + obj.GetType().Name,
- "obj");
- }
-
- public SignaturePolicyIdentifier()
- {
- this.sigPolicy = null;
- }
-
- public SignaturePolicyIdentifier(
- SignaturePolicyId signaturePolicyId)
- {
- if (signaturePolicyId == null)
- throw new ArgumentNullException("signaturePolicyId");
-
- this.sigPolicy = signaturePolicyId;
- }
-
- public SignaturePolicyId SignaturePolicyId
- {
- get { return sigPolicy; }
- }
-
- public override Asn1Object ToAsn1Object()
- {
- return sigPolicy == null
- ? DerNull.Instance
- : sigPolicy.ToAsn1Object();
- }
- }
-}
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ ///
+ ///
+ /// SignaturePolicyIdentifier ::= CHOICE {
+ /// SignaturePolicyId SignaturePolicyId,
+ /// SignaturePolicyImplied SignaturePolicyImplied
+ /// }
+ ///
+ /// SignaturePolicyImplied ::= NULL
+ ///
+ ///
+ public class SignaturePolicyIdentifier
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly SignaturePolicyId sigPolicy;
+
+ public static SignaturePolicyIdentifier GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is SignaturePolicyIdentifier)
+ return (SignaturePolicyIdentifier) obj;
+
+ if (obj is SignaturePolicyId)
+ return new SignaturePolicyIdentifier((SignaturePolicyId) obj);
+
+ if (obj is Asn1Null)
+ return new SignaturePolicyIdentifier();
+
+ throw new ArgumentException(
+ "Unknown object in 'SignaturePolicyIdentifier' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ public SignaturePolicyIdentifier()
+ {
+ this.sigPolicy = null;
+ }
+
+ public SignaturePolicyIdentifier(
+ SignaturePolicyId signaturePolicyId)
+ {
+ if (signaturePolicyId == null)
+ throw new ArgumentNullException("signaturePolicyId");
+
+ this.sigPolicy = signaturePolicyId;
+ }
+
+ public SignaturePolicyId SignaturePolicyId
+ {
+ get { return sigPolicy; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return sigPolicy == null
+ ? DerNull.Instance
+ : sigPolicy.ToAsn1Object();
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/esf/SignerAttribute.cs b/src/core/srcbc/asn1/esf/SignerAttribute.cs
new file mode 100644
index 0000000..ddee53c
--- /dev/null
+++ b/src/core/srcbc/asn1/esf/SignerAttribute.cs
@@ -0,0 +1,96 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ public class SignerAttribute
+ : Asn1Encodable
+ {
+ private Asn1Sequence claimedAttributes;
+ private AttributeCertificate certifiedAttributes;
+
+ public static SignerAttribute GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is SignerAttribute)
+ return (SignerAttribute) obj;
+
+ if (obj is Asn1Sequence)
+ return new SignerAttribute(obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'SignerAttribute' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private SignerAttribute(
+ object obj)
+ {
+ Asn1Sequence seq = (Asn1Sequence) obj;
+ DerTaggedObject taggedObject = (DerTaggedObject) seq[0];
+ if (taggedObject.TagNo == 0)
+ {
+ claimedAttributes = Asn1Sequence.GetInstance(taggedObject, true);
+ }
+ else if (taggedObject.TagNo == 1)
+ {
+ certifiedAttributes = AttributeCertificate.GetInstance(taggedObject);
+ }
+ else
+ {
+ throw new ArgumentException("illegal tag.", "obj");
+ }
+ }
+
+ public SignerAttribute(
+ Asn1Sequence claimedAttributes)
+ {
+ this.claimedAttributes = claimedAttributes;
+ }
+
+ public SignerAttribute(
+ AttributeCertificate certifiedAttributes)
+ {
+ this.certifiedAttributes = certifiedAttributes;
+ }
+
+ public virtual Asn1Sequence ClaimedAttributes
+ {
+ get { return claimedAttributes; }
+ }
+
+ public virtual AttributeCertificate CertifiedAttributes
+ {
+ get { return certifiedAttributes; }
+ }
+
+ /**
+ *
+ *
+ * SignerAttribute ::= SEQUENCE OF CHOICE {
+ * claimedAttributes [0] ClaimedAttributes,
+ * certifiedAttributes [1] CertifiedAttributes }
+ *
+ * ClaimedAttributes ::= SEQUENCE OF Attribute
+ * CertifiedAttributes ::= AttributeCertificate -- as defined in RFC 3281: see clause 4.1.
+ *
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (claimedAttributes != null)
+ {
+ v.Add(new DerTaggedObject(0, claimedAttributes));
+ }
+ else
+ {
+ v.Add(new DerTaggedObject(1, certifiedAttributes));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/ess/ESSCertIDv2.cs b/src/core/srcbc/asn1/ess/ESSCertIDv2.cs
index bdcc6e4..d6e00cf 100644
--- a/src/core/srcbc/asn1/ess/ESSCertIDv2.cs
+++ b/src/core/srcbc/asn1/ess/ESSCertIDv2.cs
@@ -1,138 +1,138 @@
-using System;
-
-using Org.BouncyCastle.Asn1.Nist;
-using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Utilities;
-
-namespace Org.BouncyCastle.Asn1.Ess
-{
- public class EssCertIDv2
- : Asn1Encodable
- {
- private readonly AlgorithmIdentifier hashAlgorithm;
- private readonly byte[] certHash;
- private readonly IssuerSerial issuerSerial;
-
- private static readonly AlgorithmIdentifier DefaultAlgID = new AlgorithmIdentifier(
- NistObjectIdentifiers.IdSha256, DerNull.Instance);
-
- public static EssCertIDv2 GetInstance(
- object o)
- {
- if (o == null || o is EssCertIDv2)
- return (EssCertIDv2) o;
-
- if (o is Asn1Sequence)
- return new EssCertIDv2((Asn1Sequence) o);
-
- throw new ArgumentException(
- "unknown object in 'EssCertIDv2' factory : "
- + o.GetType().Name + ".");
- }
-
- private EssCertIDv2(
- Asn1Sequence seq)
- {
- if (seq.Count != 2 && seq.Count != 3)
- throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
-
- int count = 0;
-
- if (seq[0] is Asn1OctetString)
- {
- // Default value
- this.hashAlgorithm = DefaultAlgID;
- }
- else
- {
- this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[count++].ToAsn1Object());
- }
-
- this.certHash = Asn1OctetString.GetInstance(seq[count++].ToAsn1Object()).GetOctets();
-
- if (seq.Count > count)
- {
- this.issuerSerial = IssuerSerial.GetInstance(
- Asn1Sequence.GetInstance(seq[count].ToAsn1Object()));
- }
- }
-
- public EssCertIDv2(
- AlgorithmIdentifier algId,
- byte[] certHash)
- : this(algId, certHash, null)
- {
- }
-
- public EssCertIDv2(
- AlgorithmIdentifier algId,
- byte[] certHash,
- IssuerSerial issuerSerial)
- {
- if (algId == null)
- {
- // Default value
- this.hashAlgorithm = DefaultAlgID;
- }
- else
- {
- this.hashAlgorithm = algId;
- }
-
- this.certHash = certHash;
- this.issuerSerial = issuerSerial;
- }
-
- public AlgorithmIdentifier HashAlgorithm
- {
- get { return this.hashAlgorithm; }
- }
-
- public byte[] GetCertHash()
- {
- return Arrays.Clone(certHash);
- }
-
- public IssuerSerial IssuerSerial
- {
- get { return issuerSerial; }
- }
-
- /**
- *
- * EssCertIDv2 ::= SEQUENCE {
- * hashAlgorithm AlgorithmIdentifier
- * DEFAULT {algorithm id-sha256 parameters NULL},
- * certHash Hash,
- * issuerSerial IssuerSerial OPTIONAL
- * }
- *
- * Hash ::= OCTET STRING
- *
- * IssuerSerial ::= SEQUENCE {
- * issuer GeneralNames,
- * serialNumber CertificateSerialNumber
- * }
- *
- */
- public override Asn1Object ToAsn1Object()
- {
- Asn1EncodableVector v = new Asn1EncodableVector();
-
- if (!hashAlgorithm.Equals(DefaultAlgID))
- {
- v.Add(hashAlgorithm);
- }
-
- v.Add(new DerOctetString(certHash).ToAsn1Object());
-
- if (issuerSerial != null)
- {
- v.Add(issuerSerial);
- }
-
- return new DerSequence(v);
- }
-
- }
-}
+using System;
+
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+ public class EssCertIDv2
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier hashAlgorithm;
+ private readonly byte[] certHash;
+ private readonly IssuerSerial issuerSerial;
+
+ private static readonly AlgorithmIdentifier DefaultAlgID = new AlgorithmIdentifier(
+ NistObjectIdentifiers.IdSha256);
+
+ public static EssCertIDv2 GetInstance(
+ object o)
+ {
+ if (o == null || o is EssCertIDv2)
+ return (EssCertIDv2) o;
+
+ if (o is Asn1Sequence)
+ return new EssCertIDv2((Asn1Sequence) o);
+
+ throw new ArgumentException(
+ "unknown object in 'EssCertIDv2' factory : "
+ + o.GetType().Name + ".");
+ }
+
+ private EssCertIDv2(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2 && seq.Count != 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ int count = 0;
+
+ if (seq[0] is Asn1OctetString)
+ {
+ // Default value
+ this.hashAlgorithm = DefaultAlgID;
+ }
+ else
+ {
+ this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[count++].ToAsn1Object());
+ }
+
+ this.certHash = Asn1OctetString.GetInstance(seq[count++].ToAsn1Object()).GetOctets();
+
+ if (seq.Count > count)
+ {
+ this.issuerSerial = IssuerSerial.GetInstance(
+ Asn1Sequence.GetInstance(seq[count].ToAsn1Object()));
+ }
+ }
+
+ public EssCertIDv2(
+ AlgorithmIdentifier algId,
+ byte[] certHash)
+ : this(algId, certHash, null)
+ {
+ }
+
+ public EssCertIDv2(
+ AlgorithmIdentifier algId,
+ byte[] certHash,
+ IssuerSerial issuerSerial)
+ {
+ if (algId == null)
+ {
+ // Default value
+ this.hashAlgorithm = DefaultAlgID;
+ }
+ else
+ {
+ this.hashAlgorithm = algId;
+ }
+
+ this.certHash = certHash;
+ this.issuerSerial = issuerSerial;
+ }
+
+ public AlgorithmIdentifier HashAlgorithm
+ {
+ get { return this.hashAlgorithm; }
+ }
+
+ public byte[] GetCertHash()
+ {
+ return Arrays.Clone(certHash);
+ }
+
+ public IssuerSerial IssuerSerial
+ {
+ get { return issuerSerial; }
+ }
+
+ /**
+ *
+ * EssCertIDv2 ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier
+ * DEFAULT {algorithm id-sha256},
+ * certHash Hash,
+ * issuerSerial IssuerSerial OPTIONAL
+ * }
+ *
+ * Hash ::= OCTET STRING
+ *
+ * IssuerSerial ::= SEQUENCE {
+ * issuer GeneralNames,
+ * serialNumber CertificateSerialNumber
+ * }
+ *
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (!hashAlgorithm.Equals(DefaultAlgID))
+ {
+ v.Add(hashAlgorithm);
+ }
+
+ v.Add(new DerOctetString(certHash).ToAsn1Object());
+
+ if (issuerSerial != null)
+ {
+ v.Add(issuerSerial);
+ }
+
+ return new DerSequence(v);
+ }
+
+ }
+}
diff --git a/src/core/srcbc/asn1/isismtt/ocsp/RequestedCertificate.cs b/src/core/srcbc/asn1/isismtt/ocsp/RequestedCertificate.cs
index 09fd6a7..7724bfe 100644
--- a/src/core/srcbc/asn1/isismtt/ocsp/RequestedCertificate.cs
+++ b/src/core/srcbc/asn1/isismtt/ocsp/RequestedCertificate.cs
@@ -1,187 +1,186 @@
-using System;
-using System.IO;
-using Org.BouncyCastle.Asn1.X509;
-
-namespace Org.BouncyCastle.Asn1.IsisMtt.Ocsp
-{
- /**
- * ISIS-MTT-Optional: The certificate requested by the client by inserting the
- * RetrieveIfAllowed extension in the request, will be returned in this
- * extension.
- *
- * ISIS-MTT-SigG: The signature act allows publishing certificates only then,
- * when the certificate owner gives his isExplicit permission. Accordingly, there
- * may be �nondownloadable� certificates, about which the responder must provide
- * status information, but MUST NOT include them in the response. Clients may
- * get therefore the following three kind of answers on a single request
- * including the RetrieveIfAllowed extension:
- *
- * - a) the responder supports the extension and is allowed to publish the
- * certificate: RequestedCertificate returned including the requested
- * certificate
- * - b) the responder supports the extension but is NOT allowed to publish
- * the certificate: RequestedCertificate returned including an empty OCTET
- * STRING
- * - c) the responder does not support the extension: RequestedCertificate is
- * not included in the response
- *
- * Clients requesting RetrieveIfAllowed MUST be able to handle these cases. If
- * any of the OCTET STRING options is used, it MUST contain the DER encoding of
- * the requested certificate.
- *
- *
- * RequestedCertificate ::= CHOICE {
- * Certificate Certificate,
- * publicKeyCertificate [0] EXPLICIT OCTET STRING,
- * attributeCertificate [1] EXPLICIT OCTET STRING
- * }
- *
- */
- public class RequestedCertificate
- : Asn1Encodable
- //, ASN1Choice
- {
- public enum Choice
- {
- Certificate = -1,
- PublicKeyCertificate = 0,
- AttributeCertificate = 1
- }
-
- private readonly X509CertificateStructure cert;
- private readonly byte[] publicKeyCert;
- private readonly byte[] attributeCert;
-
- public static RequestedCertificate GetInstance(
- object obj)
- {
- if (obj == null || obj is RequestedCertificate)
- {
- return (RequestedCertificate) obj;
- }
-
- if (obj is Asn1Sequence)
- {
- return new RequestedCertificate(X509CertificateStructure.GetInstance(obj));
- }
-
- if (obj is Asn1TaggedObject)
- {
- return new RequestedCertificate((Asn1TaggedObject) obj);
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- public static RequestedCertificate GetInstance(
- Asn1TaggedObject obj,
- bool isExplicit)
- {
- if (!isExplicit)
- throw new ArgumentException("choice item must be explicitly tagged");
-
- return GetInstance(obj.GetObject());
- }
-
- private RequestedCertificate(
- Asn1TaggedObject tagged)
- {
- switch ((Choice) tagged.TagNo)
- {
- case Choice.AttributeCertificate:
- this.attributeCert = Asn1OctetString.GetInstance(tagged, true).GetOctets();
- break;
- case Choice.PublicKeyCertificate:
- this.publicKeyCert = Asn1OctetString.GetInstance(tagged, true).GetOctets();
- break;
- default:
- throw new ArgumentException("unknown tag number: " + tagged.TagNo);
- }
- }
-
- /**
- * Constructor from a given details.
- *
- * Only one parameter can be given. All other must be null
.
- *
- * @param certificate Given as Certificate
- */
- public RequestedCertificate(
- X509CertificateStructure certificate)
- {
- this.cert = certificate;
- }
-
- public RequestedCertificate(
- Choice type,
- byte[] certificateOctets)
- : this(new DerTaggedObject((int) type, new DerOctetString(certificateOctets)))
- {
- }
-
- public Choice Type
- {
- get
- {
- if (cert != null)
- return Choice.Certificate;
-
- if (publicKeyCert != null)
- return Choice.PublicKeyCertificate;
-
- return Choice.AttributeCertificate;
- }
- }
-
- public byte[] GetCertificateBytes()
- {
- if (cert != null)
- {
- try
- {
- return cert.GetEncoded();
- }
- catch (IOException e)
- {
- throw new InvalidOperationException("can't decode certificate: " + e);
- }
- }
-
- if (publicKeyCert != null)
- return publicKeyCert;
-
- return attributeCert;
- }
-
-
- /**
- * Produce an object suitable for an Asn1OutputStream.
- *
- * Returns:
- *
- *
- * RequestedCertificate ::= CHOICE {
- * Certificate Certificate,
- * publicKeyCertificate [0] EXPLICIT OCTET STRING,
- * attributeCertificate [1] EXPLICIT OCTET STRING
- * }
- *
- *
- * @return an Asn1Object
- */
- public override Asn1Object ToAsn1Object()
- {
- if (publicKeyCert != null)
- {
- return new DerTaggedObject(0, new DerOctetString(publicKeyCert));
- }
-
- if (attributeCert != null)
- {
- return new DerTaggedObject(1, new DerOctetString(attributeCert));
- }
-
- return cert.ToAsn1Object();
- }
- }
-}
+using System;
+using System.IO;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.Ocsp
+{
+ /**
+ * ISIS-MTT-Optional: The certificate requested by the client by inserting the
+ * RetrieveIfAllowed extension in the request, will be returned in this
+ * extension.
+ *
+ * ISIS-MTT-SigG: The signature act allows publishing certificates only then,
+ * when the certificate owner gives his isExplicit permission. Accordingly, there
+ * may be �nondownloadable� certificates, about which the responder must provide
+ * status information, but MUST NOT include them in the response. Clients may
+ * get therefore the following three kind of answers on a single request
+ * including the RetrieveIfAllowed extension:
+ *
+ * - a) the responder supports the extension and is allowed to publish the
+ * certificate: RequestedCertificate returned including the requested
+ * certificate
+ * - b) the responder supports the extension but is NOT allowed to publish
+ * the certificate: RequestedCertificate returned including an empty OCTET
+ * STRING
+ * - c) the responder does not support the extension: RequestedCertificate is
+ * not included in the response
+ *
+ * Clients requesting RetrieveIfAllowed MUST be able to handle these cases. If
+ * any of the OCTET STRING options is used, it MUST contain the DER encoding of
+ * the requested certificate.
+ *
+ *
+ * RequestedCertificate ::= CHOICE {
+ * Certificate Certificate,
+ * publicKeyCertificate [0] EXPLICIT OCTET STRING,
+ * attributeCertificate [1] EXPLICIT OCTET STRING
+ * }
+ *
+ */
+ public class RequestedCertificate
+ : Asn1Encodable, IAsn1Choice
+ {
+ public enum Choice
+ {
+ Certificate = -1,
+ PublicKeyCertificate = 0,
+ AttributeCertificate = 1
+ }
+
+ private readonly X509CertificateStructure cert;
+ private readonly byte[] publicKeyCert;
+ private readonly byte[] attributeCert;
+
+ public static RequestedCertificate GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is RequestedCertificate)
+ {
+ return (RequestedCertificate) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new RequestedCertificate(X509CertificateStructure.GetInstance(obj));
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ return new RequestedCertificate((Asn1TaggedObject) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public static RequestedCertificate GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ if (!isExplicit)
+ throw new ArgumentException("choice item must be explicitly tagged");
+
+ return GetInstance(obj.GetObject());
+ }
+
+ private RequestedCertificate(
+ Asn1TaggedObject tagged)
+ {
+ switch ((Choice) tagged.TagNo)
+ {
+ case Choice.AttributeCertificate:
+ this.attributeCert = Asn1OctetString.GetInstance(tagged, true).GetOctets();
+ break;
+ case Choice.PublicKeyCertificate:
+ this.publicKeyCert = Asn1OctetString.GetInstance(tagged, true).GetOctets();
+ break;
+ default:
+ throw new ArgumentException("unknown tag number: " + tagged.TagNo);
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * Only one parameter can be given. All other must be null
.
+ *
+ * @param certificate Given as Certificate
+ */
+ public RequestedCertificate(
+ X509CertificateStructure certificate)
+ {
+ this.cert = certificate;
+ }
+
+ public RequestedCertificate(
+ Choice type,
+ byte[] certificateOctets)
+ : this(new DerTaggedObject((int) type, new DerOctetString(certificateOctets)))
+ {
+ }
+
+ public Choice Type
+ {
+ get
+ {
+ if (cert != null)
+ return Choice.Certificate;
+
+ if (publicKeyCert != null)
+ return Choice.PublicKeyCertificate;
+
+ return Choice.AttributeCertificate;
+ }
+ }
+
+ public byte[] GetCertificateBytes()
+ {
+ if (cert != null)
+ {
+ try
+ {
+ return cert.GetEncoded();
+ }
+ catch (IOException e)
+ {
+ throw new InvalidOperationException("can't decode certificate: " + e);
+ }
+ }
+
+ if (publicKeyCert != null)
+ return publicKeyCert;
+
+ return attributeCert;
+ }
+
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * RequestedCertificate ::= CHOICE {
+ * Certificate Certificate,
+ * publicKeyCertificate [0] EXPLICIT OCTET STRING,
+ * attributeCertificate [1] EXPLICIT OCTET STRING
+ * }
+ *
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (publicKeyCert != null)
+ {
+ return new DerTaggedObject(0, new DerOctetString(publicKeyCert));
+ }
+
+ if (attributeCert != null)
+ {
+ return new DerTaggedObject(1, new DerOctetString(attributeCert));
+ }
+
+ return cert.ToAsn1Object();
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/isismtt/x509/DeclarationOfMajority.cs b/src/core/srcbc/asn1/isismtt/x509/DeclarationOfMajority.cs
index 12c2a80..dfac650 100644
--- a/src/core/srcbc/asn1/isismtt/x509/DeclarationOfMajority.cs
+++ b/src/core/srcbc/asn1/isismtt/x509/DeclarationOfMajority.cs
@@ -1,171 +1,170 @@
-using System;
-
-namespace Org.BouncyCastle.Asn1.IsisMtt.X509
-{
- /**
- * A declaration of majority.
- *
- *
- * DeclarationOfMajoritySyntax ::= CHOICE
- * {
- * notYoungerThan [0] IMPLICIT INTEGER,
- * fullAgeAtCountry [1] IMPLICIT SEQUENCE
- * {
- * fullAge BOOLEAN DEFAULT TRUE,
- * country PrintableString (SIZE(2))
- * }
- * dateOfBirth [2] IMPLICIT GeneralizedTime
- * }
- *
- *
- * fullAgeAtCountry indicates the majority of the owner with respect to the laws
- * of a specific country.
- */
- public class DeclarationOfMajority
- : Asn1Encodable
- //, ASN1Choice
- {
- public enum Choice
- {
- NotYoungerThan = 0,
- FullAgeAtCountry = 1,
- DateOfBirth = 2
- };
-
- private readonly Asn1TaggedObject declaration;
-
- public DeclarationOfMajority(
- int notYoungerThan)
- {
- declaration = new DerTaggedObject(false, 0, new DerInteger(notYoungerThan));
- }
-
- public DeclarationOfMajority(
- bool fullAge,
- string country)
- {
- if (country.Length > 2)
- throw new ArgumentException("country can only be 2 characters");
-
- DerPrintableString countryString = new DerPrintableString(country, true);
-
- DerSequence seq;
- if (fullAge)
- {
- seq = new DerSequence(countryString);
- }
- else
- {
- seq = new DerSequence(DerBoolean.False, countryString);
- }
-
- this.declaration = new DerTaggedObject(false, 1, seq);
- }
-
- public DeclarationOfMajority(
- DerGeneralizedTime dateOfBirth)
- {
- this.declaration = new DerTaggedObject(false, 2, dateOfBirth);
- }
-
- public static DeclarationOfMajority GetInstance(
- object obj)
- {
- if (obj == null || obj is DeclarationOfMajority)
- {
- return (DeclarationOfMajority) obj;
- }
-
- if (obj is Asn1TaggedObject)
- {
- return new DeclarationOfMajority((Asn1TaggedObject) obj);
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- private DeclarationOfMajority(
- Asn1TaggedObject o)
- {
- if (o.TagNo > 2)
- throw new ArgumentException("Bad tag number: " + o.TagNo);
-
- this.declaration = o;
- }
-
- /**
- * Produce an object suitable for an Asn1OutputStream.
- *
- * Returns:
- *
- *
- * DeclarationOfMajoritySyntax ::= CHOICE
- * {
- * notYoungerThan [0] IMPLICIT INTEGER,
- * fullAgeAtCountry [1] IMPLICIT SEQUENCE
- * {
- * fullAge BOOLEAN DEFAULT TRUE,
- * country PrintableString (SIZE(2))
- * }
- * dateOfBirth [2] IMPLICIT GeneralizedTime
- * }
- *
- *
- * @return an Asn1Object
- */
- public override Asn1Object ToAsn1Object()
- {
- return declaration;
- }
-
- public Choice Type
- {
- get { return (Choice) declaration.TagNo; }
- }
-
- /**
- * @return notYoungerThan if that's what we are, -1 otherwise
- */
- public virtual int NotYoungerThan
- {
- get
- {
- switch ((Choice) declaration.TagNo)
- {
- case Choice.NotYoungerThan:
- return DerInteger.GetInstance(declaration, false).Value.IntValue;
- default:
- return -1;
- }
- }
- }
-
- public virtual Asn1Sequence FullAgeAtCountry
- {
- get
- {
- switch ((Choice) declaration.TagNo)
- {
- case Choice.FullAgeAtCountry:
- return Asn1Sequence.GetInstance(declaration, false);
- default:
- return null;
- }
- }
- }
-
- public virtual DerGeneralizedTime DateOfBirth
- {
- get
- {
- switch ((Choice) declaration.TagNo)
- {
- case Choice.DateOfBirth:
- return DerGeneralizedTime.GetInstance(declaration, false);
- default:
- return null;
- }
- }
- }
- }
-}
+using System;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+ /**
+ * A declaration of majority.
+ *
+ *
+ * DeclarationOfMajoritySyntax ::= CHOICE
+ * {
+ * notYoungerThan [0] IMPLICIT INTEGER,
+ * fullAgeAtCountry [1] IMPLICIT SEQUENCE
+ * {
+ * fullAge BOOLEAN DEFAULT TRUE,
+ * country PrintableString (SIZE(2))
+ * }
+ * dateOfBirth [2] IMPLICIT GeneralizedTime
+ * }
+ *
+ *
+ * fullAgeAtCountry indicates the majority of the owner with respect to the laws
+ * of a specific country.
+ */
+ public class DeclarationOfMajority
+ : Asn1Encodable, IAsn1Choice
+ {
+ public enum Choice
+ {
+ NotYoungerThan = 0,
+ FullAgeAtCountry = 1,
+ DateOfBirth = 2
+ };
+
+ private readonly Asn1TaggedObject declaration;
+
+ public DeclarationOfMajority(
+ int notYoungerThan)
+ {
+ declaration = new DerTaggedObject(false, 0, new DerInteger(notYoungerThan));
+ }
+
+ public DeclarationOfMajority(
+ bool fullAge,
+ string country)
+ {
+ if (country.Length > 2)
+ throw new ArgumentException("country can only be 2 characters");
+
+ DerPrintableString countryString = new DerPrintableString(country, true);
+
+ DerSequence seq;
+ if (fullAge)
+ {
+ seq = new DerSequence(countryString);
+ }
+ else
+ {
+ seq = new DerSequence(DerBoolean.False, countryString);
+ }
+
+ this.declaration = new DerTaggedObject(false, 1, seq);
+ }
+
+ public DeclarationOfMajority(
+ DerGeneralizedTime dateOfBirth)
+ {
+ this.declaration = new DerTaggedObject(false, 2, dateOfBirth);
+ }
+
+ public static DeclarationOfMajority GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DeclarationOfMajority)
+ {
+ return (DeclarationOfMajority) obj;
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ return new DeclarationOfMajority((Asn1TaggedObject) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ private DeclarationOfMajority(
+ Asn1TaggedObject o)
+ {
+ if (o.TagNo > 2)
+ throw new ArgumentException("Bad tag number: " + o.TagNo);
+
+ this.declaration = o;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * DeclarationOfMajoritySyntax ::= CHOICE
+ * {
+ * notYoungerThan [0] IMPLICIT INTEGER,
+ * fullAgeAtCountry [1] IMPLICIT SEQUENCE
+ * {
+ * fullAge BOOLEAN DEFAULT TRUE,
+ * country PrintableString (SIZE(2))
+ * }
+ * dateOfBirth [2] IMPLICIT GeneralizedTime
+ * }
+ *
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return declaration;
+ }
+
+ public Choice Type
+ {
+ get { return (Choice) declaration.TagNo; }
+ }
+
+ /**
+ * @return notYoungerThan if that's what we are, -1 otherwise
+ */
+ public virtual int NotYoungerThan
+ {
+ get
+ {
+ switch ((Choice) declaration.TagNo)
+ {
+ case Choice.NotYoungerThan:
+ return DerInteger.GetInstance(declaration, false).Value.IntValue;
+ default:
+ return -1;
+ }
+ }
+ }
+
+ public virtual Asn1Sequence FullAgeAtCountry
+ {
+ get
+ {
+ switch ((Choice) declaration.TagNo)
+ {
+ case Choice.FullAgeAtCountry:
+ return Asn1Sequence.GetInstance(declaration, false);
+ default:
+ return null;
+ }
+ }
+ }
+
+ public virtual DerGeneralizedTime DateOfBirth
+ {
+ get
+ {
+ switch ((Choice) declaration.TagNo)
+ {
+ case Choice.DateOfBirth:
+ return DerGeneralizedTime.GetInstance(declaration, false);
+ default:
+ return null;
+ }
+ }
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/ocsp/CertStatus.cs b/src/core/srcbc/asn1/ocsp/CertStatus.cs
index a84198b..d5b1a94 100644
--- a/src/core/srcbc/asn1/ocsp/CertStatus.cs
+++ b/src/core/srcbc/asn1/ocsp/CertStatus.cs
@@ -1,94 +1,94 @@
-using System;
-
-using Org.BouncyCastle.Asn1;
-
-namespace Org.BouncyCastle.Asn1.Ocsp
-{
- public class CertStatus
- : Asn1Encodable
- {
- private readonly int tagNo;
- private readonly Asn1Encodable value;
-
- /**
- * create a CertStatus object with a tag of zero.
- */
- public CertStatus()
- {
- tagNo = 0;
- value = DerNull.Instance;
- }
-
- public CertStatus(
- RevokedInfo info)
- {
- tagNo = 1;
- value = info;
- }
-
- public CertStatus(
- int tagNo,
- Asn1Encodable value)
- {
- this.tagNo = tagNo;
- this.value = value;
- }
-
- 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;
- }
- }
-
- public static CertStatus GetInstance(
- object obj)
- {
- if (obj == null || obj is CertStatus)
- {
- return (CertStatus)obj;
- }
-
- if (obj is Asn1TaggedObject)
- {
- return new CertStatus((Asn1TaggedObject)obj);
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- public int TagNo
- {
- get { return tagNo; }
- }
-
- public Asn1Encodable Status
- {
- get { return value; }
- }
-
- /**
- * Produce an object suitable for an Asn1OutputStream.
- *
- * CertStatus ::= CHOICE {
- * good [0] IMPLICIT Null,
- * revoked [1] IMPLICIT RevokedInfo,
- * unknown [2] IMPLICIT UnknownInfo }
- *
- */
- public override Asn1Object ToAsn1Object()
- {
- return new DerTaggedObject(false, tagNo, value);
- }
- }
-}
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class CertStatus
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly int tagNo;
+ private readonly Asn1Encodable value;
+
+ /**
+ * create a CertStatus object with a tag of zero.
+ */
+ public CertStatus()
+ {
+ tagNo = 0;
+ value = DerNull.Instance;
+ }
+
+ public CertStatus(
+ RevokedInfo info)
+ {
+ tagNo = 1;
+ value = info;
+ }
+
+ public CertStatus(
+ int tagNo,
+ Asn1Encodable value)
+ {
+ this.tagNo = tagNo;
+ this.value = value;
+ }
+
+ 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;
+ }
+ }
+
+ public static CertStatus GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CertStatus)
+ {
+ return (CertStatus)obj;
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ return new CertStatus((Asn1TaggedObject)obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public int TagNo
+ {
+ get { return tagNo; }
+ }
+
+ public Asn1Encodable Status
+ {
+ get { return value; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * CertStatus ::= CHOICE {
+ * good [0] IMPLICIT Null,
+ * revoked [1] IMPLICIT RevokedInfo,
+ * unknown [2] IMPLICIT UnknownInfo }
+ *
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerTaggedObject(false, tagNo, value);
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/ocsp/ResponderID.cs b/src/core/srcbc/asn1/ocsp/ResponderID.cs
index 9021f31..0e2450c 100644
--- a/src/core/srcbc/asn1/ocsp/ResponderID.cs
+++ b/src/core/srcbc/asn1/ocsp/ResponderID.cs
@@ -1,77 +1,77 @@
-using System;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Asn1.X509;
-
-namespace Org.BouncyCastle.Asn1.Ocsp
-{
- public class ResponderID
- : Asn1Encodable
- {
- private readonly Asn1Encodable id;
-
- public static ResponderID GetInstance(
- object obj)
- {
- if (obj == null || obj is ResponderID)
- {
- return (ResponderID)obj;
- }
-
- if (obj is DerOctetString)
- {
- return new ResponderID((DerOctetString)obj);
- }
-
- if (obj is Asn1TaggedObject)
- {
- Asn1TaggedObject o = (Asn1TaggedObject)obj;
-
- if (o.TagNo == 1)
- {
- return new ResponderID(X509Name.GetInstance(o, true));
- }
-
- return new ResponderID(Asn1OctetString.GetInstance(o, true));
- }
-
- return new ResponderID(X509Name.GetInstance(obj));
- }
-
- public ResponderID(
- Asn1OctetString id)
- {
- if (id == null)
- throw new ArgumentNullException("id");
-
- this.id = id;
- }
-
- public ResponderID(
- X509Name id)
- {
- if (id == null)
- throw new ArgumentNullException("id");
-
- this.id = id;
- }
-
- /**
- * Produce an object suitable for an Asn1OutputStream.
- *
- * ResponderID ::= CHOICE {
- * byName [1] Name,
- * byKey [2] KeyHash }
- *
- */
- public override Asn1Object ToAsn1Object()
- {
- if (id is Asn1OctetString)
- {
- return new DerTaggedObject(true, 2, id);
- }
-
- return new DerTaggedObject(true, 1, id);
- }
- }
-}
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class ResponderID
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly Asn1Encodable id;
+
+ public static ResponderID GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is ResponderID)
+ {
+ return (ResponderID)obj;
+ }
+
+ if (obj is DerOctetString)
+ {
+ return new ResponderID((DerOctetString)obj);
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ Asn1TaggedObject o = (Asn1TaggedObject)obj;
+
+ if (o.TagNo == 1)
+ {
+ return new ResponderID(X509Name.GetInstance(o, true));
+ }
+
+ return new ResponderID(Asn1OctetString.GetInstance(o, true));
+ }
+
+ return new ResponderID(X509Name.GetInstance(obj));
+ }
+
+ public ResponderID(
+ Asn1OctetString id)
+ {
+ if (id == null)
+ throw new ArgumentNullException("id");
+
+ this.id = id;
+ }
+
+ public ResponderID(
+ X509Name id)
+ {
+ if (id == null)
+ throw new ArgumentNullException("id");
+
+ this.id = id;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * ResponderID ::= CHOICE {
+ * byName [1] Name,
+ * byKey [2] KeyHash }
+ *
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (id is Asn1OctetString)
+ {
+ return new DerTaggedObject(true, 2, id);
+ }
+
+ return new DerTaggedObject(true, 1, id);
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/ocsp/TBSRequest.cs b/src/core/srcbc/asn1/ocsp/TBSRequest.cs
index 92d7fc7..6bf75eb 100644
--- a/src/core/srcbc/asn1/ocsp/TBSRequest.cs
+++ b/src/core/srcbc/asn1/ocsp/TBSRequest.cs
@@ -1,147 +1,151 @@
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Asn1.X509;
-
-using System;
-
-namespace Org.BouncyCastle.Asn1.Ocsp
-{
- public class TbsRequest
- : Asn1Encodable
- {
- private static readonly DerInteger V1 = new DerInteger(0);
-
- private readonly DerInteger version;
- private readonly GeneralName requestorName;
- private readonly Asn1Sequence requestList;
- private readonly X509Extensions requestExtensions;
-
- public static TbsRequest GetInstance(
- Asn1TaggedObject obj,
- bool explicitly)
- {
- return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
- }
-
- public static TbsRequest GetInstance(
- object obj)
- {
- if (obj == null || obj is TbsRequest)
- {
- return (TbsRequest)obj;
- }
-
- if (obj is Asn1Sequence)
- {
- return new TbsRequest((Asn1Sequence)obj);
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- public TbsRequest(
- GeneralName requestorName,
- Asn1Sequence requestList,
- X509Extensions requestExtensions)
- {
- this.version = V1;
- this.requestorName = requestorName;
- this.requestList = requestList;
- this.requestExtensions = requestExtensions;
- }
-
- private TbsRequest(
- Asn1Sequence seq)
- {
- int index = 0;
-
- Asn1Encodable enc = seq[0];
- if (enc is Asn1TaggedObject)
- {
- Asn1TaggedObject o = (Asn1TaggedObject) enc;
-
- if (o.TagNo == 0)
- {
- version = DerInteger.GetInstance(o, true);
- index++;
- }
- else
- {
- version = V1;
- }
- }
- else
- {
- version = V1;
- }
-
- if (seq[index] is Asn1TaggedObject)
- {
- requestorName = GeneralName.GetInstance((Asn1TaggedObject) seq[index++], true);
- }
-
- requestList = (Asn1Sequence) seq[index++];
-
- if (seq.Count == (index + 1))
- {
- requestExtensions = X509Extensions.GetInstance((Asn1TaggedObject) seq[index], true);
- }
- }
-
- public DerInteger Version
- {
- get { return version; }
- }
-
- public GeneralName RequestorName
- {
- get { return requestorName; }
- }
-
- public Asn1Sequence RequestList
- {
- get { return requestList; }
- }
-
- public X509Extensions RequestExtensions
- {
- get { return requestExtensions; }
- }
-
- /**
- * Produce an object suitable for an Asn1OutputStream.
- *
- * TBSRequest ::= Sequence {
- * version [0] EXPLICIT Version DEFAULT v1,
- * requestorName [1] EXPLICIT GeneralName OPTIONAL,
- * requestList Sequence OF Request,
- * requestExtensions [2] EXPLICIT Extensions OPTIONAL }
- *
- */
- public override Asn1Object ToAsn1Object()
- {
- Asn1EncodableVector v = new Asn1EncodableVector();
-
- //
- // if default don't include.
- //
- if (!version.Equals(V1))
- {
- v.Add(new DerTaggedObject(true, 0, version));
- }
-
- if (requestorName != null)
- {
- v.Add(new DerTaggedObject(true, 1, requestorName));
- }
-
- v.Add(requestList);
-
- if (requestExtensions != null)
- {
- v.Add(new DerTaggedObject(true, 2, requestExtensions));
- }
-
- return new DerSequence(v);
- }
- }
-}
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+using System;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class TbsRequest
+ : Asn1Encodable
+ {
+ private static readonly DerInteger V1 = new DerInteger(0);
+
+ private readonly DerInteger version;
+ private readonly GeneralName requestorName;
+ private readonly Asn1Sequence requestList;
+ private readonly X509Extensions requestExtensions;
+
+ private bool versionSet;
+
+ public static TbsRequest GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static TbsRequest GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is TbsRequest)
+ {
+ return (TbsRequest)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new TbsRequest((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public TbsRequest(
+ GeneralName requestorName,
+ Asn1Sequence requestList,
+ X509Extensions requestExtensions)
+ {
+ this.version = V1;
+ this.requestorName = requestorName;
+ this.requestList = requestList;
+ this.requestExtensions = requestExtensions;
+ }
+
+ private TbsRequest(
+ Asn1Sequence seq)
+ {
+ int index = 0;
+
+ Asn1Encodable enc = seq[0];
+ if (enc is Asn1TaggedObject)
+ {
+ Asn1TaggedObject o = (Asn1TaggedObject) enc;
+
+ if (o.TagNo == 0)
+ {
+ versionSet = true;
+ version = DerInteger.GetInstance(o, true);
+ index++;
+ }
+ else
+ {
+ version = V1;
+ }
+ }
+ else
+ {
+ version = V1;
+ }
+
+ if (seq[index] is Asn1TaggedObject)
+ {
+ requestorName = GeneralName.GetInstance((Asn1TaggedObject) seq[index++], true);
+ }
+
+ requestList = (Asn1Sequence) seq[index++];
+
+ if (seq.Count == (index + 1))
+ {
+ requestExtensions = X509Extensions.GetInstance((Asn1TaggedObject) seq[index], true);
+ }
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public GeneralName RequestorName
+ {
+ get { return requestorName; }
+ }
+
+ public Asn1Sequence RequestList
+ {
+ get { return requestList; }
+ }
+
+ public X509Extensions RequestExtensions
+ {
+ get { return requestExtensions; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * TBSRequest ::= Sequence {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * requestorName [1] EXPLICIT GeneralName OPTIONAL,
+ * requestList Sequence OF Request,
+ * requestExtensions [2] EXPLICIT Extensions OPTIONAL }
+ *
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ //
+ // if default don't include - unless explicitly provided. Not strictly correct
+ // but required for some requests
+ //
+ if (!version.Equals(V1) || versionSet)
+ {
+ v.Add(new DerTaggedObject(true, 0, version));
+ }
+
+ if (requestorName != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, requestorName));
+ }
+
+ v.Add(requestList);
+
+ if (requestExtensions != null)
+ {
+ v.Add(new DerTaggedObject(true, 2, requestExtensions));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/oiw/OIWObjectIdentifiers.cs b/src/core/srcbc/asn1/oiw/OIWObjectIdentifiers.cs
index e102e91..3da2263 100644
--- a/src/core/srcbc/asn1/oiw/OIWObjectIdentifiers.cs
+++ b/src/core/srcbc/asn1/oiw/OIWObjectIdentifiers.cs
@@ -1,24 +1,29 @@
-namespace Org.BouncyCastle.Asn1.Oiw
-{
- public abstract class OiwObjectIdentifiers
- {
- public static readonly DerObjectIdentifier MD4WithRsa = new DerObjectIdentifier("1.3.14.3.2.2");
- public static readonly DerObjectIdentifier MD5WithRsa = new DerObjectIdentifier("1.3.14.3.2.3");
- public static readonly DerObjectIdentifier MD4WithRsaEncryption = new DerObjectIdentifier("1.3.14.3.2.4");
-
- public static readonly DerObjectIdentifier DesCbc = new DerObjectIdentifier("1.3.14.3.2.7");
-
- // id-SHA1 OBJECT IDENTIFIER ::=
- // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } //
- public static readonly DerObjectIdentifier IdSha1 = new DerObjectIdentifier("1.3.14.3.2.26");
-
- public static readonly DerObjectIdentifier DsaWithSha1 = new DerObjectIdentifier("1.3.14.3.2.27");
-
- public static readonly DerObjectIdentifier Sha1WithRsa = new DerObjectIdentifier("1.3.14.3.2.29");
-
- // ElGamal Algorithm OBJECT IDENTIFIER ::=
- // {iso(1) identified-organization(3) oiw(14) dirservsig(7) algorithm(2) encryption(1) 1 }
- //
- public static readonly DerObjectIdentifier ElGamalAlgorithm = new DerObjectIdentifier("1.3.14.7.2.1.1");
- }
-}
+namespace Org.BouncyCastle.Asn1.Oiw
+{
+ public abstract class OiwObjectIdentifiers
+ {
+ public static readonly DerObjectIdentifier MD4WithRsa = new DerObjectIdentifier("1.3.14.3.2.2");
+ public static readonly DerObjectIdentifier MD5WithRsa = new DerObjectIdentifier("1.3.14.3.2.3");
+ public static readonly DerObjectIdentifier MD4WithRsaEncryption = new DerObjectIdentifier("1.3.14.3.2.4");
+
+ public static readonly DerObjectIdentifier DesEcb = new DerObjectIdentifier("1.3.14.3.2.6");
+ public static readonly DerObjectIdentifier DesCbc = new DerObjectIdentifier("1.3.14.3.2.7");
+ public static readonly DerObjectIdentifier DesOfb = new DerObjectIdentifier("1.3.14.3.2.8");
+ public static readonly DerObjectIdentifier DesCfb = new DerObjectIdentifier("1.3.14.3.2.9");
+
+ public static readonly DerObjectIdentifier DesEde = new DerObjectIdentifier("1.3.14.3.2.17");
+
+ // id-SHA1 OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } //
+ public static readonly DerObjectIdentifier IdSha1 = new DerObjectIdentifier("1.3.14.3.2.26");
+
+ public static readonly DerObjectIdentifier DsaWithSha1 = new DerObjectIdentifier("1.3.14.3.2.27");
+
+ public static readonly DerObjectIdentifier Sha1WithRsa = new DerObjectIdentifier("1.3.14.3.2.29");
+
+ // ElGamal Algorithm OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) oiw(14) dirservsig(7) algorithm(2) encryption(1) 1 }
+ //
+ public static readonly DerObjectIdentifier ElGamalAlgorithm = new DerObjectIdentifier("1.3.14.7.2.1.1");
+ }
+}
diff --git a/src/core/srcbc/asn1/pkcs/PBES2Parameters.cs b/src/core/srcbc/asn1/pkcs/PBES2Parameters.cs
index 7afb266..0dc74ee 100644
--- a/src/core/srcbc/asn1/pkcs/PBES2Parameters.cs
+++ b/src/core/srcbc/asn1/pkcs/PBES2Parameters.cs
@@ -1,48 +1,61 @@
-using System;
-using System.Collections;
-
-namespace Org.BouncyCastle.Asn1.Pkcs
-{
- public class PbeS2Parameters
- : Asn1Encodable
- {
- private readonly KeyDerivationFunc func;
- private readonly EncryptionScheme scheme;
-
- public PbeS2Parameters(
- Asn1Sequence obj)
- {
- IEnumerator e = obj.GetEnumerator();
-
- e.MoveNext();
- Asn1Sequence funcSeq = (Asn1Sequence) e.Current;
-
- if (funcSeq[0].Equals(PkcsObjectIdentifiers.IdPbkdf2))
- {
- func = new KeyDerivationFunc(PkcsObjectIdentifiers.IdPbkdf2, funcSeq[1]);
- }
- else
- {
- func = new KeyDerivationFunc(funcSeq);
- }
-
- e.MoveNext();
- scheme = new EncryptionScheme((Asn1Sequence) e.Current);
- }
-
- public KeyDerivationFunc KeyDerivationFunc
- {
- get { return func; }
- }
-
- public EncryptionScheme EncryptionScheme
- {
- get { return scheme; }
- }
-
- public override Asn1Object ToAsn1Object()
- {
- return new DerSequence(func, scheme);
- }
- }
-}
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class PbeS2Parameters
+ : Asn1Encodable
+ {
+ private readonly KeyDerivationFunc func;
+ private readonly EncryptionScheme scheme;
+
+ public static PbeS2Parameters GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is PbeS2Parameters)
+ return (PbeS2Parameters) obj;
+
+ if (obj is Asn1Sequence)
+ return new PbeS2Parameters((Asn1Sequence) obj);
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ public PbeS2Parameters(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ Asn1Sequence funcSeq = (Asn1Sequence)seq[0];
+
+ // TODO Not sure if this special case is really necessary/appropriate
+ if (funcSeq[0].Equals(PkcsObjectIdentifiers.IdPbkdf2))
+ {
+ func = new KeyDerivationFunc(PkcsObjectIdentifiers.IdPbkdf2,
+ Pbkdf2Params.GetInstance(funcSeq[1]));
+ }
+ else
+ {
+ func = new KeyDerivationFunc(funcSeq);
+ }
+
+ scheme = new EncryptionScheme((Asn1Sequence) seq[1]);
+ }
+
+ public KeyDerivationFunc KeyDerivationFunc
+ {
+ get { return func; }
+ }
+
+ public EncryptionScheme EncryptionScheme
+ {
+ get { return scheme; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(func, scheme);
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/pkcs/PBKDF2Params.cs b/src/core/srcbc/asn1/pkcs/PBKDF2Params.cs
index 1e6adcf..715bf3a 100644
--- a/src/core/srcbc/asn1/pkcs/PBKDF2Params.cs
+++ b/src/core/srcbc/asn1/pkcs/PBKDF2Params.cs
@@ -1,85 +1,77 @@
-using System;
-using System.Collections;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Math;
-
-namespace Org.BouncyCastle.Asn1.Pkcs
-{
- public class Pbkdf2Params
- : Asn1Encodable
- {
- internal Asn1OctetString octStr;
- internal DerInteger iterationCount;
- internal DerInteger keyLength;
-
- public static Pbkdf2Params GetInstance(
- object obj)
- {
- if (obj is Pbkdf2Params || obj == null)
- {
- return (Pbkdf2Params) obj;
- }
-
- if (obj is Asn1Sequence)
- {
- return new Pbkdf2Params((Asn1Sequence) obj);
- }
-
- throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
- }
-
- public Pbkdf2Params(
- Asn1Sequence seq)
- {
- IEnumerator e = seq.GetEnumerator();
-
- e.MoveNext();
- octStr = (Asn1OctetString) e.Current;
-
- e.MoveNext();
- iterationCount = (DerInteger) e.Current;
-
- if (e.MoveNext())
- {
- keyLength = (DerInteger) e.Current;
- }
- }
-
- public Pbkdf2Params(
- byte[] salt,
- int iterationCount)
- {
- this.octStr = new DerOctetString(salt);
- this.iterationCount = new DerInteger(iterationCount);
- }
-
- public byte[] GetSalt()
- {
- return octStr.GetOctets();
- }
-
- public BigInteger IterationCount
- {
- get { return iterationCount.Value; }
- }
-
- public BigInteger KeyLength
- {
- get { return keyLength == null ? null : keyLength.Value; }
- }
-
- public override Asn1Object ToAsn1Object()
- {
- Asn1EncodableVector v = new Asn1EncodableVector(
- octStr, iterationCount);
-
- if (keyLength != null)
- {
- v.Add(keyLength);
- }
-
- return new DerSequence(v);
- }
- }
-}
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class Pbkdf2Params
+ : Asn1Encodable
+ {
+ private readonly Asn1OctetString octStr;
+ private readonly DerInteger iterationCount;
+ private readonly DerInteger keyLength;
+
+ public static Pbkdf2Params GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Pbkdf2Params)
+ return (Pbkdf2Params)obj;
+
+ if (obj is Asn1Sequence)
+ return new Pbkdf2Params((Asn1Sequence)obj);
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ public Pbkdf2Params(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 2 || seq.Count > 3)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ octStr = (Asn1OctetString)seq[0];
+ iterationCount = (DerInteger)seq[1];
+
+ if (seq.Count > 2)
+ {
+ keyLength = (DerInteger)seq[2];
+ }
+ }
+
+ public Pbkdf2Params(
+ byte[] salt,
+ int iterationCount)
+ {
+ this.octStr = new DerOctetString(salt);
+ this.iterationCount = new DerInteger(iterationCount);
+ }
+
+ public byte[] GetSalt()
+ {
+ return octStr.GetOctets();
+ }
+
+ public BigInteger IterationCount
+ {
+ get { return iterationCount.Value; }
+ }
+
+ public BigInteger KeyLength
+ {
+ get { return keyLength == null ? null : keyLength.Value; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ octStr, iterationCount);
+
+ if (keyLength != null)
+ {
+ v.Add(keyLength);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x500/DirectoryString.cs b/src/core/srcbc/asn1/x500/DirectoryString.cs
index d2b80e1..78ecc26 100644
--- a/src/core/srcbc/asn1/x500/DirectoryString.cs
+++ b/src/core/srcbc/asn1/x500/DirectoryString.cs
@@ -1,76 +1,75 @@
-using System;
-
-namespace Org.BouncyCastle.Asn1.X500
-{
- public class DirectoryString
- : Asn1Encodable, IAsn1String
- //, Asn1Choice
- {
- private readonly DerStringBase str;
-
- public static DirectoryString GetInstance(
- object obj)
- {
- if (obj is DirectoryString)
- {
- return (DirectoryString) obj;
- }
-
- if (obj is DerStringBase)
- {
- if (obj is DerT61String
- || obj is DerPrintableString
- || obj is DerUniversalString
- || obj is DerUtf8String
- || obj is DerBmpString)
- {
- return new DirectoryString((DerStringBase) obj);
- }
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- public static DirectoryString GetInstance(
- Asn1TaggedObject obj,
- bool isExplicit)
- {
- if (!isExplicit)
- throw new ArgumentException("choice item must be explicitly tagged");
-
- return GetInstance(obj.GetObject());
- }
-
- private DirectoryString(
- DerStringBase str)
- {
- this.str = str;
- }
-
- public DirectoryString(
- string str)
- {
- this.str = new DerUtf8String(str);
- }
-
- public string GetString()
- {
- return str.GetString();
- }
-
- /**
- *
- * DirectoryString ::= CHOICE {
- * teletexString TeletexString (SIZE (1..MAX)),
- * printableString PrintableString (SIZE (1..MAX)),
- * universalString UniversalString (SIZE (1..MAX)),
- * utf8String UTF8String (SIZE (1..MAX)),
- * bmpString BMPString (SIZE (1..MAX)) }
- *
- */
- public override Asn1Object ToAsn1Object()
- {
- return str.ToAsn1Object();
- }
- }
-}
+using System;
+
+namespace Org.BouncyCastle.Asn1.X500
+{
+ public class DirectoryString
+ : Asn1Encodable, IAsn1Choice, IAsn1String
+ {
+ private readonly DerStringBase str;
+
+ public static DirectoryString GetInstance(
+ object obj)
+ {
+ if (obj is DirectoryString)
+ {
+ return (DirectoryString) obj;
+ }
+
+ if (obj is DerStringBase)
+ {
+ if (obj is DerT61String
+ || obj is DerPrintableString
+ || obj is DerUniversalString
+ || obj is DerUtf8String
+ || obj is DerBmpString)
+ {
+ return new DirectoryString((DerStringBase) obj);
+ }
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public static DirectoryString GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ if (!isExplicit)
+ throw new ArgumentException("choice item must be explicitly tagged");
+
+ return GetInstance(obj.GetObject());
+ }
+
+ private DirectoryString(
+ DerStringBase str)
+ {
+ this.str = str;
+ }
+
+ public DirectoryString(
+ string str)
+ {
+ this.str = new DerUtf8String(str);
+ }
+
+ public string GetString()
+ {
+ return str.GetString();
+ }
+
+ /**
+ *
+ * DirectoryString ::= CHOICE {
+ * teletexString TeletexString (SIZE (1..MAX)),
+ * printableString PrintableString (SIZE (1..MAX)),
+ * universalString UniversalString (SIZE (1..MAX)),
+ * utf8String UTF8String (SIZE (1..MAX)),
+ * bmpString BMPString (SIZE (1..MAX)) }
+ *
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return str.ToAsn1Object();
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/AccessDescription.cs b/src/core/srcbc/asn1/x509/AccessDescription.cs
index 72d6568..09b5b59 100644
--- a/src/core/srcbc/asn1/x509/AccessDescription.cs
+++ b/src/core/srcbc/asn1/x509/AccessDescription.cs
@@ -1,88 +1,83 @@
-using System;
-
-namespace Org.BouncyCastle.Asn1.X509
-{
- /**
- * The AccessDescription object.
- *
- * AccessDescription ::= SEQUENCE {
- * accessMethod OBJECT IDENTIFIER,
- * accessLocation GeneralName }
- *
- */
- public class AccessDescription
- : Asn1Encodable
- {
- public readonly static DerObjectIdentifier IdADCAIssuers = new DerObjectIdentifier("1.3.6.1.5.5.7.48.2");
-
- public readonly static DerObjectIdentifier IdADOcsp = new DerObjectIdentifier("1.3.6.1.5.5.7.48.1");
-
- internal DerObjectIdentifier accessMethod;
- internal GeneralName accessLocation;
-
- public static AccessDescription GetInstance(
- object obj)
- {
- if (obj is AccessDescription)
- {
- return (AccessDescription) obj;
- }
-
- if (obj is Asn1Sequence)
- {
- return new AccessDescription((Asn1Sequence) obj);
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- private AccessDescription(
- Asn1Sequence seq)
- {
- if (seq.Count != 2)
- throw new ArgumentException("wrong number of elements in inner sequence");
-
- accessMethod = DerObjectIdentifier.GetInstance(seq[0]);
- accessLocation = GeneralName.GetInstance(seq[1]);
- }
-
- /**
- * create an AccessDescription with the oid and location provided.
- */
- public AccessDescription(
- DerObjectIdentifier oid,
- GeneralName location)
- {
- accessMethod = oid;
- accessLocation = location;
- }
-
- /**
- *
- * @return the access method.
- */
- public DerObjectIdentifier AccessMethod
- {
- get { return accessMethod; }
- }
-
- /**
- *
- * @return the access location
- */
- public GeneralName AccessLocation
- {
- get { return accessLocation; }
- }
-
- public override Asn1Object ToAsn1Object()
- {
- return new DerSequence(accessMethod, accessLocation);
- }
-
- public override string ToString()
- {
- return ("AccessDescription: Oid(" + this.accessMethod.Id + ")");
- }
- }
-}
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The AccessDescription object.
+ *
+ * AccessDescription ::= SEQUENCE {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName }
+ *
+ */
+ public class AccessDescription
+ : Asn1Encodable
+ {
+ public readonly static DerObjectIdentifier IdADCAIssuers = new DerObjectIdentifier("1.3.6.1.5.5.7.48.2");
+ public readonly static DerObjectIdentifier IdADOcsp = new DerObjectIdentifier("1.3.6.1.5.5.7.48.1");
+
+ private readonly DerObjectIdentifier accessMethod;
+ private readonly GeneralName accessLocation;
+
+ public static AccessDescription GetInstance(
+ object obj)
+ {
+ if (obj is AccessDescription)
+ return (AccessDescription) obj;
+
+ if (obj is Asn1Sequence)
+ return new AccessDescription((Asn1Sequence) obj);
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ private AccessDescription(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("wrong number of elements in sequence");
+
+ accessMethod = DerObjectIdentifier.GetInstance(seq[0]);
+ accessLocation = GeneralName.GetInstance(seq[1]);
+ }
+
+ /**
+ * create an AccessDescription with the oid and location provided.
+ */
+ public AccessDescription(
+ DerObjectIdentifier oid,
+ GeneralName location)
+ {
+ accessMethod = oid;
+ accessLocation = location;
+ }
+
+ /**
+ *
+ * @return the access method.
+ */
+ public DerObjectIdentifier AccessMethod
+ {
+ get { return accessMethod; }
+ }
+
+ /**
+ *
+ * @return the access location
+ */
+ public GeneralName AccessLocation
+ {
+ get { return accessLocation; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(accessMethod, accessLocation);
+ }
+
+ public override string ToString()
+ {
+ return "AccessDescription: Oid(" + this.accessMethod.Id + ")";
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/AttCertIssuer.cs b/src/core/srcbc/asn1/x509/AttCertIssuer.cs
index cdffe15..e9314fa 100644
--- a/src/core/srcbc/asn1/x509/AttCertIssuer.cs
+++ b/src/core/srcbc/asn1/x509/AttCertIssuer.cs
@@ -1,86 +1,86 @@
-using System;
-
-using Org.BouncyCastle.Asn1;
-
-namespace Org.BouncyCastle.Asn1.X509
-{
- public class AttCertIssuer
- : Asn1Encodable
- {
- internal readonly Asn1Encodable obj;
- internal readonly Asn1Object choiceObj;
-
- public static AttCertIssuer GetInstance(
- object obj)
- {
- if (obj is AttCertIssuer)
- {
- return (AttCertIssuer)obj;
- }
- else if (obj is V2Form)
- {
- return new AttCertIssuer(V2Form.GetInstance(obj));
- }
- else if (obj is GeneralNames)
- {
- return new AttCertIssuer((GeneralNames)obj);
- }
- else if (obj is Asn1TaggedObject)
- {
- return new AttCertIssuer(V2Form.GetInstance((Asn1TaggedObject)obj, false));
- }
- else if (obj is Asn1Sequence)
- {
- return new AttCertIssuer(GeneralNames.GetInstance(obj));
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- public static AttCertIssuer GetInstance(
- Asn1TaggedObject obj,
- bool isExplicit)
- {
- return GetInstance(obj.GetObject()); // must be explictly tagged
- }
-
- ///
- /// Don't use this one if you are trying to be RFC 3281 compliant.
- /// Use it for v1 attribute certificates only.
- ///
- /// Our GeneralNames structure
- public AttCertIssuer(
- GeneralNames names)
- {
- obj = names;
- choiceObj = obj.ToAsn1Object();
- }
-
- public AttCertIssuer(
- V2Form v2Form)
- {
- obj = v2Form;
- choiceObj = new DerTaggedObject(false, 0, obj);
- }
-
- public Asn1Encodable Issuer
- {
- get { return obj; }
- }
-
- /**
- * Produce an object suitable for an Asn1OutputStream.
- *
- * AttCertIssuer ::= CHOICE {
- * v1Form GeneralNames, -- MUST NOT be used in this
- * -- profile
- * v2Form [0] V2Form -- v2 only
- * }
- *
- */
- public override Asn1Object ToAsn1Object()
- {
- return choiceObj;
- }
- }
-}
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class AttCertIssuer
+ : Asn1Encodable, IAsn1Choice
+ {
+ internal readonly Asn1Encodable obj;
+ internal readonly Asn1Object choiceObj;
+
+ public static AttCertIssuer GetInstance(
+ object obj)
+ {
+ if (obj is AttCertIssuer)
+ {
+ return (AttCertIssuer)obj;
+ }
+ else if (obj is V2Form)
+ {
+ return new AttCertIssuer(V2Form.GetInstance(obj));
+ }
+ else if (obj is GeneralNames)
+ {
+ return new AttCertIssuer((GeneralNames)obj);
+ }
+ else if (obj is Asn1TaggedObject)
+ {
+ return new AttCertIssuer(V2Form.GetInstance((Asn1TaggedObject)obj, false));
+ }
+ else if (obj is Asn1Sequence)
+ {
+ return new AttCertIssuer(GeneralNames.GetInstance(obj));
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public static AttCertIssuer GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(obj.GetObject()); // must be explictly tagged
+ }
+
+ ///
+ /// Don't use this one if you are trying to be RFC 3281 compliant.
+ /// Use it for v1 attribute certificates only.
+ ///
+ /// Our GeneralNames structure
+ public AttCertIssuer(
+ GeneralNames names)
+ {
+ obj = names;
+ choiceObj = obj.ToAsn1Object();
+ }
+
+ public AttCertIssuer(
+ V2Form v2Form)
+ {
+ obj = v2Form;
+ choiceObj = new DerTaggedObject(false, 0, obj);
+ }
+
+ public Asn1Encodable Issuer
+ {
+ get { return obj; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * AttCertIssuer ::= CHOICE {
+ * v1Form GeneralNames, -- MUST NOT be used in this
+ * -- profile
+ * v2Form [0] V2Form -- v2 only
+ * }
+ *
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return choiceObj;
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/AuthorityInformationAccess.cs b/src/core/srcbc/asn1/x509/AuthorityInformationAccess.cs
index afbdbde..3eeba8c 100644
--- a/src/core/srcbc/asn1/x509/AuthorityInformationAccess.cs
+++ b/src/core/srcbc/asn1/x509/AuthorityInformationAccess.cs
@@ -1,87 +1,105 @@
-using System;
-using System.Collections;
-
-using Org.BouncyCastle.Asn1;
-
-namespace Org.BouncyCastle.Asn1.X509
-{
- /**
- * The AuthorityInformationAccess object.
- *
- * id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
- *
- * AuthorityInfoAccessSyntax ::=
- * Sequence SIZE (1..MAX) OF AccessDescription
- * AccessDescription ::= Sequence {
- * accessMethod OBJECT IDENTIFIER,
- * accessLocation GeneralName }
- *
- * id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
- * id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
- * id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
- *
- */
- public class AuthorityInformationAccess
- : Asn1Encodable
- {
- internal readonly DerObjectIdentifier accessMethod;
- internal readonly GeneralName accessLocation;
-
- public static AuthorityInformationAccess GetInstance(
- object obj)
- {
- if (obj is AuthorityInformationAccess)
- {
- return (AuthorityInformationAccess) obj;
- }
-
- if (obj is Asn1Sequence)
- {
- return new AuthorityInformationAccess((Asn1Sequence) obj);
- }
-
- if (obj is X509Extension)
- {
- return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- private AuthorityInformationAccess(
- Asn1Sequence seq)
- {
- foreach (DerSequence vec in seq)
- {
- if (vec.Count != 2)
- {
- throw new ArgumentException("wrong number of elements in inner sequence");
- }
-
- accessMethod = (DerObjectIdentifier) vec[0];
- accessLocation = (GeneralName) vec[1];
- }
- }
-
- /**
- * create an AuthorityInformationAccess with the oid and location provided.
- */
- public AuthorityInformationAccess(
- DerObjectIdentifier oid,
- GeneralName location)
- {
- accessMethod = oid;
- accessLocation = location;
- }
-
- public override Asn1Object ToAsn1Object()
- {
- return new DerSequence(new DerSequence(accessMethod, accessLocation));
- }
-
- public override string ToString()
- {
- return ("AuthorityInformationAccess: Oid(" + this.accessMethod.Id + ")");
- }
- }
-}
+using System;
+using System.Collections;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The AuthorityInformationAccess object.
+ *
+ * id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
+ *
+ * AuthorityInfoAccessSyntax ::=
+ * Sequence SIZE (1..MAX) OF AccessDescription
+ * AccessDescription ::= Sequence {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName }
+ *
+ * id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
+ * id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
+ * id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
+ *
+ */
+ public class AuthorityInformationAccess
+ : Asn1Encodable
+ {
+ private readonly AccessDescription[] descriptions;
+
+ public static AuthorityInformationAccess GetInstance(
+ object obj)
+ {
+ if (obj is AuthorityInformationAccess)
+ return (AuthorityInformationAccess) obj;
+
+ if (obj is Asn1Sequence)
+ return new AuthorityInformationAccess((Asn1Sequence) obj);
+
+ if (obj is X509Extension)
+ return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ private AuthorityInformationAccess(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1)
+ throw new ArgumentException("sequence may not be empty");
+
+ this.descriptions = new AccessDescription[seq.Count];
+
+ for (int i = 0; i < seq.Count; ++i)
+ {
+ descriptions[i] = AccessDescription.GetInstance(seq[i]);
+ }
+ }
+
+ /**
+ * create an AuthorityInformationAccess with the oid and location provided.
+ */
+ [Obsolete("Use version taking an AccessDescription instead")]
+ public AuthorityInformationAccess(
+ DerObjectIdentifier oid,
+ GeneralName location)
+ {
+ this.descriptions = new AccessDescription[]{ new AccessDescription(oid, location) };
+ }
+
+ public AuthorityInformationAccess(
+ AccessDescription description)
+ {
+ this.descriptions = new AccessDescription[]{ description };
+ }
+
+ public AccessDescription[] GetAccessDescriptions()
+ {
+ return (AccessDescription[]) descriptions.Clone();
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(descriptions);
+ }
+
+ public override string ToString()
+ {
+ StringBuilder buf = new StringBuilder();
+ string sep = Platform.NewLine;
+
+ buf.Append("AuthorityInformationAccess:");
+ buf.Append(sep);
+
+ foreach (AccessDescription description in descriptions)
+ {
+ buf.Append(" ");
+ buf.Append(description);
+ buf.Append(sep);
+ }
+
+ return buf.ToString();
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/DisplayText.cs b/src/core/srcbc/asn1/x509/DisplayText.cs
index 18f725f..699f390 100644
--- a/src/core/srcbc/asn1/x509/DisplayText.cs
+++ b/src/core/srcbc/asn1/x509/DisplayText.cs
@@ -1,172 +1,172 @@
-using System;
-
-namespace Org.BouncyCastle.Asn1.X509
-{
- /**
- * DisplayText
class, used in
- * CertificatePolicies
X509 V3 extensions (in policy qualifiers).
- *
- * It stores a string in a chosen encoding.
- *
- * DisplayText ::= CHOICE {
- * ia5String IA5String (SIZE (1..200)),
- * visibleString VisibleString (SIZE (1..200)),
- * bmpString BMPString (SIZE (1..200)),
- * utf8String UTF8String (SIZE (1..200)) }
- *
- * @see PolicyQualifierInfo
- * @see PolicyInformation
- */
- public class DisplayText
- : Asn1Encodable
- {
- /**
- * Constant corresponding to ia5String encoding.
- *
- */
- public const int ContentTypeIA5String = 0;
- /**
- * Constant corresponding to bmpString encoding.
- *
- */
- public const int ContentTypeBmpString = 1;
- /**
- * Constant corresponding to utf8String encoding.
- *
- */
- public const int ContentTypeUtf8String = 2;
- /**
- * Constant corresponding to visibleString encoding.
- *
- */
- public const int ContentTypeVisibleString = 3;
- /**
- * Describe constant DisplayTextMaximumSize
here.
- *
- */
- public const int DisplayTextMaximumSize = 200;
-
- internal readonly int contentType;
- internal readonly IAsn1String contents;
-
- /**
- * Creates a new DisplayText
instance.
- *
- * @param type the desired encoding type for the text.
- * @param text the text to store. Strings longer than 200
- * characters are truncated.
- */
- public DisplayText(
- int type,
- string text)
- {
- if (text.Length > DisplayTextMaximumSize)
- {
- // RFC3280 limits these strings to 200 chars
- // truncate the string
- text = text.Substring(0, DisplayTextMaximumSize);
- }
-
- contentType = type;
- switch (type)
- {
- case ContentTypeIA5String:
- contents = (IAsn1String)new DerIA5String (text);
- break;
- case ContentTypeUtf8String:
- contents = (IAsn1String)new DerUtf8String(text);
- break;
- case ContentTypeVisibleString:
- contents = (IAsn1String)new DerVisibleString(text);
- break;
- case ContentTypeBmpString:
- contents = (IAsn1String)new DerBmpString(text);
- break;
- default:
- contents = (IAsn1String)new DerUtf8String(text);
- break;
- }
- }
-
-// /**
-// * return true if the passed in string can be represented without
-// * loss as a PrintableString, false otherwise.
-// */
-// private bool CanBePrintable(
-// string str)
-// {
-// for (int i = str.Length - 1; i >= 0; i--)
-// {
-// if (str[i] > 0x007f)
-// {
-// return false;
-// }
-// }
-//
-// return true;
-// }
-
- /**
- * Creates a new DisplayText
instance.
- *
- * @param text the text to encapsulate. Strings longer than 200
- * characters are truncated.
- */
- public DisplayText(
- string text)
- {
- // by default use UTF8String
- if (text.Length > DisplayTextMaximumSize)
- {
- text = text.Substring(0, DisplayTextMaximumSize);
- }
-
- contentType = ContentTypeUtf8String;
- contents = new DerUtf8String(text);
- }
-
- /**
- * Creates a new DisplayText
instance.
- * Useful when reading back a DisplayText
class
- * from it's Asn1Encodable form.
- *
- * @param contents an Asn1Encodable
instance.
- */
- public DisplayText(
- IAsn1String contents)
- {
- this.contents = contents;
- }
-
- public static DisplayText GetInstance(
- object obj)
- {
- if (obj is IAsn1String)
- {
- return new DisplayText((IAsn1String) obj);
- }
-
- if (obj is DisplayText)
- {
- return (DisplayText) obj;
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- public override Asn1Object ToAsn1Object()
- {
- return (Asn1Object) contents;
- }
-
- /**
- * Returns the stored string
object.
- *
- * @return the stored text as a string
.
- */
- public string GetString()
- {
- return contents.GetString();
- }
- }
-}
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * DisplayText
class, used in
+ * CertificatePolicies
X509 V3 extensions (in policy qualifiers).
+ *
+ * It stores a string in a chosen encoding.
+ *
+ * DisplayText ::= CHOICE {
+ * ia5String IA5String (SIZE (1..200)),
+ * visibleString VisibleString (SIZE (1..200)),
+ * bmpString BMPString (SIZE (1..200)),
+ * utf8String UTF8String (SIZE (1..200)) }
+ *
+ * @see PolicyQualifierInfo
+ * @see PolicyInformation
+ */
+ public class DisplayText
+ : Asn1Encodable, IAsn1Choice
+ {
+ /**
+ * Constant corresponding to ia5String encoding.
+ *
+ */
+ public const int ContentTypeIA5String = 0;
+ /**
+ * Constant corresponding to bmpString encoding.
+ *
+ */
+ public const int ContentTypeBmpString = 1;
+ /**
+ * Constant corresponding to utf8String encoding.
+ *
+ */
+ public const int ContentTypeUtf8String = 2;
+ /**
+ * Constant corresponding to visibleString encoding.
+ *
+ */
+ public const int ContentTypeVisibleString = 3;
+ /**
+ * Describe constant DisplayTextMaximumSize
here.
+ *
+ */
+ public const int DisplayTextMaximumSize = 200;
+
+ internal readonly int contentType;
+ internal readonly IAsn1String contents;
+
+ /**
+ * Creates a new DisplayText
instance.
+ *
+ * @param type the desired encoding type for the text.
+ * @param text the text to store. Strings longer than 200
+ * characters are truncated.
+ */
+ public DisplayText(
+ int type,
+ string text)
+ {
+ if (text.Length > DisplayTextMaximumSize)
+ {
+ // RFC3280 limits these strings to 200 chars
+ // truncate the string
+ text = text.Substring(0, DisplayTextMaximumSize);
+ }
+
+ contentType = type;
+ switch (type)
+ {
+ case ContentTypeIA5String:
+ contents = (IAsn1String)new DerIA5String (text);
+ break;
+ case ContentTypeUtf8String:
+ contents = (IAsn1String)new DerUtf8String(text);
+ break;
+ case ContentTypeVisibleString:
+ contents = (IAsn1String)new DerVisibleString(text);
+ break;
+ case ContentTypeBmpString:
+ contents = (IAsn1String)new DerBmpString(text);
+ break;
+ default:
+ contents = (IAsn1String)new DerUtf8String(text);
+ break;
+ }
+ }
+
+// /**
+// * return true if the passed in string can be represented without
+// * loss as a PrintableString, false otherwise.
+// */
+// private bool CanBePrintable(
+// string str)
+// {
+// for (int i = str.Length - 1; i >= 0; i--)
+// {
+// if (str[i] > 0x007f)
+// {
+// return false;
+// }
+// }
+//
+// return true;
+// }
+
+ /**
+ * Creates a new DisplayText
instance.
+ *
+ * @param text the text to encapsulate. Strings longer than 200
+ * characters are truncated.
+ */
+ public DisplayText(
+ string text)
+ {
+ // by default use UTF8String
+ if (text.Length > DisplayTextMaximumSize)
+ {
+ text = text.Substring(0, DisplayTextMaximumSize);
+ }
+
+ contentType = ContentTypeUtf8String;
+ contents = new DerUtf8String(text);
+ }
+
+ /**
+ * Creates a new DisplayText
instance.
+ * Useful when reading back a DisplayText
class
+ * from it's Asn1Encodable form.
+ *
+ * @param contents an Asn1Encodable
instance.
+ */
+ public DisplayText(
+ IAsn1String contents)
+ {
+ this.contents = contents;
+ }
+
+ public static DisplayText GetInstance(
+ object obj)
+ {
+ if (obj is IAsn1String)
+ {
+ return new DisplayText((IAsn1String) obj);
+ }
+
+ if (obj is DisplayText)
+ {
+ return (DisplayText) obj;
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return (Asn1Object) contents;
+ }
+
+ /**
+ * Returns the stored string
object.
+ *
+ * @return the stored text as a string
.
+ */
+ public string GetString()
+ {
+ return contents.GetString();
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/DistributionPointName.cs b/src/core/srcbc/asn1/x509/DistributionPointName.cs
index 8a4d40e..dfa30dc 100644
--- a/src/core/srcbc/asn1/x509/DistributionPointName.cs
+++ b/src/core/srcbc/asn1/x509/DistributionPointName.cs
@@ -1,130 +1,130 @@
-using System;
-using System.Text;
-
-using Org.BouncyCastle.Utilities;
-
-namespace Org.BouncyCastle.Asn1.X509
-{
- /**
- * The DistributionPointName object.
- *
- * DistributionPointName ::= CHOICE {
- * fullName [0] GeneralNames,
- * nameRelativeToCRLIssuer [1] RelativeDistinguishedName
- * }
- *
- */
- public class DistributionPointName
- : Asn1Encodable
- {
- internal readonly Asn1Encodable name;
- internal readonly int type;
-
- public const int FullName = 0;
- public const int NameRelativeToCrlIssuer = 1;
-
- public static DistributionPointName GetInstance(
- Asn1TaggedObject obj,
- bool explicitly)
- {
- return GetInstance(Asn1TaggedObject.GetInstance(obj, explicitly));
- }
-
- public static DistributionPointName GetInstance(
- object obj)
- {
- if (obj == null || obj is DistributionPointName)
- {
- return (DistributionPointName) obj;
- }
-
- if (obj is Asn1TaggedObject)
- {
- return new DistributionPointName((Asn1TaggedObject) obj);
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- public DistributionPointName(
- int type,
- Asn1Encodable name)
- {
- this.type = type;
- this.name = name;
- }
-
- public DistributionPointName(
- GeneralNames name)
- : this(FullName, name)
- {
- }
-
- public int PointType
- {
- get { return type; }
- }
-
- public Asn1Encodable Name
- {
- get { return name; }
- }
-
- public DistributionPointName(
- Asn1TaggedObject obj)
- {
- this.type = obj.TagNo;
-
- if (type == FullName)
- {
- this.name = GeneralNames.GetInstance(obj, false);
- }
- else
- {
- this.name = Asn1Set.GetInstance(obj, false);
- }
- }
-
- public override Asn1Object ToAsn1Object()
- {
- return new DerTaggedObject(false, type, name);
- }
-
- public override string ToString()
- {
- string sep = Platform.NewLine;
- StringBuilder buf = new StringBuilder();
- buf.Append("DistributionPointName: [");
- buf.Append(sep);
- if (type == FullName)
- {
- appendObject(buf, sep, "fullName", name.ToString());
- }
- else
- {
- appendObject(buf, sep, "nameRelativeToCRLIssuer", name.ToString());
- }
- buf.Append("]");
- buf.Append(sep);
- return buf.ToString();
- }
-
- private void appendObject(
- StringBuilder buf,
- string sep,
- string name,
- string val)
- {
- string indent = " ";
-
- buf.Append(indent);
- buf.Append(name);
- buf.Append(":");
- buf.Append(sep);
- buf.Append(indent);
- buf.Append(indent);
- buf.Append(val);
- buf.Append(sep);
- }
- }
-}
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The DistributionPointName object.
+ *
+ * DistributionPointName ::= CHOICE {
+ * fullName [0] GeneralNames,
+ * nameRelativeToCRLIssuer [1] RelativeDistinguishedName
+ * }
+ *
+ */
+ public class DistributionPointName
+ : Asn1Encodable, IAsn1Choice
+ {
+ internal readonly Asn1Encodable name;
+ internal readonly int type;
+
+ public const int FullName = 0;
+ public const int NameRelativeToCrlIssuer = 1;
+
+ public static DistributionPointName GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1TaggedObject.GetInstance(obj, true));
+ }
+
+ public static DistributionPointName GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DistributionPointName)
+ {
+ return (DistributionPointName) obj;
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ return new DistributionPointName((Asn1TaggedObject) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public DistributionPointName(
+ int type,
+ Asn1Encodable name)
+ {
+ this.type = type;
+ this.name = name;
+ }
+
+ public DistributionPointName(
+ GeneralNames name)
+ : this(FullName, name)
+ {
+ }
+
+ public int PointType
+ {
+ get { return type; }
+ }
+
+ public Asn1Encodable Name
+ {
+ get { return name; }
+ }
+
+ public DistributionPointName(
+ Asn1TaggedObject obj)
+ {
+ this.type = obj.TagNo;
+
+ if (type == FullName)
+ {
+ this.name = GeneralNames.GetInstance(obj, false);
+ }
+ else
+ {
+ this.name = Asn1Set.GetInstance(obj, false);
+ }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerTaggedObject(false, type, name);
+ }
+
+ public override string ToString()
+ {
+ string sep = Platform.NewLine;
+ StringBuilder buf = new StringBuilder();
+ buf.Append("DistributionPointName: [");
+ buf.Append(sep);
+ if (type == FullName)
+ {
+ appendObject(buf, sep, "fullName", name.ToString());
+ }
+ else
+ {
+ appendObject(buf, sep, "nameRelativeToCRLIssuer", name.ToString());
+ }
+ buf.Append("]");
+ buf.Append(sep);
+ return buf.ToString();
+ }
+
+ private void appendObject(
+ StringBuilder buf,
+ string sep,
+ string name,
+ string val)
+ {
+ string indent = " ";
+
+ buf.Append(indent);
+ buf.Append(name);
+ buf.Append(":");
+ buf.Append(sep);
+ buf.Append(indent);
+ buf.Append(indent);
+ buf.Append(val);
+ buf.Append(sep);
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/GeneralName.cs b/src/core/srcbc/asn1/x509/GeneralName.cs
index d0134b5..9188721 100644
--- a/src/core/srcbc/asn1/x509/GeneralName.cs
+++ b/src/core/srcbc/asn1/x509/GeneralName.cs
@@ -1,406 +1,406 @@
-using System;
-using System.Collections;
-using System.Globalization;
-using System.Text;
-
-using NetUtils = Org.BouncyCastle.Utilities.Net;
-
-namespace Org.BouncyCastle.Asn1.X509
-{
- /**
- * The GeneralName object.
- *
- * GeneralName ::= CHOICE {
- * otherName [0] OtherName,
- * rfc822Name [1] IA5String,
- * dNSName [2] IA5String,
- * x400Address [3] ORAddress,
- * directoryName [4] Name,
- * ediPartyName [5] EDIPartyName,
- * uniformResourceIdentifier [6] IA5String,
- * iPAddress [7] OCTET STRING,
- * registeredID [8] OBJECT IDENTIFIER}
- *
- * OtherName ::= Sequence {
- * type-id OBJECT IDENTIFIER,
- * value [0] EXPLICIT ANY DEFINED BY type-id }
- *
- * EDIPartyName ::= Sequence {
- * nameAssigner [0] DirectoryString OPTIONAL,
- * partyName [1] DirectoryString }
- *
- */
- public class GeneralName
- : Asn1Encodable
- {
- public const int OtherName = 0;
- public const int Rfc822Name = 1;
- public const int DnsName = 2;
- public const int X400Address = 3;
- public const int DirectoryName = 4;
- public const int EdiPartyName = 5;
- public const int UniformResourceIdentifier = 6;
- public const int IPAddress = 7;
- public const int RegisteredID = 8;
-
- internal readonly Asn1Encodable obj;
- internal readonly int tag;
-
- public GeneralName(
- X509Name directoryName)
- {
- this.obj = directoryName;
- this.tag = 4;
- }
-
- /**
- * When the subjectAltName extension contains an Internet mail address,
- * the address MUST be included as an rfc822Name. The format of an
- * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
- *
- * When the subjectAltName extension contains a domain name service
- * label, the domain name MUST be stored in the dNSName (an IA5String).
- * The name MUST be in the "preferred name syntax," as specified by RFC
- * 1034 [RFC 1034].
- *
- * When the subjectAltName extension contains a URI, the name MUST be
- * stored in the uniformResourceIdentifier (an IA5String). The name MUST
- * be a non-relative URL, and MUST follow the URL syntax and encoding
- * rules specified in [RFC 1738]. The name must include both a scheme
- * (e.g., "http" or "ftp") and a scheme-specific-part. The scheme-
- * specific-part must include a fully qualified domain name or IP
- * address as the host.
- *
- * When the subjectAltName extension contains a iPAddress, the address
- * MUST be stored in the octet string in "network byte order," as
- * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
- * each octet is the LSB of the corresponding byte in the network
- * address. For IP Version 4, as specified in RFC 791, the octet string
- * MUST contain exactly four octets. For IP Version 6, as specified in
- * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
- * 1883].
- */
- public GeneralName(
- Asn1Object name,
- int tag)
- {
- this.obj = name;
- this.tag = tag;
- }
-
- public GeneralName(
- int tag,
- Asn1Encodable name)
- {
- this.obj = name;
- this.tag = tag;
- }
-
- /**
- * Create a GeneralName for the given tag from the passed in string.
- *
- * This constructor can handle:
- *
- * - rfc822Name
- * - iPAddress
- * - directoryName
- * - dNSName
- * - uniformResourceIdentifier
- * - registeredID
- *
- * For x400Address, otherName and ediPartyName there is no common string
- * format defined.
- *
- * Note: A directory name can be encoded in different ways into a byte
- * representation. Be aware of this if the byte representation is used for
- * comparing results.
- *
- *
- * @param tag tag number
- * @param name string representation of name
- * @throws ArgumentException if the string encoding is not correct or
- * not supported.
- */
- public GeneralName(
- int tag,
- string name)
- {
- this.tag = tag;
-
- if (tag == Rfc822Name || tag == DnsName || tag == UniformResourceIdentifier)
- {
- this.obj = new DerIA5String(name);
- }
- else if (tag == RegisteredID)
- {
- this.obj = new DerObjectIdentifier(name);
- }
- else if (tag == DirectoryName)
- {
- this.obj = new X509Name(name);
- }
- else if (tag == IPAddress)
- {
- byte[] enc = toGeneralNameEncoding(name);
- if (enc == null)
- throw new ArgumentException("IP Address is invalid", "name");
-
- this.obj = new DerOctetString(enc);
- }
- else
- {
- throw new ArgumentException("can't process string for tag: " + tag, "tag");
- }
- }
-
- public static GeneralName GetInstance(
- object obj)
- {
- if (obj == null || obj is GeneralName)
- {
- return (GeneralName) obj;
- }
-
- if (obj is Asn1TaggedObject)
- {
- Asn1TaggedObject tagObj = (Asn1TaggedObject) obj;
- int tag = tagObj.TagNo;
-
- switch (tag)
- {
- case OtherName:
- return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, false));
- case Rfc822Name:
- return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
- case DnsName:
- return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
- case X400Address:
- throw new ArgumentException("unknown tag: " + tag);
- case DirectoryName:
- return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, true));
- case EdiPartyName:
- return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, false));
- case UniformResourceIdentifier:
- return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
- case IPAddress:
- return new GeneralName(tag, Asn1OctetString.GetInstance(tagObj, false));
- case RegisteredID:
- return new GeneralName(tag, DerObjectIdentifier.GetInstance(tagObj, false));
- }
-
- }
-
- throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
- }
-
- public static GeneralName GetInstance(
- Asn1TaggedObject tagObj,
- bool explicitly)
- {
- return GetInstance(Asn1TaggedObject.GetInstance(tagObj, explicitly));
- }
-
- public int TagNo
- {
- get { return tag; }
- }
-
- public Asn1Encodable Name
- {
- get { return obj; }
- }
-
- public override string ToString()
- {
- StringBuilder buf = new StringBuilder();
- buf.Append(tag);
- buf.Append(": ");
-
- switch (tag)
- {
- case Rfc822Name:
- case DnsName:
- case UniformResourceIdentifier:
- buf.Append(DerIA5String.GetInstance(obj).GetString());
- break;
- case DirectoryName:
- buf.Append(X509Name.GetInstance(obj).ToString());
- break;
- default:
- buf.Append(obj.ToString());
- break;
- }
-
- return buf.ToString();
- }
-
- private byte[] toGeneralNameEncoding(
- string ip)
- {
- if (NetUtils.IPAddress.IsValidIPv6WithNetmask(ip) || NetUtils.IPAddress.IsValidIPv6(ip))
- {
- int slashIndex = ip.IndexOf('/');
-
- if (slashIndex < 0)
- {
- byte[] addr = new byte[16];
- int[] parsedIp = parseIPv6(ip);
- copyInts(parsedIp, addr, 0);
-
- return addr;
- }
- else
- {
- byte[] addr = new byte[32];
- int[] parsedIp = parseIPv6(ip.Substring(0, slashIndex));
- copyInts(parsedIp, addr, 0);
- string mask = ip.Substring(slashIndex + 1);
- if (mask.IndexOf(':') > 0)
- {
- parsedIp = parseIPv6(mask);
- }
- else
- {
- parsedIp = parseMask(mask);
- }
- copyInts(parsedIp, addr, 16);
-
- return addr;
- }
- }
- else if (NetUtils.IPAddress.IsValidIPv4WithNetmask(ip) || NetUtils.IPAddress.IsValidIPv4(ip))
- {
- int slashIndex = ip.IndexOf('/');
-
- if (slashIndex < 0)
- {
- byte[] addr = new byte[4];
-
- parseIPv4(ip, addr, 0);
-
- return addr;
- }
- else
- {
- byte[] addr = new byte[8];
-
- parseIPv4(ip.Substring(0, slashIndex), addr, 0);
-
- string mask = ip.Substring(slashIndex + 1);
- if (mask.IndexOf('.') > 0)
- {
- parseIPv4(mask, addr, 4);
- }
- else
- {
- parseIPv4Mask(mask, addr, 4);
- }
-
- return addr;
- }
- }
-
- return null;
- }
-
- private void parseIPv4Mask(string mask, byte[] addr, int offset)
- {
- int maskVal = Int32.Parse(mask);
-
- for (int i = 0; i != maskVal; i++)
- {
- addr[(i / 8) + offset] |= (byte)(1 << (i % 8));
- }
- }
-
- private void parseIPv4(string ip, byte[] addr, int offset)
- {
- foreach (string token in ip.Split('.', '/'))
- {
- addr[offset++] = (byte)Int32.Parse(token);
- }
- }
-
- private int[] parseMask(string mask)
- {
- int[] res = new int[8];
- int maskVal = Int32.Parse(mask);
-
- for (int i = 0; i != maskVal; i++)
- {
- res[i / 16] |= 1 << (i % 16);
- }
- return res;
- }
-
- private void copyInts(int[] parsedIp, byte[] addr, int offSet)
- {
- for (int i = 0; i != parsedIp.Length; i++)
- {
- addr[(i * 2) + offSet] = (byte)(parsedIp[i] >> 8);
- addr[(i * 2 + 1) + offSet] = (byte)parsedIp[i];
- }
- }
-
- private int[] parseIPv6(string ip)
- {
- if (ip.StartsWith("::"))
- {
- ip = ip.Substring(1);
- }
- else if (ip.EndsWith("::"))
- {
- ip = ip.Substring(0, ip.Length - 1);
- }
-
- IEnumerator sEnum = ip.Split(':').GetEnumerator();
-
- int index = 0;
- int[] val = new int[8];
-
- int doubleColon = -1;
-
- while (sEnum.MoveNext())
- {
- string e = (string) sEnum.Current;
-
- if (e.Length == 0)
- {
- doubleColon = index;
- val[index++] = 0;
- }
- else
- {
- if (e.IndexOf('.') < 0)
- {
- val[index++] = Int32.Parse(e, NumberStyles.AllowHexSpecifier);
- }
- else
- {
- string[] tokens = e.Split('.');
-
- val[index++] = (Int32.Parse(tokens[0]) << 8) | Int32.Parse(tokens[1]);
- val[index++] = (Int32.Parse(tokens[2]) << 8) | Int32.Parse(tokens[3]);
- }
- }
- }
-
- if (index != val.Length)
- {
- Array.Copy(val, doubleColon, val, val.Length - (index - doubleColon), index - doubleColon);
- for (int i = doubleColon; i != val.Length - (index - doubleColon); i++)
- {
- val[i] = 0;
- }
- }
-
- return val;
- }
-
- public override Asn1Object ToAsn1Object()
- {
- // Explicitly tagged if DirectoryName
- return new DerTaggedObject(tag == DirectoryName, tag, obj);
- }
- }
-}
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Text;
+
+using NetUtils = Org.BouncyCastle.Utilities.Net;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The GeneralName object.
+ *
+ * GeneralName ::= CHOICE {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER}
+ *
+ * OtherName ::= Sequence {
+ * type-id OBJECT IDENTIFIER,
+ * value [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * EDIPartyName ::= Sequence {
+ * nameAssigner [0] DirectoryString OPTIONAL,
+ * partyName [1] DirectoryString }
+ *
+ */
+ public class GeneralName
+ : Asn1Encodable, IAsn1Choice
+ {
+ public const int OtherName = 0;
+ public const int Rfc822Name = 1;
+ public const int DnsName = 2;
+ public const int X400Address = 3;
+ public const int DirectoryName = 4;
+ public const int EdiPartyName = 5;
+ public const int UniformResourceIdentifier = 6;
+ public const int IPAddress = 7;
+ public const int RegisteredID = 8;
+
+ internal readonly Asn1Encodable obj;
+ internal readonly int tag;
+
+ public GeneralName(
+ X509Name directoryName)
+ {
+ this.obj = directoryName;
+ this.tag = 4;
+ }
+
+ /**
+ * When the subjectAltName extension contains an Internet mail address,
+ * the address MUST be included as an rfc822Name. The format of an
+ * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
+ *
+ * When the subjectAltName extension contains a domain name service
+ * label, the domain name MUST be stored in the dNSName (an IA5String).
+ * The name MUST be in the "preferred name syntax," as specified by RFC
+ * 1034 [RFC 1034].
+ *
+ * When the subjectAltName extension contains a URI, the name MUST be
+ * stored in the uniformResourceIdentifier (an IA5String). The name MUST
+ * be a non-relative URL, and MUST follow the URL syntax and encoding
+ * rules specified in [RFC 1738]. The name must include both a scheme
+ * (e.g., "http" or "ftp") and a scheme-specific-part. The scheme-
+ * specific-part must include a fully qualified domain name or IP
+ * address as the host.
+ *
+ * When the subjectAltName extension contains a iPAddress, the address
+ * MUST be stored in the octet string in "network byte order," as
+ * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
+ * each octet is the LSB of the corresponding byte in the network
+ * address. For IP Version 4, as specified in RFC 791, the octet string
+ * MUST contain exactly four octets. For IP Version 6, as specified in
+ * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
+ * 1883].
+ */
+ public GeneralName(
+ Asn1Object name,
+ int tag)
+ {
+ this.obj = name;
+ this.tag = tag;
+ }
+
+ public GeneralName(
+ int tag,
+ Asn1Encodable name)
+ {
+ this.obj = name;
+ this.tag = tag;
+ }
+
+ /**
+ * Create a GeneralName for the given tag from the passed in string.
+ *
+ * This constructor can handle:
+ *
+ * - rfc822Name
+ * - iPAddress
+ * - directoryName
+ * - dNSName
+ * - uniformResourceIdentifier
+ * - registeredID
+ *
+ * For x400Address, otherName and ediPartyName there is no common string
+ * format defined.
+ *
+ * Note: A directory name can be encoded in different ways into a byte
+ * representation. Be aware of this if the byte representation is used for
+ * comparing results.
+ *
+ *
+ * @param tag tag number
+ * @param name string representation of name
+ * @throws ArgumentException if the string encoding is not correct or
+ * not supported.
+ */
+ public GeneralName(
+ int tag,
+ string name)
+ {
+ this.tag = tag;
+
+ if (tag == Rfc822Name || tag == DnsName || tag == UniformResourceIdentifier)
+ {
+ this.obj = new DerIA5String(name);
+ }
+ else if (tag == RegisteredID)
+ {
+ this.obj = new DerObjectIdentifier(name);
+ }
+ else if (tag == DirectoryName)
+ {
+ this.obj = new X509Name(name);
+ }
+ else if (tag == IPAddress)
+ {
+ byte[] enc = toGeneralNameEncoding(name);
+ if (enc == null)
+ throw new ArgumentException("IP Address is invalid", "name");
+
+ this.obj = new DerOctetString(enc);
+ }
+ else
+ {
+ throw new ArgumentException("can't process string for tag: " + tag, "tag");
+ }
+ }
+
+ public static GeneralName GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is GeneralName)
+ {
+ return (GeneralName) obj;
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tagObj = (Asn1TaggedObject) obj;
+ int tag = tagObj.TagNo;
+
+ switch (tag)
+ {
+ case OtherName:
+ return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, false));
+ case Rfc822Name:
+ return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
+ case DnsName:
+ return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
+ case X400Address:
+ throw new ArgumentException("unknown tag: " + tag);
+ case DirectoryName:
+ return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, true));
+ case EdiPartyName:
+ return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, false));
+ case UniformResourceIdentifier:
+ return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
+ case IPAddress:
+ return new GeneralName(tag, Asn1OctetString.GetInstance(tagObj, false));
+ case RegisteredID:
+ return new GeneralName(tag, DerObjectIdentifier.GetInstance(tagObj, false));
+ }
+
+ }
+
+ throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ public static GeneralName GetInstance(
+ Asn1TaggedObject tagObj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1TaggedObject.GetInstance(tagObj, true));
+ }
+
+ public int TagNo
+ {
+ get { return tag; }
+ }
+
+ public Asn1Encodable Name
+ {
+ get { return obj; }
+ }
+
+ public override string ToString()
+ {
+ StringBuilder buf = new StringBuilder();
+ buf.Append(tag);
+ buf.Append(": ");
+
+ switch (tag)
+ {
+ case Rfc822Name:
+ case DnsName:
+ case UniformResourceIdentifier:
+ buf.Append(DerIA5String.GetInstance(obj).GetString());
+ break;
+ case DirectoryName:
+ buf.Append(X509Name.GetInstance(obj).ToString());
+ break;
+ default:
+ buf.Append(obj.ToString());
+ break;
+ }
+
+ return buf.ToString();
+ }
+
+ private byte[] toGeneralNameEncoding(
+ string ip)
+ {
+ if (NetUtils.IPAddress.IsValidIPv6WithNetmask(ip) || NetUtils.IPAddress.IsValidIPv6(ip))
+ {
+ int slashIndex = ip.IndexOf('/');
+
+ if (slashIndex < 0)
+ {
+ byte[] addr = new byte[16];
+ int[] parsedIp = parseIPv6(ip);
+ copyInts(parsedIp, addr, 0);
+
+ return addr;
+ }
+ else
+ {
+ byte[] addr = new byte[32];
+ int[] parsedIp = parseIPv6(ip.Substring(0, slashIndex));
+ copyInts(parsedIp, addr, 0);
+ string mask = ip.Substring(slashIndex + 1);
+ if (mask.IndexOf(':') > 0)
+ {
+ parsedIp = parseIPv6(mask);
+ }
+ else
+ {
+ parsedIp = parseMask(mask);
+ }
+ copyInts(parsedIp, addr, 16);
+
+ return addr;
+ }
+ }
+ else if (NetUtils.IPAddress.IsValidIPv4WithNetmask(ip) || NetUtils.IPAddress.IsValidIPv4(ip))
+ {
+ int slashIndex = ip.IndexOf('/');
+
+ if (slashIndex < 0)
+ {
+ byte[] addr = new byte[4];
+
+ parseIPv4(ip, addr, 0);
+
+ return addr;
+ }
+ else
+ {
+ byte[] addr = new byte[8];
+
+ parseIPv4(ip.Substring(0, slashIndex), addr, 0);
+
+ string mask = ip.Substring(slashIndex + 1);
+ if (mask.IndexOf('.') > 0)
+ {
+ parseIPv4(mask, addr, 4);
+ }
+ else
+ {
+ parseIPv4Mask(mask, addr, 4);
+ }
+
+ return addr;
+ }
+ }
+
+ return null;
+ }
+
+ private void parseIPv4Mask(string mask, byte[] addr, int offset)
+ {
+ int maskVal = Int32.Parse(mask);
+
+ for (int i = 0; i != maskVal; i++)
+ {
+ addr[(i / 8) + offset] |= (byte)(1 << (i % 8));
+ }
+ }
+
+ private void parseIPv4(string ip, byte[] addr, int offset)
+ {
+ foreach (string token in ip.Split('.', '/'))
+ {
+ addr[offset++] = (byte)Int32.Parse(token);
+ }
+ }
+
+ private int[] parseMask(string mask)
+ {
+ int[] res = new int[8];
+ int maskVal = Int32.Parse(mask);
+
+ for (int i = 0; i != maskVal; i++)
+ {
+ res[i / 16] |= 1 << (i % 16);
+ }
+ return res;
+ }
+
+ private void copyInts(int[] parsedIp, byte[] addr, int offSet)
+ {
+ for (int i = 0; i != parsedIp.Length; i++)
+ {
+ addr[(i * 2) + offSet] = (byte)(parsedIp[i] >> 8);
+ addr[(i * 2 + 1) + offSet] = (byte)parsedIp[i];
+ }
+ }
+
+ private int[] parseIPv6(string ip)
+ {
+ if (ip.StartsWith("::"))
+ {
+ ip = ip.Substring(1);
+ }
+ else if (ip.EndsWith("::"))
+ {
+ ip = ip.Substring(0, ip.Length - 1);
+ }
+
+ IEnumerator sEnum = ip.Split(':').GetEnumerator();
+
+ int index = 0;
+ int[] val = new int[8];
+
+ int doubleColon = -1;
+
+ while (sEnum.MoveNext())
+ {
+ string e = (string) sEnum.Current;
+
+ if (e.Length == 0)
+ {
+ doubleColon = index;
+ val[index++] = 0;
+ }
+ else
+ {
+ if (e.IndexOf('.') < 0)
+ {
+ val[index++] = Int32.Parse(e, NumberStyles.AllowHexSpecifier);
+ }
+ else
+ {
+ string[] tokens = e.Split('.');
+
+ val[index++] = (Int32.Parse(tokens[0]) << 8) | Int32.Parse(tokens[1]);
+ val[index++] = (Int32.Parse(tokens[2]) << 8) | Int32.Parse(tokens[3]);
+ }
+ }
+ }
+
+ if (index != val.Length)
+ {
+ Array.Copy(val, doubleColon, val, val.Length - (index - doubleColon), index - doubleColon);
+ for (int i = doubleColon; i != val.Length - (index - doubleColon); i++)
+ {
+ val[i] = 0;
+ }
+ }
+
+ return val;
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ // Explicitly tagged if DirectoryName
+ return new DerTaggedObject(tag == DirectoryName, tag, obj);
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/GeneralNames.cs b/src/core/srcbc/asn1/x509/GeneralNames.cs
index acf8a27..8837b97 100644
--- a/src/core/srcbc/asn1/x509/GeneralNames.cs
+++ b/src/core/srcbc/asn1/x509/GeneralNames.cs
@@ -1,91 +1,89 @@
-using System;
-using System.Text;
-
-using Org.BouncyCastle.Utilities;
-
-namespace Org.BouncyCastle.Asn1.X509
-{
- public class GeneralNames
- : Asn1Encodable
- {
- private readonly Asn1Sequence seq;
-
- public static GeneralNames GetInstance(
- object obj)
- {
- if (obj == null || obj is GeneralNames)
- {
- return (GeneralNames) obj;
- }
-
- if (obj is Asn1Sequence)
- {
- return new GeneralNames((Asn1Sequence) obj);
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- public static GeneralNames GetInstance(
- Asn1TaggedObject obj,
- bool explicitly)
- {
- return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
- }
-
- /// Construct a GeneralNames object containing one GeneralName.
- /// The name to be contained.
- public GeneralNames(
- GeneralName name)
- {
- this.seq = new DerSequence(name);
- }
-
- private GeneralNames(
- Asn1Sequence seq)
- {
- this.seq = seq;
- }
-
- public GeneralName[] GetNames()
- {
- GeneralName[] names = new GeneralName[seq.Count];
-
- for (int i = 0; i != seq.Count; i++)
- {
- names[i] = GeneralName.GetInstance(seq[i]);
- }
-
- return names;
- }
-
- /**
- * Produce an object suitable for an Asn1OutputStream.
- *
- * GeneralNames ::= Sequence SIZE {1..MAX} OF GeneralName
- *
- */
- public override Asn1Object ToAsn1Object()
- {
- return seq;
- }
-
- public override string ToString()
- {
- StringBuilder buf = new StringBuilder();
- string sep = Platform.NewLine;
- GeneralName[] names = GetNames();
-
- buf.Append("GeneralNames:");
- buf.Append(sep);
-
- for (int i = 0; i != names.Length; i++)
- {
- buf.Append(" ");
- buf.Append(names[i]);
- buf.Append(sep);
- }
- return buf.ToString();
- }
- }
-}
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class GeneralNames
+ : Asn1Encodable
+ {
+ private readonly GeneralName[] names;
+
+ public static GeneralNames GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is GeneralNames)
+ {
+ return (GeneralNames) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new GeneralNames((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public static GeneralNames GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ /// Construct a GeneralNames object containing one GeneralName.
+ /// The name to be contained.
+ public GeneralNames(
+ GeneralName name)
+ {
+ names = new GeneralName[]{ name };
+ }
+
+ private GeneralNames(
+ Asn1Sequence seq)
+ {
+ this.names = new GeneralName[seq.Count];
+
+ for (int i = 0; i != seq.Count; i++)
+ {
+ names[i] = GeneralName.GetInstance(seq[i]);
+ }
+ }
+
+ public GeneralName[] GetNames()
+ {
+ return (GeneralName[]) names.Clone();
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * GeneralNames ::= Sequence SIZE {1..MAX} OF GeneralName
+ *
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(names);
+ }
+
+ public override string ToString()
+ {
+ StringBuilder buf = new StringBuilder();
+ string sep = Platform.NewLine;
+
+ buf.Append("GeneralNames:");
+ buf.Append(sep);
+
+ foreach (GeneralName name in names)
+ {
+ buf.Append(" ");
+ buf.Append(name);
+ buf.Append(sep);
+ }
+
+ return buf.ToString();
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/RoleSyntax.cs b/src/core/srcbc/asn1/x509/RoleSyntax.cs
index 732a0be..4fc6e9b 100644
--- a/src/core/srcbc/asn1/x509/RoleSyntax.cs
+++ b/src/core/srcbc/asn1/x509/RoleSyntax.cs
@@ -1,234 +1,234 @@
-using System;
-using System.Text;
-
-namespace Org.BouncyCastle.Asn1.X509
-{
- /**
- * Implementation of the RoleSyntax object as specified by the RFC3281.
- *
- *
- * RoleSyntax ::= SEQUENCE {
- * roleAuthority [0] GeneralNames OPTIONAL,
- * roleName [1] GeneralName
- * }
- *
- */
- public class RoleSyntax
- : Asn1Encodable
- {
- private readonly GeneralNames roleAuthority;
- private readonly GeneralName roleName;
-
- /**
- * RoleSyntax factory method.
- * @param obj the object used to construct an instance of
- * RoleSyntax
. It must be an instance of RoleSyntax
- *
or Asn1Sequence
.
- * @return the instance of RoleSyntax
built from the
- * supplied object.
- * @throws java.lang.ArgumentException if the object passed
- * to the factory is not an instance of RoleSyntax
or
- * Asn1Sequence
.
- */
- public static RoleSyntax GetInstance(
- object obj)
- {
- if (obj == null || obj is RoleSyntax)
- {
- return (RoleSyntax) obj;
- }
-
- if (obj is Asn1Sequence)
- {
- return new RoleSyntax((Asn1Sequence) obj);
- }
-
- throw new ArgumentException("unknown object in 'RoleSyntax' factory: " + obj.GetType().Name, "obj");
- }
-
- /**
- * Constructor.
- * @param roleAuthority the role authority of this RoleSyntax.
- * @param roleName the role name of this RoleSyntax.
- */
- public RoleSyntax(
- GeneralNames roleAuthority,
- GeneralName roleName)
- {
- if (roleName == null
- || roleName.TagNo != GeneralName.UniformResourceIdentifier
- || ((IAsn1String) roleName.Name).GetString().Equals(""))
- {
- throw new ArgumentException("the role name MUST be non empty and MUST " +
- "use the URI option of GeneralName");
- }
-
- this.roleAuthority = roleAuthority;
- this.roleName = roleName;
- }
-
- /**
- * Constructor. Invoking this constructor is the same as invoking
- * new RoleSyntax(null, roleName)
.
- * @param roleName the role name of this RoleSyntax.
- */
- public RoleSyntax(
- GeneralName roleName)
- : this(null, roleName)
- {
- }
-
- /**
- * Utility constructor. Takes a string
argument representing
- * the role name, builds a GeneralName
to hold the role name
- * and calls the constructor that takes a GeneralName
.
- * @param roleName
- */
- public RoleSyntax(
- string roleName)
- : this(new GeneralName(GeneralName.UniformResourceIdentifier,
- (roleName == null)? "": roleName))
- {
- }
-
- /**
- * Constructor that builds an instance of RoleSyntax
by
- * extracting the encoded elements from the Asn1Sequence
- * object supplied.
- * @param seq an instance of Asn1Sequence
that holds
- * the encoded elements used to build this RoleSyntax
.
- */
- private RoleSyntax(
- Asn1Sequence seq)
- {
- if (seq.Count < 1 || seq.Count > 2)
- {
- throw new ArgumentException("Bad sequence size: " + seq.Count);
- }
-
- for (int i = 0; i != seq.Count; i++)
- {
- Asn1TaggedObject taggedObject = Asn1TaggedObject.GetInstance(seq[i]);
- switch (taggedObject.TagNo)
- {
- case 0:
- roleAuthority = GeneralNames.GetInstance(taggedObject, false);
- break;
- case 1:
- roleName = GeneralName.GetInstance(taggedObject, false);
- break;
- default:
- throw new ArgumentException("Unknown tag in RoleSyntax");
- }
- }
- }
-
- /**
- * Gets the role authority of this RoleSyntax.
- * @return an instance of GeneralNames
holding the
- * role authority of this RoleSyntax.
- */
- public GeneralNames RoleAuthority
- {
- get { return this.roleAuthority; }
- }
-
- /**
- * Gets the role name of this RoleSyntax.
- * @return an instance of GeneralName
holding the
- * role name of this RoleSyntax.
- */
- public GeneralName RoleName
- {
- get { return this.roleName; }
- }
-
- /**
- * Gets the role name as a java.lang.string
object.
- * @return the role name of this RoleSyntax represented as a
- * string
object.
- */
- public string GetRoleNameAsString()
- {
- return ((IAsn1String) this.roleName.Name).GetString();
- }
-
- /**
- * Gets the role authority as a string[]
object.
- * @return the role authority of this RoleSyntax represented as a
- * string[]
array.
- */
- public string[] GetRoleAuthorityAsString()
- {
- if (roleAuthority == null)
- {
- return new string[0];
- }
-
- GeneralName[] names = roleAuthority.GetNames();
- string[] namesString = new string[names.Length];
- for(int i = 0; i < names.Length; i++)
- {
- Asn1Encodable asn1Value = names[i].Name;
- if (asn1Value is IAsn1String)
- {
- namesString[i] = ((IAsn1String) asn1Value).GetString();
- }
- else
- {
- namesString[i] = asn1Value.ToString();
- }
- }
-
- return namesString;
- }
-
- /**
- * Implementation of the method ToAsn1Object
as
- * required by the superclass ASN1Encodable
.
- *
- *
- * RoleSyntax ::= SEQUENCE {
- * roleAuthority [0] GeneralNames OPTIONAL,
- * roleName [1] GeneralName
- * }
- *
- */
- public override Asn1Object ToAsn1Object()
- {
- Asn1EncodableVector v = new Asn1EncodableVector();
-
- if (this.roleAuthority != null)
- {
- v.Add(new DerTaggedObject(false, 0, roleAuthority));
- }
-
- v.Add(new DerTaggedObject(false, 1, roleName));
-
- return new DerSequence(v);
- }
-
- public override string ToString()
- {
- StringBuilder buff = new StringBuilder("Name: " + this.GetRoleNameAsString() +
- " - Auth: ");
-
- if (this.roleAuthority == null || roleAuthority.GetNames().Length == 0)
- {
- buff.Append("N/A");
- }
- else
- {
- string[] names = this.GetRoleAuthorityAsString();
- buff.Append('[').Append(names[0]);
- for(int i = 1; i < names.Length; i++)
- {
- buff.Append(", ").Append(names[i]);
- }
- buff.Append(']');
- }
-
- return buff.ToString();
- }
- }
-}
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * Implementation of the RoleSyntax object as specified by the RFC3281.
+ *
+ *
+ * RoleSyntax ::= SEQUENCE {
+ * roleAuthority [0] GeneralNames OPTIONAL,
+ * roleName [1] GeneralName
+ * }
+ *
+ */
+ public class RoleSyntax
+ : Asn1Encodable
+ {
+ private readonly GeneralNames roleAuthority;
+ private readonly GeneralName roleName;
+
+ /**
+ * RoleSyntax factory method.
+ * @param obj the object used to construct an instance of
+ * RoleSyntax
. It must be an instance of RoleSyntax
+ *
or Asn1Sequence
.
+ * @return the instance of RoleSyntax
built from the
+ * supplied object.
+ * @throws java.lang.ArgumentException if the object passed
+ * to the factory is not an instance of RoleSyntax
or
+ * Asn1Sequence
.
+ */
+ public static RoleSyntax GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is RoleSyntax)
+ {
+ return (RoleSyntax) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new RoleSyntax((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in 'RoleSyntax' factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor.
+ * @param roleAuthority the role authority of this RoleSyntax.
+ * @param roleName the role name of this RoleSyntax.
+ */
+ public RoleSyntax(
+ GeneralNames roleAuthority,
+ GeneralName roleName)
+ {
+ if (roleName == null
+ || roleName.TagNo != GeneralName.UniformResourceIdentifier
+ || ((IAsn1String) roleName.Name).GetString().Equals(""))
+ {
+ throw new ArgumentException("the role name MUST be non empty and MUST " +
+ "use the URI option of GeneralName");
+ }
+
+ this.roleAuthority = roleAuthority;
+ this.roleName = roleName;
+ }
+
+ /**
+ * Constructor. Invoking this constructor is the same as invoking
+ * new RoleSyntax(null, roleName)
.
+ * @param roleName the role name of this RoleSyntax.
+ */
+ public RoleSyntax(
+ GeneralName roleName)
+ : this(null, roleName)
+ {
+ }
+
+ /**
+ * Utility constructor. Takes a string
argument representing
+ * the role name, builds a GeneralName
to hold the role name
+ * and calls the constructor that takes a GeneralName
.
+ * @param roleName
+ */
+ public RoleSyntax(
+ string roleName)
+ : this(new GeneralName(GeneralName.UniformResourceIdentifier,
+ (roleName == null)? "": roleName))
+ {
+ }
+
+ /**
+ * Constructor that builds an instance of RoleSyntax
by
+ * extracting the encoded elements from the Asn1Sequence
+ * object supplied.
+ * @param seq an instance of Asn1Sequence
that holds
+ * the encoded elements used to build this RoleSyntax
.
+ */
+ private RoleSyntax(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1 || seq.Count > 2)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+
+ for (int i = 0; i != seq.Count; i++)
+ {
+ Asn1TaggedObject taggedObject = Asn1TaggedObject.GetInstance(seq[i]);
+ switch (taggedObject.TagNo)
+ {
+ case 0:
+ roleAuthority = GeneralNames.GetInstance(taggedObject, false);
+ break;
+ case 1:
+ roleName = GeneralName.GetInstance(taggedObject, true);
+ break;
+ default:
+ throw new ArgumentException("Unknown tag in RoleSyntax");
+ }
+ }
+ }
+
+ /**
+ * Gets the role authority of this RoleSyntax.
+ * @return an instance of GeneralNames
holding the
+ * role authority of this RoleSyntax.
+ */
+ public GeneralNames RoleAuthority
+ {
+ get { return this.roleAuthority; }
+ }
+
+ /**
+ * Gets the role name of this RoleSyntax.
+ * @return an instance of GeneralName
holding the
+ * role name of this RoleSyntax.
+ */
+ public GeneralName RoleName
+ {
+ get { return this.roleName; }
+ }
+
+ /**
+ * Gets the role name as a java.lang.string
object.
+ * @return the role name of this RoleSyntax represented as a
+ * string
object.
+ */
+ public string GetRoleNameAsString()
+ {
+ return ((IAsn1String) this.roleName.Name).GetString();
+ }
+
+ /**
+ * Gets the role authority as a string[]
object.
+ * @return the role authority of this RoleSyntax represented as a
+ * string[]
array.
+ */
+ public string[] GetRoleAuthorityAsString()
+ {
+ if (roleAuthority == null)
+ {
+ return new string[0];
+ }
+
+ GeneralName[] names = roleAuthority.GetNames();
+ string[] namesString = new string[names.Length];
+ for(int i = 0; i < names.Length; i++)
+ {
+ Asn1Encodable asn1Value = names[i].Name;
+ if (asn1Value is IAsn1String)
+ {
+ namesString[i] = ((IAsn1String) asn1Value).GetString();
+ }
+ else
+ {
+ namesString[i] = asn1Value.ToString();
+ }
+ }
+
+ return namesString;
+ }
+
+ /**
+ * Implementation of the method ToAsn1Object
as
+ * required by the superclass ASN1Encodable
.
+ *
+ *
+ * RoleSyntax ::= SEQUENCE {
+ * roleAuthority [0] GeneralNames OPTIONAL,
+ * roleName [1] GeneralName
+ * }
+ *
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (this.roleAuthority != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, roleAuthority));
+ }
+
+ v.Add(new DerTaggedObject(true, 1, roleName));
+
+ return new DerSequence(v);
+ }
+
+ public override string ToString()
+ {
+ StringBuilder buff = new StringBuilder("Name: " + this.GetRoleNameAsString() +
+ " - Auth: ");
+
+ if (this.roleAuthority == null || roleAuthority.GetNames().Length == 0)
+ {
+ buff.Append("N/A");
+ }
+ else
+ {
+ string[] names = this.GetRoleAuthorityAsString();
+ buff.Append('[').Append(names[0]);
+ for(int i = 1; i < names.Length; i++)
+ {
+ buff.Append(", ").Append(names[i]);
+ }
+ buff.Append(']');
+ }
+
+ return buff.ToString();
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/Target.cs b/src/core/srcbc/asn1/x509/Target.cs
index 6ff6da7..309b28c 100644
--- a/src/core/srcbc/asn1/x509/Target.cs
+++ b/src/core/srcbc/asn1/x509/Target.cs
@@ -1,140 +1,139 @@
-using System;
-
-namespace Org.BouncyCastle.Asn1.X509
-{
- /**
- * Target structure used in target information extension for attribute
- * certificates from RFC 3281.
- *
- *
- * Target ::= CHOICE {
- * targetName [0] GeneralName,
- * targetGroup [1] GeneralName,
- * targetCert [2] TargetCert
- * }
- *
- *
- *
- * The targetCert field is currently not supported and must not be used
- * according to RFC 3281.
- */
- public class Target
- : Asn1Encodable
- //, ASN1Choice
- {
- public enum Choice
- {
- Name = 0,
- Group = 1
- };
-
- private readonly GeneralName targetName;
- private readonly GeneralName targetGroup;
-
- /**
- * Creates an instance of a Target from the given object.
- *
- * obj
can be a Target or a {@link Asn1TaggedObject}
- *
- * @param obj The object.
- * @return A Target instance.
- * @throws ArgumentException if the given object cannot be
- * interpreted as Target.
- */
- public static Target GetInstance(
- object obj)
- {
- if (obj is Target)
- {
- return (Target) obj;
- }
-
- if (obj is Asn1TaggedObject)
- {
- return new Target((Asn1TaggedObject) obj);
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- /**
- * Constructor from Asn1TaggedObject.
- *
- * @param tagObj The tagged object.
- * @throws ArgumentException if the encoding is wrong.
- */
- private Target(
- Asn1TaggedObject tagObj)
- {
- switch ((Choice) tagObj.TagNo)
- {
- case Choice.Name: // GeneralName is already a choice so explicit
- targetName = GeneralName.GetInstance(tagObj, true);
- break;
- case Choice.Group:
- targetGroup = GeneralName.GetInstance(tagObj, true);
- break;
- default:
- throw new ArgumentException("unknown tag: " + tagObj.TagNo);
- }
- }
-
- /**
- * Constructor from given details.
- *
- * Exactly one of the parameters must be not null
.
- *
- * @param type the choice type to apply to the name.
- * @param name the general name.
- * @throws ArgumentException if type is invalid.
- */
- public Target(
- Choice type,
- GeneralName name)
- : this(new DerTaggedObject((int) type, name))
- {
- }
-
- /**
- * @return Returns the targetGroup.
- */
- public virtual GeneralName TargetGroup
- {
- get { return targetGroup; }
- }
-
- /**
- * @return Returns the targetName.
- */
- public virtual GeneralName TargetName
- {
- get { return targetName; }
- }
-
- /**
- * Produce an object suitable for an Asn1OutputStream.
- *
- * Returns:
- *
- *
- * Target ::= CHOICE {
- * targetName [0] GeneralName,
- * targetGroup [1] GeneralName,
- * targetCert [2] TargetCert
- * }
- *
- *
- * @return an Asn1Object
- */
- public override Asn1Object ToAsn1Object()
- {
- // GeneralName is a choice already so most be explicitly tagged
- if (targetName != null)
- {
- return new DerTaggedObject(true, 0, targetName);
- }
-
- return new DerTaggedObject(true, 1, targetGroup);
- }
- }
-}
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * Target structure used in target information extension for attribute
+ * certificates from RFC 3281.
+ *
+ *
+ * Target ::= CHOICE {
+ * targetName [0] GeneralName,
+ * targetGroup [1] GeneralName,
+ * targetCert [2] TargetCert
+ * }
+ *
+ *
+ *
+ * The targetCert field is currently not supported and must not be used
+ * according to RFC 3281.
+ */
+ public class Target
+ : Asn1Encodable, IAsn1Choice
+ {
+ public enum Choice
+ {
+ Name = 0,
+ Group = 1
+ };
+
+ private readonly GeneralName targetName;
+ private readonly GeneralName targetGroup;
+
+ /**
+ * Creates an instance of a Target from the given object.
+ *
+ * obj
can be a Target or a {@link Asn1TaggedObject}
+ *
+ * @param obj The object.
+ * @return A Target instance.
+ * @throws ArgumentException if the given object cannot be
+ * interpreted as Target.
+ */
+ public static Target GetInstance(
+ object obj)
+ {
+ if (obj is Target)
+ {
+ return (Target) obj;
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ return new Target((Asn1TaggedObject) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from Asn1TaggedObject.
+ *
+ * @param tagObj The tagged object.
+ * @throws ArgumentException if the encoding is wrong.
+ */
+ private Target(
+ Asn1TaggedObject tagObj)
+ {
+ switch ((Choice) tagObj.TagNo)
+ {
+ case Choice.Name: // GeneralName is already a choice so explicit
+ targetName = GeneralName.GetInstance(tagObj, true);
+ break;
+ case Choice.Group:
+ targetGroup = GeneralName.GetInstance(tagObj, true);
+ break;
+ default:
+ throw new ArgumentException("unknown tag: " + tagObj.TagNo);
+ }
+ }
+
+ /**
+ * Constructor from given details.
+ *
+ * Exactly one of the parameters must be not null
.
+ *
+ * @param type the choice type to apply to the name.
+ * @param name the general name.
+ * @throws ArgumentException if type is invalid.
+ */
+ public Target(
+ Choice type,
+ GeneralName name)
+ : this(new DerTaggedObject((int) type, name))
+ {
+ }
+
+ /**
+ * @return Returns the targetGroup.
+ */
+ public virtual GeneralName TargetGroup
+ {
+ get { return targetGroup; }
+ }
+
+ /**
+ * @return Returns the targetName.
+ */
+ public virtual GeneralName TargetName
+ {
+ get { return targetName; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * Target ::= CHOICE {
+ * targetName [0] GeneralName,
+ * targetGroup [1] GeneralName,
+ * targetCert [2] TargetCert
+ * }
+ *
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ // GeneralName is a choice already so most be explicitly tagged
+ if (targetName != null)
+ {
+ return new DerTaggedObject(true, 0, targetName);
+ }
+
+ return new DerTaggedObject(true, 1, targetGroup);
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/Time.cs b/src/core/srcbc/asn1/x509/Time.cs
index 5c9fc67..25f11c1 100644
--- a/src/core/srcbc/asn1/x509/Time.cs
+++ b/src/core/srcbc/asn1/x509/Time.cs
@@ -1,126 +1,126 @@
-using System;
-
-namespace Org.BouncyCastle.Asn1.X509
-{
- public class Time
- : Asn1Encodable
- {
- internal Asn1Object time;
-
- public static Time GetInstance(
- Asn1TaggedObject obj,
- bool explicitly)
- {
- return GetInstance(obj.GetObject());
- }
-
- public Time(
- Asn1Object time)
- {
- if (time == null)
- throw new ArgumentNullException("time");
-
- if (!(time is DerUtcTime) && !(time is DerGeneralizedTime))
- {
- throw new ArgumentException("unknown object passed to Time");
- }
-
- this.time = time;
- }
-
- /**
- * creates a time object from a given date - if the date is between 1950
- * and 2049 a UTCTime object is Generated, otherwise a GeneralizedTime
- * is used.
- */
- public Time(
- DateTime date)
- {
- string d = date.ToString("yyyyMMddHHmmss") + "Z";
-
- int year = Int32.Parse(d.Substring(0, 4));
-
- if (year < 1950 || year > 2049)
- {
- time = new DerGeneralizedTime(d);
- }
- else
- {
- time = new DerUtcTime(d.Substring(2));
- }
- }
-
- public static Time GetInstance(
- object obj)
- {
- if (obj is Time)
- {
- return (Time) obj;
- }
-
- if (obj is DerUtcTime)
- {
- return new Time((DerUtcTime) obj);
- }
-
- if (obj is DerGeneralizedTime)
- {
- return new Time((DerGeneralizedTime) obj);
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- public string GetTime()
- {
- if (time is DerUtcTime)
- {
- return ((DerUtcTime) time).AdjustedTimeString;
- }
-
- return ((DerGeneralizedTime) time).GetTime();
- }
-
- ///
- /// Return our time as DateTime.
- ///
- /// A date time.
- public DateTime ToDateTime()
- {
- try
- {
- if (time is DerUtcTime)
- {
- return ((DerUtcTime)time).ToAdjustedDateTime();
- }
- else
- {
- return ((DerGeneralizedTime)time).ToDateTime();
- }
- }
- catch (FormatException e)
- {
- // this should never happen
- throw new InvalidOperationException("invalid date string: " + e.Message);
- }
- }
-
- /**
- * Produce an object suitable for an Asn1OutputStream.
- *
- * Time ::= CHOICE {
- * utcTime UTCTime,
- * generalTime GeneralizedTime }
- *
- */
- public override Asn1Object ToAsn1Object()
- {
- return time;
- }
-
- public override string ToString()
- {
- return GetTime();
- }
- }
-}
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class Time
+ : Asn1Encodable, IAsn1Choice
+ {
+ internal Asn1Object time;
+
+ public static Time GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(obj.GetObject());
+ }
+
+ public Time(
+ Asn1Object time)
+ {
+ if (time == null)
+ throw new ArgumentNullException("time");
+
+ if (!(time is DerUtcTime) && !(time is DerGeneralizedTime))
+ {
+ throw new ArgumentException("unknown object passed to Time");
+ }
+
+ this.time = time;
+ }
+
+ /**
+ * creates a time object from a given date - if the date is between 1950
+ * and 2049 a UTCTime object is Generated, otherwise a GeneralizedTime
+ * is used.
+ */
+ public Time(
+ DateTime date)
+ {
+ string d = date.ToString("yyyyMMddHHmmss") + "Z";
+
+ int year = Int32.Parse(d.Substring(0, 4));
+
+ if (year < 1950 || year > 2049)
+ {
+ time = new DerGeneralizedTime(d);
+ }
+ else
+ {
+ time = new DerUtcTime(d.Substring(2));
+ }
+ }
+
+ public static Time GetInstance(
+ object obj)
+ {
+ if (obj is Time)
+ {
+ return (Time) obj;
+ }
+
+ if (obj is DerUtcTime)
+ {
+ return new Time((DerUtcTime) obj);
+ }
+
+ if (obj is DerGeneralizedTime)
+ {
+ return new Time((DerGeneralizedTime) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public string GetTime()
+ {
+ if (time is DerUtcTime)
+ {
+ return ((DerUtcTime) time).AdjustedTimeString;
+ }
+
+ return ((DerGeneralizedTime) time).GetTime();
+ }
+
+ ///
+ /// Return our time as DateTime.
+ ///
+ /// A date time.
+ public DateTime ToDateTime()
+ {
+ try
+ {
+ if (time is DerUtcTime)
+ {
+ return ((DerUtcTime)time).ToAdjustedDateTime();
+ }
+ else
+ {
+ return ((DerGeneralizedTime)time).ToDateTime();
+ }
+ }
+ catch (FormatException e)
+ {
+ // this should never happen
+ throw new InvalidOperationException("invalid date string: " + e.Message);
+ }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ *
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return time;
+ }
+
+ public override string ToString()
+ {
+ return GetTime();
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/X509Name.cs b/src/core/srcbc/asn1/x509/X509Name.cs
index a83cb1f..b8ac338 100644
--- a/src/core/srcbc/asn1/x509/X509Name.cs
+++ b/src/core/srcbc/asn1/x509/X509Name.cs
@@ -1,1040 +1,1072 @@
-using System;
-using System.Collections;
-using System.Globalization;
-using System.Text;
-
-using Org.BouncyCastle.Asn1.Pkcs;
-using Org.BouncyCastle.Utilities.Encoders;
-
-namespace Org.BouncyCastle.Asn1.X509
-{
- /**
- *
- * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
- *
- * RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
- *
- * AttributeTypeAndValue ::= SEQUENCE {
- * type OBJECT IDENTIFIER,
- * value ANY }
- *
- */
- public class X509Name
- : Asn1Encodable
- {
- /**
- * country code - StringType(SIZE(2))
- */
- public static readonly DerObjectIdentifier C = new DerObjectIdentifier("2.5.4.6");
-
- /**
- * organization - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier O = new DerObjectIdentifier("2.5.4.10");
-
- /**
- * organizational unit name - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier OU = new DerObjectIdentifier("2.5.4.11");
-
- /**
- * Title
- */
- public static readonly DerObjectIdentifier T = new DerObjectIdentifier("2.5.4.12");
-
- /**
- * common name - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier CN = new DerObjectIdentifier("2.5.4.3");
-
- /**
- * street - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier Street = new DerObjectIdentifier("2.5.4.9");
-
- /**
- * device serial number name - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier SerialNumber = new DerObjectIdentifier("2.5.4.5");
-
- /**
- * locality name - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier L = new DerObjectIdentifier("2.5.4.7");
-
- /**
- * state, or province name - StringType(SIZE(1..64))
- */
- public static readonly DerObjectIdentifier ST = new DerObjectIdentifier("2.5.4.8");
-
- /**
- * Naming attributes of type X520name
- */
- public static readonly DerObjectIdentifier Surname = new DerObjectIdentifier("2.5.4.4");
- public static readonly DerObjectIdentifier GivenName = new DerObjectIdentifier("2.5.4.42");
- public static readonly DerObjectIdentifier Initials = new DerObjectIdentifier("2.5.4.43");
- public static readonly DerObjectIdentifier Generation = new DerObjectIdentifier("2.5.4.44");
- public static readonly DerObjectIdentifier UniqueIdentifier = new DerObjectIdentifier("2.5.4.45");
-
- /**
- * businessCategory - DirectoryString(SIZE(1..128)
- */
- public static readonly DerObjectIdentifier BusinessCategory = new DerObjectIdentifier(
- "2.5.4.15");
-
- /**
- * postalCode - DirectoryString(SIZE(1..40)
- */
- public static readonly DerObjectIdentifier PostalCode = new DerObjectIdentifier(
- "2.5.4.17");
-
- /**
- * dnQualifier - DirectoryString(SIZE(1..64)
- */
- public static readonly DerObjectIdentifier DnQualifier = new DerObjectIdentifier(
- "2.5.4.46");
-
- /**
- * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
- */
- public static readonly DerObjectIdentifier Pseudonym = new DerObjectIdentifier(
- "2.5.4.65");
-
- /**
- * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
- */
- public static readonly DerObjectIdentifier DateOfBirth = new DerObjectIdentifier(
- "1.3.6.1.5.5.7.9.1");
-
- /**
- * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
- */
- public static readonly DerObjectIdentifier PlaceOfBirth = new DerObjectIdentifier(
- "1.3.6.1.5.5.7.9.2");
-
- /**
- * RFC 3039 DateOfBirth - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
- */
- public static readonly DerObjectIdentifier Gender = new DerObjectIdentifier(
- "1.3.6.1.5.5.7.9.3");
-
- /**
- * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
- * codes only
- */
- public static readonly DerObjectIdentifier CountryOfCitizenship = new DerObjectIdentifier(
- "1.3.6.1.5.5.7.9.4");
-
- /**
- * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
- * codes only
- */
- public static readonly DerObjectIdentifier CountryOfResidence = new DerObjectIdentifier(
- "1.3.6.1.5.5.7.9.5");
-
- /**
- * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
- */
- public static readonly DerObjectIdentifier NameAtBirth = new DerObjectIdentifier("1.3.36.8.3.14");
-
- /**
- * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
- * DirectoryString(SIZE(1..30))
- */
- public static readonly DerObjectIdentifier PostalAddress = new DerObjectIdentifier("2.5.4.16");
-
- /**
- * id-at-telephoneNumber
- */
- public static readonly DerObjectIdentifier TelephoneNumber = new DerObjectIdentifier("2.5.4.20");
-
- /**
- * Email address (RSA PKCS#9 extension) - IA5String.
- * Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
- */
- public static readonly DerObjectIdentifier EmailAddress = PkcsObjectIdentifiers.Pkcs9AtEmailAddress;
-
- /**
- * more from PKCS#9
- */
- public static readonly DerObjectIdentifier UnstructuredName = PkcsObjectIdentifiers.Pkcs9AtUnstructuredName;
- public static readonly DerObjectIdentifier UnstructuredAddress = PkcsObjectIdentifiers.Pkcs9AtUnstructuredAddress;
-
- /**
- * email address in Verisign certificates
- */
- public static readonly DerObjectIdentifier E = EmailAddress;
-
- /*
- * others...
- */
- public static readonly DerObjectIdentifier DC = new DerObjectIdentifier("0.9.2342.19200300.100.1.25");
-
- /**
- * LDAP User id.
- */
- public static readonly DerObjectIdentifier UID = new DerObjectIdentifier("0.9.2342.19200300.100.1.1");
-
- /**
- * determines whether or not strings should be processed and printed
- * from back to front.
- */
-// public static bool DefaultReverse = false;
- public static bool DefaultReverse
- {
- get { return defaultReverse[0]; }
- set { defaultReverse[0] = value; }
- }
-
- private static readonly bool[] defaultReverse = { false };
-
- /**
- * default look up table translating OID values into their common symbols following
- * the convention in RFC 2253 with a few extras
- */
- public static readonly Hashtable DefaultSymbols = new Hashtable();
-
- /**
- * look up table translating OID values into their common symbols following the convention in RFC 2253
- */
- public static readonly Hashtable RFC2253Symbols = new Hashtable();
-
- /**
- * look up table translating OID values into their common symbols following the convention in RFC 1779
- *
- */
- public static readonly Hashtable RFC1779Symbols = new Hashtable();
-
- /**
- * look up table translating common symbols into their OIDS.
- */
- public static readonly Hashtable DefaultLookup = new Hashtable();
-
- /**
- * look up table translating OID values into their common symbols.
- */
- [Obsolete("Use 'DefaultSymbols' instead")]
- public static readonly Hashtable OIDLookup = DefaultSymbols;
-
- /**
- * look up table translating string values into their OIDS -
- * this static is scheduled for deletion
- */
- [Obsolete("Use 'DefaultLookup' instead")]
- public static readonly Hashtable SymbolLookup = DefaultLookup;
-
- static X509Name()
- {
- DefaultSymbols.Add(C, "C");
- DefaultSymbols.Add(O, "O");
- DefaultSymbols.Add(T, "T");
- DefaultSymbols.Add(OU, "OU");
- DefaultSymbols.Add(CN, "CN");
- DefaultSymbols.Add(L, "L");
- DefaultSymbols.Add(ST, "ST");
- DefaultSymbols.Add(SerialNumber, "SERIALNUMBER");
- DefaultSymbols.Add(EmailAddress, "E");
- DefaultSymbols.Add(DC, "DC");
- DefaultSymbols.Add(UID, "UID");
- DefaultSymbols.Add(Street, "STREET");
- DefaultSymbols.Add(Surname, "SURNAME");
- DefaultSymbols.Add(GivenName, "GIVENNAME");
- DefaultSymbols.Add(Initials, "INITIALS");
- DefaultSymbols.Add(Generation, "GENERATION");
- DefaultSymbols.Add(UnstructuredAddress, "unstructuredAddress");
- DefaultSymbols.Add(UnstructuredName, "unstructuredName");
- DefaultSymbols.Add(UniqueIdentifier, "UniqueIdentifier");
- DefaultSymbols.Add(DnQualifier, "DN");
- DefaultSymbols.Add(Pseudonym, "Pseudonym");
- DefaultSymbols.Add(PostalAddress, "PostalAddress");
- DefaultSymbols.Add(NameAtBirth, "NameAtBirth");
- DefaultSymbols.Add(CountryOfCitizenship, "CountryOfCitizenship");
- DefaultSymbols.Add(CountryOfResidence, "CountryOfResidence");
- DefaultSymbols.Add(Gender, "Gender");
- DefaultSymbols.Add(PlaceOfBirth, "PlaceOfBirth");
- DefaultSymbols.Add(DateOfBirth, "DateOfBirth");
- DefaultSymbols.Add(PostalCode, "PostalCode");
- DefaultSymbols.Add(BusinessCategory, "BusinessCategory");
- DefaultSymbols.Add(TelephoneNumber, "TelephoneNumber");
-
- RFC2253Symbols.Add(C, "C");
- RFC2253Symbols.Add(O, "O");
- RFC2253Symbols.Add(OU, "OU");
- RFC2253Symbols.Add(CN, "CN");
- RFC2253Symbols.Add(L, "L");
- RFC2253Symbols.Add(ST, "ST");
- RFC2253Symbols.Add(Street, "STREET");
- RFC2253Symbols.Add(DC, "DC");
- RFC2253Symbols.Add(UID, "UID");
-
- RFC1779Symbols.Add(C, "C");
- RFC1779Symbols.Add(O, "O");
- RFC1779Symbols.Add(OU, "OU");
- RFC1779Symbols.Add(CN, "CN");
- RFC1779Symbols.Add(L, "L");
- RFC1779Symbols.Add(ST, "ST");
- RFC1779Symbols.Add(Street, "STREET");
-
- DefaultLookup.Add("c", C);
- DefaultLookup.Add("o", O);
- DefaultLookup.Add("t", T);
- DefaultLookup.Add("ou", OU);
- DefaultLookup.Add("cn", CN);
- DefaultLookup.Add("l", L);
- DefaultLookup.Add("st", ST);
- DefaultLookup.Add("serialnumber", SerialNumber);
- DefaultLookup.Add("street", Street);
- DefaultLookup.Add("emailaddress", E);
- DefaultLookup.Add("dc", DC);
- DefaultLookup.Add("e", E);
- DefaultLookup.Add("uid", UID);
- DefaultLookup.Add("surname", Surname);
- DefaultLookup.Add("givenname", GivenName);
- DefaultLookup.Add("initials", Initials);
- DefaultLookup.Add("generation", Generation);
- DefaultLookup.Add("unstructuredaddress", UnstructuredAddress);
- DefaultLookup.Add("unstructuredname", UnstructuredName);
- DefaultLookup.Add("uniqueidentifier", UniqueIdentifier);
- DefaultLookup.Add("dn", DnQualifier);
- DefaultLookup.Add("pseudonym", Pseudonym);
- DefaultLookup.Add("postaladdress", PostalAddress);
- DefaultLookup.Add("nameofbirth", NameAtBirth);
- DefaultLookup.Add("countryofcitizenship", CountryOfCitizenship);
- DefaultLookup.Add("countryofresidence", CountryOfResidence);
- DefaultLookup.Add("gender", Gender);
- DefaultLookup.Add("placeofbirth", PlaceOfBirth);
- DefaultLookup.Add("dateofbirth", DateOfBirth);
- DefaultLookup.Add("postalcode", PostalCode);
- DefaultLookup.Add("businesscategory", BusinessCategory);
- DefaultLookup.Add("telephonenumber", TelephoneNumber);
- }
-
- private readonly ArrayList ordering = new ArrayList();
- private readonly X509NameEntryConverter converter;
-
- private ArrayList values = new ArrayList();
- private ArrayList added = new ArrayList();
- private Asn1Sequence seq;
-
- /**
- * Return a X509Name based on the passed in tagged object.
- *
- * @param obj tag object holding name.
- * @param explicitly true if explicitly tagged false otherwise.
- * @return the X509Name
- */
- public static X509Name GetInstance(
- Asn1TaggedObject obj,
- bool explicitly)
- {
- return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
- }
-
- public static X509Name GetInstance(
- object obj)
- {
- if (obj == null || obj is X509Name)
- {
- return (X509Name) obj;
- }
-
- if (obj is Asn1Sequence)
- {
- return new X509Name((Asn1Sequence) obj);
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name);
- }
-
- /**
- * Constructor from Asn1Sequence
- *
- * the principal will be a list of constructed sets, each containing an (OID, string) pair.
- */
- protected X509Name(
- Asn1Sequence seq)
- {
- this.seq = seq;
-
- foreach (Asn1Encodable asn1Obj in seq)
- {
- Asn1Set asn1Set = Asn1Set.GetInstance(asn1Obj.ToAsn1Object());
-
- for (int i = 0; i < asn1Set.Count; i++)
- {
- Asn1Sequence s = Asn1Sequence.GetInstance(asn1Set[i].ToAsn1Object());
-
- if (s.Count != 2)
- throw new ArgumentException("badly sized pair");
-
- ordering.Add(DerObjectIdentifier.GetInstance(s[0].ToAsn1Object()));
-
- Asn1Object derValue = s[1].ToAsn1Object();
- if (derValue is IAsn1String && !(derValue is DerUniversalString))
- {
- string v = ((IAsn1String)derValue).GetString();
- if (v.StartsWith("#"))
- {
- v = "\\" + v;
- }
-
- values.Add(v);
- }
- else
- {
- byte[] hex = Hex.Encode(derValue.GetEncoded());
- values.Add("#" + Encoding.ASCII.GetString(hex, 0, hex.Length));
- }
-
- added.Add(i != 0);
- }
- }
- }
-
- /**
- * Constructor from a table of attributes with ordering.
- *
- * it's is assumed the table contains OID/string pairs, and the contents
- * of the table are copied into an internal table as part of the
- * construction process. The ordering ArrayList should contain the OIDs
- * in the order they are meant to be encoded or printed in ToString.
- */
- public X509Name(
- ArrayList ordering,
- Hashtable attributes)
- : this(ordering, attributes, new X509DefaultEntryConverter())
- {
- }
-
- /**
- * Constructor from a table of attributes with ordering.
- *
- * it's is assumed the table contains OID/string pairs, and the contents
- * of the table are copied into an internal table as part of the
- * construction process. The ordering ArrayList should contain the OIDs
- * in the order they are meant to be encoded or printed in ToString.
- *
- * The passed in converter will be used to convert the strings into their
- * ASN.1 counterparts.
- */
- public X509Name(
- ArrayList ordering,
- Hashtable attributes,
- X509NameEntryConverter converter)
- {
- this.converter = converter;
-
- foreach (DerObjectIdentifier oid in ordering)
- {
- object attribute = attributes[oid];
- if (attribute == null)
- {
- throw new ArgumentException("No attribute for object id - " + oid + " - passed to distinguished name");
- }
-
- this.ordering.Add(oid);
- this.added.Add(false);
- this.values.Add(attribute); // copy the hash table
- }
- }
-
- /**
- * Takes two vectors one of the oids and the other of the values.
- */
- public X509Name(
- ArrayList oids,
- ArrayList values)
- : this(oids, values, new X509DefaultEntryConverter())
- {
- }
-
- /**
- * Takes two vectors one of the oids and the other of the values.
- *
- * The passed in converter will be used to convert the strings into their
- * ASN.1 counterparts.
- */
- public X509Name(
- ArrayList oids,
- ArrayList values,
- X509NameEntryConverter converter)
- {
- this.converter = converter;
-
- if (oids.Count != values.Count)
- {
- throw new ArgumentException("'oids' must be same length as 'values'.");
- }
-
- for (int i = 0; i < oids.Count; i++)
- {
- this.ordering.Add(oids[i]);
- this.values.Add(values[i]);
- this.added.Add(false);
- }
- }
-
-// private static bool IsEncoded(
-// string s)
-// {
-// return s.StartsWith("#");
-// }
-
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes.
- */
- public X509Name(
- string dirName)
- : this(DefaultReverse, DefaultLookup, dirName)
- {
- }
-
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes with each
- * string value being converted to its associated ASN.1 type using the passed
- * in converter.
- */
- public X509Name(
- string dirName,
- X509NameEntryConverter converter)
- : this(DefaultReverse, DefaultLookup, dirName, converter)
- {
- }
-
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes. If reverse
- * is true, create the encoded version of the sequence starting from the
- * last element in the string.
- */
- public X509Name(
- bool reverse,
- string dirName)
- : this(reverse, DefaultLookup, dirName)
- {
- }
-
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes with each
- * string value being converted to its associated ASN.1 type using the passed
- * in converter. If reverse is true the ASN.1 sequence representing the DN will
- * be built by starting at the end of the string, rather than the start.
- */
- public X509Name(
- bool reverse,
- string dirName,
- X509NameEntryConverter converter)
- : this(reverse, DefaultLookup, dirName, converter)
- {
- }
-
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes. lookUp
- * should provide a table of lookups, indexed by lowercase only strings and
- * yielding a DerObjectIdentifier, other than that OID. and numeric oids
- * will be processed automatically.
- *
- * If reverse is true, create the encoded version of the sequence
- * starting from the last element in the string.
- * @param reverse true if we should start scanning from the end (RFC 2553).
- * @param lookUp table of names and their oids.
- * @param dirName the X.500 string to be parsed.
- */
- public X509Name(
- bool reverse,
- Hashtable lookUp,
- string dirName)
- : this(reverse, lookUp, dirName, new X509DefaultEntryConverter())
- {
- }
-
- private DerObjectIdentifier DecodeOid(
- string name,
- IDictionary lookUp)
- {
- if (name.ToUpper(CultureInfo.InvariantCulture).StartsWith("OID."))
- {
- return new DerObjectIdentifier(name.Substring(4));
- }
- else if (name[0] >= '0' && name[0] <= '9')
- {
- return new DerObjectIdentifier(name);
- }
-
- DerObjectIdentifier oid = (DerObjectIdentifier)lookUp[name.ToLower(CultureInfo.InvariantCulture)];
- if (oid == null)
- {
- throw new ArgumentException("Unknown object id - " + name + " - passed to distinguished name");
- }
-
- return oid;
- }
-
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes. lookUp
- * should provide a table of lookups, indexed by lowercase only strings and
- * yielding a DerObjectIdentifier, other than that OID. and numeric oids
- * will be processed automatically. The passed in converter is used to convert the
- * string values to the right of each equals sign to their ASN.1 counterparts.
- *
- * @param reverse true if we should start scanning from the end, false otherwise.
- * @param lookUp table of names and oids.
- * @param dirName the string dirName
- * @param converter the converter to convert string values into their ASN.1 equivalents
- */
- public X509Name(
- bool reverse,
- IDictionary lookUp,
- string dirName,
- X509NameEntryConverter converter)
- {
- this.converter = converter;
- X509NameTokenizer nTok = new X509NameTokenizer(dirName);
-
- while (nTok.HasMoreTokens())
- {
- string token = nTok.NextToken();
- int index = token.IndexOf('=');
-
- if (index == -1)
- {
- throw new ArgumentException("badly formated directory string");
- }
-
- string name = token.Substring(0, index);
- string value = token.Substring(index + 1);
- DerObjectIdentifier oid = DecodeOid(name, lookUp);
-
- if (value.IndexOf('+') > 0)
- {
- X509NameTokenizer vTok = new X509NameTokenizer(value, '+');
- string v = vTok.NextToken();
-
- this.ordering.Add(oid);
- this.values.Add(v);
- this.added.Add(false);
-
- while (vTok.HasMoreTokens())
- {
- string sv = vTok.NextToken();
- int ndx = sv.IndexOf('=');
-
- string nm = sv.Substring(0, ndx);
- string vl = sv.Substring(ndx + 1);
- this.ordering.Add(DecodeOid(nm, lookUp));
- this.values.Add(vl);
- this.added.Add(true);
- }
- }
- else
- {
- this.ordering.Add(oid);
- this.values.Add(value);
- this.added.Add(false);
- }
- }
-
- if (reverse)
- {
-// this.ordering.Reverse();
-// this.values.Reverse();
-// this.added.Reverse();
- ArrayList o = new ArrayList();
- ArrayList v = new ArrayList();
- ArrayList a = new ArrayList();
- int count = 1;
-
- for (int i = 0; i < this.ordering.Count; i++)
- {
- if (!((bool) this.added[i]))
- {
- count = 0;
- }
-
- int index = count++;
-
- o.Insert(index, this.ordering[i]);
- v.Insert(index, this.values[i]);
- a.Insert(index, this.added[i]);
- }
-
- this.ordering = o;
- this.values = v;
- this.added = a;
- }
- }
-
- /**
- * return an ArrayList of the oids in the name, in the order they were found.
- */
- public ArrayList GetOids()
- {
- return (ArrayList) ordering.Clone();
- }
-
- /**
- * return an ArrayList of the values found in the name, in the order they
- * were found.
- */
- public ArrayList GetValues()
- {
- return (ArrayList) values.Clone();
- }
-
- /**
- * return an ArrayList of the values found in the name, in the order they
- * were found, with the DN label corresponding to passed in oid.
- */
- public ArrayList GetValues(
- DerObjectIdentifier oid)
- {
- ArrayList v = new ArrayList();
-
- for (int i = 0; i != values.Count; i++)
- {
- if (ordering[i].Equals(oid))
- {
- string val = (string)values[i];
-
- if (val.StartsWith("\\#"))
- {
- val = val.Substring(1);
- }
-
- v.Add(val);
- }
- }
-
- return v;
- }
-
- public override Asn1Object ToAsn1Object()
- {
- if (seq == null)
- {
- Asn1EncodableVector vec = new Asn1EncodableVector();
- Asn1EncodableVector sVec = new Asn1EncodableVector();
- DerObjectIdentifier lstOid = null;
-
- for (int i = 0; i != ordering.Count; i++)
- {
- DerObjectIdentifier oid = (DerObjectIdentifier)ordering[i];
- string str = (string)values[i];
-
- if (lstOid == null
- || ((bool)this.added[i]))
- {
- }
- else
- {
- vec.Add(new DerSet(sVec));
- sVec = new Asn1EncodableVector();
- }
-
- sVec.Add(
- new DerSequence(
- oid,
- converter.GetConvertedValue(oid, str)));
-
- lstOid = oid;
- }
-
- vec.Add(new DerSet(sVec));
-
- seq = new DerSequence(vec);
- }
-
- return seq;
- }
-
- [Obsolete("Use 'Equivalent(X509Name, int)' instead")]
- public bool Equals(
- X509Name other,
- bool inOrder)
- {
- return Equivalent(other, inOrder);
- }
-
- /// The X509Name object to test equivalency against.
- /// If true, the order of elements must be the same,
- /// as well as the values associated with each element.
- public bool Equivalent(
- X509Name other,
- bool inOrder)
- {
- if (!inOrder)
- return this.Equivalent(other);
-
- if (other == null)
- return false;
-
- if (other == this)
- return true;
-
- int orderingSize = ordering.Count;
-
- if (orderingSize != other.ordering.Count)
- return false;
-
- for (int i = 0; i < orderingSize; i++)
- {
- DerObjectIdentifier oid = (DerObjectIdentifier) ordering[i];
- DerObjectIdentifier oOid = (DerObjectIdentifier) other.ordering[i];
-
- if (!oid.Equals(oOid))
- return false;
-
- string val = (string) values[i];
- string oVal = (string) other.values[i];
-
- if (!equivalentStrings(val, oVal))
- return false;
- }
-
- return true;
- }
-
- [Obsolete("Use 'Equivalent(X509Name)' instead")]
- public bool Equals(
- X509Name other)
- {
- return Equivalent(other);
- }
-
- /**
- * test for equivalence - note: case is ignored.
- */
- public bool Equivalent(
- X509Name other)
- {
- if (other == null)
- return false;
-
- if (other == this)
- return true;
-
- int orderingSize = ordering.Count;
-
- if (orderingSize != other.ordering.Count)
- {
- return false;
- }
-
- bool[] indexes = new bool[orderingSize];
- int start, end, delta;
-
- if (ordering[0].Equals(other.ordering[0])) // guess forward
- {
- start = 0;
- end = orderingSize;
- delta = 1;
- }
- else // guess reversed - most common problem
- {
- start = orderingSize - 1;
- end = -1;
- delta = -1;
- }
-
- for (int i = start; i != end; i += delta)
- {
- bool found = false;
- DerObjectIdentifier oid = (DerObjectIdentifier)ordering[i];
- string value = (string)values[i];
-
- for (int j = 0; j < orderingSize; j++)
- {
- if (indexes[j])
- {
- continue;
- }
-
- DerObjectIdentifier oOid = (DerObjectIdentifier)other.ordering[j];
-
- if (oid.Equals(oOid))
- {
- string oValue = (string)other.values[j];
-
- if (equivalentStrings(value, oValue))
- {
- indexes[j] = true;
- found = true;
- break;
- }
- }
- }
-
- if (!found)
- {
- return false;
- }
- }
-
- return true;
- }
-
- private bool equivalentStrings(
- string s1,
- string s2)
- {
- string value = s1.ToLower(CultureInfo.InvariantCulture).Trim();
- string oValue = s2.ToLower(CultureInfo.InvariantCulture).Trim();
-
- if (!value.Equals(oValue))
- {
- value = stripInternalSpaces(value);
- oValue = stripInternalSpaces(oValue);
-
- if (!value.Equals(oValue))
- {
- return false;
- }
- }
-
- return true;
- }
-
- private string stripInternalSpaces(
- string str)
- {
- StringBuilder res = new StringBuilder();
-
- if (str.Length != 0)
- {
- char c1 = str[0];
-
- res.Append(c1);
-
- for (int k = 1; k < str.Length; k++)
- {
- char c2 = str[k];
- if (!(c1 == ' ' && c2 == ' '))
- {
- res.Append(c2);
- }
- c1 = c2;
- }
- }
-
- return res.ToString();
- }
-
- private void AppendValue(
- StringBuilder buf,
- Hashtable oidSymbols,
- DerObjectIdentifier oid,
- string val)
- {
- string sym = (string) oidSymbols[oid];
-
- if (sym != null)
- {
- buf.Append(sym);
- }
- else
- {
- buf.Append(oid.Id);
- }
-
- buf.Append('=');
-
- int index = buf.Length;
-
- buf.Append(val);
-
- int end = buf.Length;
-
- if (val.StartsWith("\\#"))
- {
- index += 2;
- }
-
- while (index != end)
- {
- if ((buf[index] == ',')
- || (buf[index] == '"')
- || (buf[index] == '\\')
- || (buf[index] == '+')
- || (buf[index] == '<')
- || (buf[index] == '>')
- || (buf[index] == ';'))
- {
- buf.Insert(index++, "\\");
- end++;
- }
-
- index++;
- }
- }
-
- /**
- * convert the structure to a string - if reverse is true the
- * oids and values are listed out starting with the last element
- * in the sequence (ala RFC 2253), otherwise the string will begin
- * with the first element of the structure. If no string definition
- * for the oid is found in oidSymbols the string value of the oid is
- * added. Two standard symbol tables are provided DefaultSymbols, and
- * RFC2253Symbols as part of this class.
- *
- * @param reverse if true start at the end of the sequence and work back.
- * @param oidSymbols look up table strings for oids.
- */
- public string ToString(
- bool reverse,
- Hashtable oidSymbols)
- {
- ArrayList components = new ArrayList();
-
- StringBuilder ava = null;
-
- for (int i = 0; i < ordering.Count; i++)
- {
- if ((bool) added[i])
- {
- ava.Append('+');
- AppendValue(ava, oidSymbols,
- (DerObjectIdentifier)ordering[i],
- (string)values[i]);
- }
- else
- {
- ava = new StringBuilder();
- AppendValue(ava, oidSymbols,
- (DerObjectIdentifier)ordering[i],
- (string)values[i]);
- components.Add(ava);
- }
- }
-
- if (reverse)
- {
- components.Reverse();
- }
-
- StringBuilder buf = new StringBuilder();
-
- if (components.Count > 0)
- {
- buf.Append(components[0].ToString());
-
- for (int i = 1; i < components.Count; ++i)
- {
- buf.Append(',');
- buf.Append(components[i].ToString());
- }
- }
-
- return buf.ToString();
- }
-
- public override string ToString()
- {
- return ToString(DefaultReverse, DefaultSymbols);
- }
- }
-}
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ *
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ *
+ * RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type OBJECT IDENTIFIER,
+ * value ANY }
+ *
+ */
+ public class X509Name
+ : Asn1Encodable
+ {
+ /**
+ * country code - StringType(SIZE(2))
+ */
+ public static readonly DerObjectIdentifier C = new DerObjectIdentifier("2.5.4.6");
+
+ /**
+ * organization - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier O = new DerObjectIdentifier("2.5.4.10");
+
+ /**
+ * organizational unit name - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier OU = new DerObjectIdentifier("2.5.4.11");
+
+ /**
+ * Title
+ */
+ public static readonly DerObjectIdentifier T = new DerObjectIdentifier("2.5.4.12");
+
+ /**
+ * common name - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier CN = new DerObjectIdentifier("2.5.4.3");
+
+ /**
+ * street - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier Street = new DerObjectIdentifier("2.5.4.9");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier SerialNumber = new DerObjectIdentifier("2.5.4.5");
+
+ /**
+ * locality name - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier L = new DerObjectIdentifier("2.5.4.7");
+
+ /**
+ * state, or province name - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier ST = new DerObjectIdentifier("2.5.4.8");
+
+ /**
+ * Naming attributes of type X520name
+ */
+ public static readonly DerObjectIdentifier Surname = new DerObjectIdentifier("2.5.4.4");
+ public static readonly DerObjectIdentifier GivenName = new DerObjectIdentifier("2.5.4.42");
+ public static readonly DerObjectIdentifier Initials = new DerObjectIdentifier("2.5.4.43");
+ public static readonly DerObjectIdentifier Generation = new DerObjectIdentifier("2.5.4.44");
+ public static readonly DerObjectIdentifier UniqueIdentifier = new DerObjectIdentifier("2.5.4.45");
+
+ /**
+ * businessCategory - DirectoryString(SIZE(1..128)
+ */
+ public static readonly DerObjectIdentifier BusinessCategory = new DerObjectIdentifier(
+ "2.5.4.15");
+
+ /**
+ * postalCode - DirectoryString(SIZE(1..40)
+ */
+ public static readonly DerObjectIdentifier PostalCode = new DerObjectIdentifier(
+ "2.5.4.17");
+
+ /**
+ * dnQualifier - DirectoryString(SIZE(1..64)
+ */
+ public static readonly DerObjectIdentifier DnQualifier = new DerObjectIdentifier(
+ "2.5.4.46");
+
+ /**
+ * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
+ */
+ public static readonly DerObjectIdentifier Pseudonym = new DerObjectIdentifier(
+ "2.5.4.65");
+
+ /**
+ * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
+ */
+ public static readonly DerObjectIdentifier DateOfBirth = new DerObjectIdentifier(
+ "1.3.6.1.5.5.7.9.1");
+
+ /**
+ * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
+ */
+ public static readonly DerObjectIdentifier PlaceOfBirth = new DerObjectIdentifier(
+ "1.3.6.1.5.5.7.9.2");
+
+ /**
+ * RFC 3039 DateOfBirth - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
+ */
+ public static readonly DerObjectIdentifier Gender = new DerObjectIdentifier(
+ "1.3.6.1.5.5.7.9.3");
+
+ /**
+ * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static readonly DerObjectIdentifier CountryOfCitizenship = new DerObjectIdentifier(
+ "1.3.6.1.5.5.7.9.4");
+
+ /**
+ * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static readonly DerObjectIdentifier CountryOfResidence = new DerObjectIdentifier(
+ "1.3.6.1.5.5.7.9.5");
+
+ /**
+ * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
+ */
+ public static readonly DerObjectIdentifier NameAtBirth = new DerObjectIdentifier("1.3.36.8.3.14");
+
+ /**
+ * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
+ * DirectoryString(SIZE(1..30))
+ */
+ public static readonly DerObjectIdentifier PostalAddress = new DerObjectIdentifier("2.5.4.16");
+
+ /**
+ * id-at-telephoneNumber
+ */
+ public static readonly DerObjectIdentifier TelephoneNumber = new DerObjectIdentifier("2.5.4.20");
+
+ /**
+ * Email address (RSA PKCS#9 extension) - IA5String.
+ * Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
+ */
+ public static readonly DerObjectIdentifier EmailAddress = PkcsObjectIdentifiers.Pkcs9AtEmailAddress;
+
+ /**
+ * more from PKCS#9
+ */
+ public static readonly DerObjectIdentifier UnstructuredName = PkcsObjectIdentifiers.Pkcs9AtUnstructuredName;
+ public static readonly DerObjectIdentifier UnstructuredAddress = PkcsObjectIdentifiers.Pkcs9AtUnstructuredAddress;
+
+ /**
+ * email address in Verisign certificates
+ */
+ public static readonly DerObjectIdentifier E = EmailAddress;
+
+ /*
+ * others...
+ */
+ public static readonly DerObjectIdentifier DC = new DerObjectIdentifier("0.9.2342.19200300.100.1.25");
+
+ /**
+ * LDAP User id.
+ */
+ public static readonly DerObjectIdentifier UID = new DerObjectIdentifier("0.9.2342.19200300.100.1.1");
+
+ /**
+ * determines whether or not strings should be processed and printed
+ * from back to front.
+ */
+// public static bool DefaultReverse = false;
+ public static bool DefaultReverse
+ {
+ get { return defaultReverse[0]; }
+ set { defaultReverse[0] = value; }
+ }
+
+ private static readonly bool[] defaultReverse = { false };
+
+ /**
+ * default look up table translating OID values into their common symbols following
+ * the convention in RFC 2253 with a few extras
+ */
+ public static readonly Hashtable DefaultSymbols = new Hashtable();
+
+ /**
+ * look up table translating OID values into their common symbols following the convention in RFC 2253
+ */
+ public static readonly Hashtable RFC2253Symbols = new Hashtable();
+
+ /**
+ * look up table translating OID values into their common symbols following the convention in RFC 1779
+ *
+ */
+ public static readonly Hashtable RFC1779Symbols = new Hashtable();
+
+ /**
+ * look up table translating common symbols into their OIDS.
+ */
+ public static readonly Hashtable DefaultLookup = new Hashtable();
+
+ /**
+ * look up table translating OID values into their common symbols.
+ */
+ [Obsolete("Use 'DefaultSymbols' instead")]
+ public static readonly Hashtable OIDLookup = DefaultSymbols;
+
+ /**
+ * look up table translating string values into their OIDS -
+ * this static is scheduled for deletion
+ */
+ [Obsolete("Use 'DefaultLookup' instead")]
+ public static readonly Hashtable SymbolLookup = DefaultLookup;
+
+ static X509Name()
+ {
+ DefaultSymbols.Add(C, "C");
+ DefaultSymbols.Add(O, "O");
+ DefaultSymbols.Add(T, "T");
+ DefaultSymbols.Add(OU, "OU");
+ DefaultSymbols.Add(CN, "CN");
+ DefaultSymbols.Add(L, "L");
+ DefaultSymbols.Add(ST, "ST");
+ DefaultSymbols.Add(SerialNumber, "SERIALNUMBER");
+ DefaultSymbols.Add(EmailAddress, "E");
+ DefaultSymbols.Add(DC, "DC");
+ DefaultSymbols.Add(UID, "UID");
+ DefaultSymbols.Add(Street, "STREET");
+ DefaultSymbols.Add(Surname, "SURNAME");
+ DefaultSymbols.Add(GivenName, "GIVENNAME");
+ DefaultSymbols.Add(Initials, "INITIALS");
+ DefaultSymbols.Add(Generation, "GENERATION");
+ DefaultSymbols.Add(UnstructuredAddress, "unstructuredAddress");
+ DefaultSymbols.Add(UnstructuredName, "unstructuredName");
+ DefaultSymbols.Add(UniqueIdentifier, "UniqueIdentifier");
+ DefaultSymbols.Add(DnQualifier, "DN");
+ DefaultSymbols.Add(Pseudonym, "Pseudonym");
+ DefaultSymbols.Add(PostalAddress, "PostalAddress");
+ DefaultSymbols.Add(NameAtBirth, "NameAtBirth");
+ DefaultSymbols.Add(CountryOfCitizenship, "CountryOfCitizenship");
+ DefaultSymbols.Add(CountryOfResidence, "CountryOfResidence");
+ DefaultSymbols.Add(Gender, "Gender");
+ DefaultSymbols.Add(PlaceOfBirth, "PlaceOfBirth");
+ DefaultSymbols.Add(DateOfBirth, "DateOfBirth");
+ DefaultSymbols.Add(PostalCode, "PostalCode");
+ DefaultSymbols.Add(BusinessCategory, "BusinessCategory");
+ DefaultSymbols.Add(TelephoneNumber, "TelephoneNumber");
+
+ RFC2253Symbols.Add(C, "C");
+ RFC2253Symbols.Add(O, "O");
+ RFC2253Symbols.Add(OU, "OU");
+ RFC2253Symbols.Add(CN, "CN");
+ RFC2253Symbols.Add(L, "L");
+ RFC2253Symbols.Add(ST, "ST");
+ RFC2253Symbols.Add(Street, "STREET");
+ RFC2253Symbols.Add(DC, "DC");
+ RFC2253Symbols.Add(UID, "UID");
+
+ RFC1779Symbols.Add(C, "C");
+ RFC1779Symbols.Add(O, "O");
+ RFC1779Symbols.Add(OU, "OU");
+ RFC1779Symbols.Add(CN, "CN");
+ RFC1779Symbols.Add(L, "L");
+ RFC1779Symbols.Add(ST, "ST");
+ RFC1779Symbols.Add(Street, "STREET");
+
+ DefaultLookup.Add("c", C);
+ DefaultLookup.Add("o", O);
+ DefaultLookup.Add("t", T);
+ DefaultLookup.Add("ou", OU);
+ DefaultLookup.Add("cn", CN);
+ DefaultLookup.Add("l", L);
+ DefaultLookup.Add("st", ST);
+ DefaultLookup.Add("serialnumber", SerialNumber);
+ DefaultLookup.Add("street", Street);
+ DefaultLookup.Add("emailaddress", E);
+ DefaultLookup.Add("dc", DC);
+ DefaultLookup.Add("e", E);
+ DefaultLookup.Add("uid", UID);
+ DefaultLookup.Add("surname", Surname);
+ DefaultLookup.Add("givenname", GivenName);
+ DefaultLookup.Add("initials", Initials);
+ DefaultLookup.Add("generation", Generation);
+ DefaultLookup.Add("unstructuredaddress", UnstructuredAddress);
+ DefaultLookup.Add("unstructuredname", UnstructuredName);
+ DefaultLookup.Add("uniqueidentifier", UniqueIdentifier);
+ DefaultLookup.Add("dn", DnQualifier);
+ DefaultLookup.Add("pseudonym", Pseudonym);
+ DefaultLookup.Add("postaladdress", PostalAddress);
+ DefaultLookup.Add("nameofbirth", NameAtBirth);
+ DefaultLookup.Add("countryofcitizenship", CountryOfCitizenship);
+ DefaultLookup.Add("countryofresidence", CountryOfResidence);
+ DefaultLookup.Add("gender", Gender);
+ DefaultLookup.Add("placeofbirth", PlaceOfBirth);
+ DefaultLookup.Add("dateofbirth", DateOfBirth);
+ DefaultLookup.Add("postalcode", PostalCode);
+ DefaultLookup.Add("businesscategory", BusinessCategory);
+ DefaultLookup.Add("telephonenumber", TelephoneNumber);
+ }
+
+ private readonly ArrayList ordering = new ArrayList();
+ private readonly X509NameEntryConverter converter;
+
+ private ArrayList values = new ArrayList();
+ private ArrayList added = new ArrayList();
+ private Asn1Sequence seq;
+
+ /**
+ * Return a X509Name based on the passed in tagged object.
+ *
+ * @param obj tag object holding name.
+ * @param explicitly true if explicitly tagged false otherwise.
+ * @return the X509Name
+ */
+ public static X509Name GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static X509Name GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is X509Name)
+ {
+ return (X509Name) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new X509Name((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name);
+ }
+
+ /**
+ * Constructor from Asn1Sequence
+ *
+ * the principal will be a list of constructed sets, each containing an (OID, string) pair.
+ */
+ protected X509Name(
+ Asn1Sequence seq)
+ {
+ this.seq = seq;
+
+ foreach (Asn1Encodable asn1Obj in seq)
+ {
+ Asn1Set asn1Set = Asn1Set.GetInstance(asn1Obj.ToAsn1Object());
+
+ for (int i = 0; i < asn1Set.Count; i++)
+ {
+ Asn1Sequence s = Asn1Sequence.GetInstance(asn1Set[i].ToAsn1Object());
+
+ if (s.Count != 2)
+ throw new ArgumentException("badly sized pair");
+
+ ordering.Add(DerObjectIdentifier.GetInstance(s[0].ToAsn1Object()));
+
+ Asn1Object derValue = s[1].ToAsn1Object();
+ if (derValue is IAsn1String && !(derValue is DerUniversalString))
+ {
+ string v = ((IAsn1String)derValue).GetString();
+ if (v.StartsWith("#"))
+ {
+ v = "\\" + v;
+ }
+
+ values.Add(v);
+ }
+ else
+ {
+ byte[] hex = Hex.Encode(derValue.GetEncoded());
+ values.Add("#" + Encoding.ASCII.GetString(hex, 0, hex.Length));
+ }
+
+ added.Add(i != 0);
+ }
+ }
+ }
+
+ /**
+ * Constructor from a table of attributes with ordering.
+ *
+ * it's is assumed the table contains OID/string pairs, and the contents
+ * of the table are copied into an internal table as part of the
+ * construction process. The ordering ArrayList should contain the OIDs
+ * in the order they are meant to be encoded or printed in ToString.
+ */
+ public X509Name(
+ ArrayList ordering,
+ Hashtable attributes)
+ : this(ordering, attributes, new X509DefaultEntryConverter())
+ {
+ }
+
+ /**
+ * Constructor from a table of attributes with ordering.
+ *
+ * it's is assumed the table contains OID/string pairs, and the contents
+ * of the table are copied into an internal table as part of the
+ * construction process. The ordering ArrayList should contain the OIDs
+ * in the order they are meant to be encoded or printed in ToString.
+ *
+ * The passed in converter will be used to convert the strings into their
+ * ASN.1 counterparts.
+ */
+ public X509Name(
+ ArrayList ordering,
+ Hashtable attributes,
+ X509NameEntryConverter converter)
+ {
+ this.converter = converter;
+
+ foreach (DerObjectIdentifier oid in ordering)
+ {
+ object attribute = attributes[oid];
+ if (attribute == null)
+ {
+ throw new ArgumentException("No attribute for object id - " + oid + " - passed to distinguished name");
+ }
+
+ this.ordering.Add(oid);
+ this.added.Add(false);
+ this.values.Add(attribute); // copy the hash table
+ }
+ }
+
+ /**
+ * Takes two vectors one of the oids and the other of the values.
+ */
+ public X509Name(
+ ArrayList oids,
+ ArrayList values)
+ : this(oids, values, new X509DefaultEntryConverter())
+ {
+ }
+
+ /**
+ * Takes two vectors one of the oids and the other of the values.
+ *
+ * The passed in converter will be used to convert the strings into their
+ * ASN.1 counterparts.
+ */
+ public X509Name(
+ ArrayList oids,
+ ArrayList values,
+ X509NameEntryConverter converter)
+ {
+ this.converter = converter;
+
+ if (oids.Count != values.Count)
+ {
+ throw new ArgumentException("'oids' must be same length as 'values'.");
+ }
+
+ for (int i = 0; i < oids.Count; i++)
+ {
+ this.ordering.Add(oids[i]);
+ this.values.Add(values[i]);
+ this.added.Add(false);
+ }
+ }
+
+// private static bool IsEncoded(
+// string s)
+// {
+// return s.StartsWith("#");
+// }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes.
+ */
+ public X509Name(
+ string dirName)
+ : this(DefaultReverse, DefaultLookup, dirName)
+ {
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes with each
+ * string value being converted to its associated ASN.1 type using the passed
+ * in converter.
+ */
+ public X509Name(
+ string dirName,
+ X509NameEntryConverter converter)
+ : this(DefaultReverse, DefaultLookup, dirName, converter)
+ {
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes. If reverse
+ * is true, create the encoded version of the sequence starting from the
+ * last element in the string.
+ */
+ public X509Name(
+ bool reverse,
+ string dirName)
+ : this(reverse, DefaultLookup, dirName)
+ {
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes with each
+ * string value being converted to its associated ASN.1 type using the passed
+ * in converter. If reverse is true the ASN.1 sequence representing the DN will
+ * be built by starting at the end of the string, rather than the start.
+ */
+ public X509Name(
+ bool reverse,
+ string dirName,
+ X509NameEntryConverter converter)
+ : this(reverse, DefaultLookup, dirName, converter)
+ {
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes. lookUp
+ * should provide a table of lookups, indexed by lowercase only strings and
+ * yielding a DerObjectIdentifier, other than that OID. and numeric oids
+ * will be processed automatically.
+ *
+ * If reverse is true, create the encoded version of the sequence
+ * starting from the last element in the string.
+ * @param reverse true if we should start scanning from the end (RFC 2553).
+ * @param lookUp table of names and their oids.
+ * @param dirName the X.500 string to be parsed.
+ */
+ public X509Name(
+ bool reverse,
+ Hashtable lookUp,
+ string dirName)
+ : this(reverse, lookUp, dirName, new X509DefaultEntryConverter())
+ {
+ }
+
+ private DerObjectIdentifier DecodeOid(
+ string name,
+ IDictionary lookUp)
+ {
+ if (name.ToUpper(CultureInfo.InvariantCulture).StartsWith("OID."))
+ {
+ return new DerObjectIdentifier(name.Substring(4));
+ }
+ else if (name[0] >= '0' && name[0] <= '9')
+ {
+ return new DerObjectIdentifier(name);
+ }
+
+ DerObjectIdentifier oid = (DerObjectIdentifier)lookUp[name.ToLower(CultureInfo.InvariantCulture)];
+ if (oid == null)
+ {
+ throw new ArgumentException("Unknown object id - " + name + " - passed to distinguished name");
+ }
+
+ return oid;
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes. lookUp
+ * should provide a table of lookups, indexed by lowercase only strings and
+ * yielding a DerObjectIdentifier, other than that OID. and numeric oids
+ * will be processed automatically. The passed in converter is used to convert the
+ * string values to the right of each equals sign to their ASN.1 counterparts.
+ *
+ * @param reverse true if we should start scanning from the end, false otherwise.
+ * @param lookUp table of names and oids.
+ * @param dirName the string dirName
+ * @param converter the converter to convert string values into their ASN.1 equivalents
+ */
+ public X509Name(
+ bool reverse,
+ IDictionary lookUp,
+ string dirName,
+ X509NameEntryConverter converter)
+ {
+ this.converter = converter;
+ X509NameTokenizer nTok = new X509NameTokenizer(dirName);
+
+ while (nTok.HasMoreTokens())
+ {
+ string token = nTok.NextToken();
+ int index = token.IndexOf('=');
+
+ if (index == -1)
+ {
+ throw new ArgumentException("badly formated directory string");
+ }
+
+ string name = token.Substring(0, index);
+ string value = token.Substring(index + 1);
+ DerObjectIdentifier oid = DecodeOid(name, lookUp);
+
+ if (value.IndexOf('+') > 0)
+ {
+ X509NameTokenizer vTok = new X509NameTokenizer(value, '+');
+ string v = vTok.NextToken();
+
+ this.ordering.Add(oid);
+ this.values.Add(v);
+ this.added.Add(false);
+
+ while (vTok.HasMoreTokens())
+ {
+ string sv = vTok.NextToken();
+ int ndx = sv.IndexOf('=');
+
+ string nm = sv.Substring(0, ndx);
+ string vl = sv.Substring(ndx + 1);
+ this.ordering.Add(DecodeOid(nm, lookUp));
+ this.values.Add(vl);
+ this.added.Add(true);
+ }
+ }
+ else
+ {
+ this.ordering.Add(oid);
+ this.values.Add(value);
+ this.added.Add(false);
+ }
+ }
+
+ if (reverse)
+ {
+// this.ordering.Reverse();
+// this.values.Reverse();
+// this.added.Reverse();
+ ArrayList o = new ArrayList();
+ ArrayList v = new ArrayList();
+ ArrayList a = new ArrayList();
+ int count = 1;
+
+ for (int i = 0; i < this.ordering.Count; i++)
+ {
+ if (!((bool) this.added[i]))
+ {
+ count = 0;
+ }
+
+ int index = count++;
+
+ o.Insert(index, this.ordering[i]);
+ v.Insert(index, this.values[i]);
+ a.Insert(index, this.added[i]);
+ }
+
+ this.ordering = o;
+ this.values = v;
+ this.added = a;
+ }
+ }
+
+ /**
+ * return an ArrayList of the oids in the name, in the order they were found.
+ */
+ public ArrayList GetOids()
+ {
+ return (ArrayList) ordering.Clone();
+ }
+
+ /**
+ * return an ArrayList of the values found in the name, in the order they
+ * were found.
+ */
+ public ArrayList GetValues()
+ {
+ return (ArrayList) values.Clone();
+ }
+
+ /**
+ * return an ArrayList of the values found in the name, in the order they
+ * were found, with the DN label corresponding to passed in oid.
+ */
+ public ArrayList GetValues(
+ DerObjectIdentifier oid)
+ {
+ ArrayList v = new ArrayList();
+
+ for (int i = 0; i != values.Count; i++)
+ {
+ if (ordering[i].Equals(oid))
+ {
+ string val = (string)values[i];
+
+ if (val.StartsWith("\\#"))
+ {
+ val = val.Substring(1);
+ }
+
+ v.Add(val);
+ }
+ }
+
+ return v;
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ if (seq == null)
+ {
+ Asn1EncodableVector vec = new Asn1EncodableVector();
+ Asn1EncodableVector sVec = new Asn1EncodableVector();
+ DerObjectIdentifier lstOid = null;
+
+ for (int i = 0; i != ordering.Count; i++)
+ {
+ DerObjectIdentifier oid = (DerObjectIdentifier)ordering[i];
+ string str = (string)values[i];
+
+ if (lstOid == null
+ || ((bool)this.added[i]))
+ {
+ }
+ else
+ {
+ vec.Add(new DerSet(sVec));
+ sVec = new Asn1EncodableVector();
+ }
+
+ sVec.Add(
+ new DerSequence(
+ oid,
+ converter.GetConvertedValue(oid, str)));
+
+ lstOid = oid;
+ }
+
+ vec.Add(new DerSet(sVec));
+
+ seq = new DerSequence(vec);
+ }
+
+ return seq;
+ }
+
+ [Obsolete("Use 'Equivalent(X509Name, int)' instead")]
+ public bool Equals(
+ X509Name other,
+ bool inOrder)
+ {
+ return Equivalent(other, inOrder);
+ }
+
+ /// The X509Name object to test equivalency against.
+ /// If true, the order of elements must be the same,
+ /// as well as the values associated with each element.
+ public bool Equivalent(
+ X509Name other,
+ bool inOrder)
+ {
+ if (!inOrder)
+ return this.Equivalent(other);
+
+ if (other == null)
+ return false;
+
+ if (other == this)
+ return true;
+
+ int orderingSize = ordering.Count;
+
+ if (orderingSize != other.ordering.Count)
+ return false;
+
+ for (int i = 0; i < orderingSize; i++)
+ {
+ DerObjectIdentifier oid = (DerObjectIdentifier) ordering[i];
+ DerObjectIdentifier oOid = (DerObjectIdentifier) other.ordering[i];
+
+ if (!oid.Equals(oOid))
+ return false;
+
+ string val = (string) values[i];
+ string oVal = (string) other.values[i];
+
+ if (!equivalentStrings(val, oVal))
+ return false;
+ }
+
+ return true;
+ }
+
+ [Obsolete("Use 'Equivalent(X509Name)' instead")]
+ public bool Equals(
+ X509Name other)
+ {
+ return Equivalent(other);
+ }
+
+ /**
+ * test for equivalence - note: case is ignored.
+ */
+ public bool Equivalent(
+ X509Name other)
+ {
+ if (other == null)
+ return false;
+
+ if (other == this)
+ return true;
+
+ int orderingSize = ordering.Count;
+
+ if (orderingSize != other.ordering.Count)
+ {
+ return false;
+ }
+
+ bool[] indexes = new bool[orderingSize];
+ int start, end, delta;
+
+ if (ordering[0].Equals(other.ordering[0])) // guess forward
+ {
+ start = 0;
+ end = orderingSize;
+ delta = 1;
+ }
+ else // guess reversed - most common problem
+ {
+ start = orderingSize - 1;
+ end = -1;
+ delta = -1;
+ }
+
+ for (int i = start; i != end; i += delta)
+ {
+ bool found = false;
+ DerObjectIdentifier oid = (DerObjectIdentifier)ordering[i];
+ string value = (string)values[i];
+
+ for (int j = 0; j < orderingSize; j++)
+ {
+ if (indexes[j])
+ {
+ continue;
+ }
+
+ DerObjectIdentifier oOid = (DerObjectIdentifier)other.ordering[j];
+
+ if (oid.Equals(oOid))
+ {
+ string oValue = (string)other.values[j];
+
+ if (equivalentStrings(value, oValue))
+ {
+ indexes[j] = true;
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool equivalentStrings(
+ string s1,
+ string s2)
+ {
+ string v1 = canonicalize(s1);
+ string v2 = canonicalize(s2);
+
+ if (!v1.Equals(v2))
+ {
+ v1 = stripInternalSpaces(v1);
+ v2 = stripInternalSpaces(v2);
+
+ if (!v1.Equals(v2))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static string canonicalize(
+ string s)
+ {
+ string v = s.ToLower(CultureInfo.InvariantCulture).Trim();
+
+ if (v.StartsWith("#"))
+ {
+ Asn1Object obj = decodeObject(v);
+
+ if (obj is IAsn1String)
+ {
+ v = ((IAsn1String)obj).GetString().ToLower(CultureInfo.InvariantCulture).Trim();
+ }
+ }
+
+ return v;
+ }
+
+ private static Asn1Object decodeObject(
+ string v)
+ {
+ try
+ {
+ return Asn1Object.FromByteArray(Hex.Decode(v.Substring(1)));
+ }
+ catch (IOException e)
+ {
+ throw new InvalidOperationException("unknown encoding in name: " + e.Message, e);
+ }
+ }
+
+ private static string stripInternalSpaces(
+ string str)
+ {
+ StringBuilder res = new StringBuilder();
+
+ if (str.Length != 0)
+ {
+ char c1 = str[0];
+
+ res.Append(c1);
+
+ for (int k = 1; k < str.Length; k++)
+ {
+ char c2 = str[k];
+ if (!(c1 == ' ' && c2 == ' '))
+ {
+ res.Append(c2);
+ }
+ c1 = c2;
+ }
+ }
+
+ return res.ToString();
+ }
+
+ private void AppendValue(
+ StringBuilder buf,
+ Hashtable oidSymbols,
+ DerObjectIdentifier oid,
+ string val)
+ {
+ string sym = (string) oidSymbols[oid];
+
+ if (sym != null)
+ {
+ buf.Append(sym);
+ }
+ else
+ {
+ buf.Append(oid.Id);
+ }
+
+ buf.Append('=');
+
+ int index = buf.Length;
+
+ buf.Append(val);
+
+ int end = buf.Length;
+
+ if (val.StartsWith("\\#"))
+ {
+ index += 2;
+ }
+
+ while (index != end)
+ {
+ if ((buf[index] == ',')
+ || (buf[index] == '"')
+ || (buf[index] == '\\')
+ || (buf[index] == '+')
+ || (buf[index] == '<')
+ || (buf[index] == '>')
+ || (buf[index] == ';'))
+ {
+ buf.Insert(index++, "\\");
+ end++;
+ }
+
+ index++;
+ }
+ }
+
+ /**
+ * convert the structure to a string - if reverse is true the
+ * oids and values are listed out starting with the last element
+ * in the sequence (ala RFC 2253), otherwise the string will begin
+ * with the first element of the structure. If no string definition
+ * for the oid is found in oidSymbols the string value of the oid is
+ * added. Two standard symbol tables are provided DefaultSymbols, and
+ * RFC2253Symbols as part of this class.
+ *
+ * @param reverse if true start at the end of the sequence and work back.
+ * @param oidSymbols look up table strings for oids.
+ */
+ public string ToString(
+ bool reverse,
+ Hashtable oidSymbols)
+ {
+ ArrayList components = new ArrayList();
+
+ StringBuilder ava = null;
+
+ for (int i = 0; i < ordering.Count; i++)
+ {
+ if ((bool) added[i])
+ {
+ ava.Append('+');
+ AppendValue(ava, oidSymbols,
+ (DerObjectIdentifier)ordering[i],
+ (string)values[i]);
+ }
+ else
+ {
+ ava = new StringBuilder();
+ AppendValue(ava, oidSymbols,
+ (DerObjectIdentifier)ordering[i],
+ (string)values[i]);
+ components.Add(ava);
+ }
+ }
+
+ if (reverse)
+ {
+ components.Reverse();
+ }
+
+ StringBuilder buf = new StringBuilder();
+
+ if (components.Count > 0)
+ {
+ buf.Append(components[0].ToString());
+
+ for (int i = 1; i < components.Count; ++i)
+ {
+ buf.Append(',');
+ buf.Append(components[i].ToString());
+ }
+ }
+
+ return buf.ToString();
+ }
+
+ public override string ToString()
+ {
+ return ToString(DefaultReverse, DefaultSymbols);
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/qualified/Iso4217CurrencyCode.cs b/src/core/srcbc/asn1/x509/qualified/Iso4217CurrencyCode.cs
index d5ea190..3300562 100644
--- a/src/core/srcbc/asn1/x509/qualified/Iso4217CurrencyCode.cs
+++ b/src/core/srcbc/asn1/x509/qualified/Iso4217CurrencyCode.cs
@@ -1,84 +1,84 @@
-using System;
-
-using Org.BouncyCastle.Asn1;
-
-namespace Org.BouncyCastle.Asn1.X509.Qualified
-{
- /**
- * The Iso4217CurrencyCode object.
- *
- * Iso4217CurrencyCode ::= CHOICE {
- * alphabetic PrintableString (SIZE 3), --Recommended
- * numeric INTEGER (1..999) }
- * -- Alphabetic or numeric currency code as defined in ISO 4217
- * -- It is recommended that the Alphabetic form is used
- *
- */
- public class Iso4217CurrencyCode
- : Asn1Encodable
- {
- internal const int AlphabeticMaxSize = 3;
- internal const int NumericMinSize = 1;
- internal const int NumericMaxSize = 999;
-
- internal Asn1Encodable obj;
-// internal int numeric;
-
- public static Iso4217CurrencyCode GetInstance(
- object obj)
- {
- if (obj == null || obj is Iso4217CurrencyCode)
- {
- return (Iso4217CurrencyCode) obj;
- }
-
- if (obj is DerInteger)
- {
- DerInteger numericobj = DerInteger.GetInstance(obj);
- int numeric = numericobj.Value.IntValue;
- return new Iso4217CurrencyCode(numeric);
- }
-
- if (obj is DerPrintableString)
- {
- DerPrintableString alphabetic = DerPrintableString.GetInstance(obj);
- return new Iso4217CurrencyCode(alphabetic.GetString());
- }
-
- throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
- }
-
- public Iso4217CurrencyCode(
- int numeric)
- {
- if (numeric > NumericMaxSize || numeric < NumericMinSize)
- {
- throw new ArgumentException("wrong size in numeric code : not in (" +NumericMinSize +".."+ NumericMaxSize +")");
- }
-
- obj = new DerInteger(numeric);
- }
-
- public Iso4217CurrencyCode(
- string alphabetic)
- {
- if (alphabetic.Length > AlphabeticMaxSize)
- {
- throw new ArgumentException("wrong size in alphabetic code : max size is " + AlphabeticMaxSize);
- }
-
- obj = new DerPrintableString(alphabetic);
- }
-
- public bool IsAlphabetic { get { return obj is DerPrintableString; } }
-
- public string Alphabetic { get { return ((DerPrintableString) obj).GetString(); } }
-
- public int Numeric { get { return ((DerInteger)obj).Value.IntValue; } }
-
- public override Asn1Object ToAsn1Object()
- {
- return obj.ToAsn1Object();
- }
- }
-}
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+ /**
+ * The Iso4217CurrencyCode object.
+ *
+ * Iso4217CurrencyCode ::= CHOICE {
+ * alphabetic PrintableString (SIZE 3), --Recommended
+ * numeric INTEGER (1..999) }
+ * -- Alphabetic or numeric currency code as defined in ISO 4217
+ * -- It is recommended that the Alphabetic form is used
+ *
+ */
+ public class Iso4217CurrencyCode
+ : Asn1Encodable, IAsn1Choice
+ {
+ internal const int AlphabeticMaxSize = 3;
+ internal const int NumericMinSize = 1;
+ internal const int NumericMaxSize = 999;
+
+ internal Asn1Encodable obj;
+// internal int numeric;
+
+ public static Iso4217CurrencyCode GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Iso4217CurrencyCode)
+ {
+ return (Iso4217CurrencyCode) obj;
+ }
+
+ if (obj is DerInteger)
+ {
+ DerInteger numericobj = DerInteger.GetInstance(obj);
+ int numeric = numericobj.Value.IntValue;
+ return new Iso4217CurrencyCode(numeric);
+ }
+
+ if (obj is DerPrintableString)
+ {
+ DerPrintableString alphabetic = DerPrintableString.GetInstance(obj);
+ return new Iso4217CurrencyCode(alphabetic.GetString());
+ }
+
+ throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ public Iso4217CurrencyCode(
+ int numeric)
+ {
+ if (numeric > NumericMaxSize || numeric < NumericMinSize)
+ {
+ throw new ArgumentException("wrong size in numeric code : not in (" +NumericMinSize +".."+ NumericMaxSize +")");
+ }
+
+ obj = new DerInteger(numeric);
+ }
+
+ public Iso4217CurrencyCode(
+ string alphabetic)
+ {
+ if (alphabetic.Length > AlphabeticMaxSize)
+ {
+ throw new ArgumentException("wrong size in alphabetic code : max size is " + AlphabeticMaxSize);
+ }
+
+ obj = new DerPrintableString(alphabetic);
+ }
+
+ public bool IsAlphabetic { get { return obj is DerPrintableString; } }
+
+ public string Alphabetic { get { return ((DerPrintableString) obj).GetString(); } }
+
+ public int Numeric { get { return ((DerInteger)obj).Value.IntValue; } }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return obj.ToAsn1Object();
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/qualified/TypeOfBiometricData.cs b/src/core/srcbc/asn1/x509/qualified/TypeOfBiometricData.cs
index 6226937..a77e54a 100644
--- a/src/core/srcbc/asn1/x509/qualified/TypeOfBiometricData.cs
+++ b/src/core/srcbc/asn1/x509/qualified/TypeOfBiometricData.cs
@@ -1,91 +1,91 @@
-using System;
-
-using Org.BouncyCastle.Asn1;
-
-namespace Org.BouncyCastle.Asn1.X509.Qualified
-{
- /**
- * The TypeOfBiometricData object.
- *
- * TypeOfBiometricData ::= CHOICE {
- * predefinedBiometricType PredefinedBiometricType,
- * biometricDataOid OBJECT IDENTIFIER }
- *
- * PredefinedBiometricType ::= INTEGER {
- * picture(0),handwritten-signature(1)}
- * (picture|handwritten-signature)
- *
- */
- public class TypeOfBiometricData
- : Asn1Encodable
- {
- public const int Picture = 0;
- public const int HandwrittenSignature = 1;
-
- internal Asn1Encodable obj;
-
- public static TypeOfBiometricData GetInstance(
- object obj)
- {
- if (obj == null || obj is TypeOfBiometricData)
- {
- return (TypeOfBiometricData) obj;
- }
-
- if (obj is DerInteger)
- {
- DerInteger predefinedBiometricTypeObj = DerInteger.GetInstance(obj);
- int predefinedBiometricType = predefinedBiometricTypeObj.Value.IntValue;
-
- return new TypeOfBiometricData(predefinedBiometricType);
- }
-
- if (obj is DerObjectIdentifier)
- {
- DerObjectIdentifier BiometricDataOid = DerObjectIdentifier.GetInstance(obj);
- return new TypeOfBiometricData(BiometricDataOid);
- }
-
- throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
- }
-
- public TypeOfBiometricData(
- int predefinedBiometricType)
- {
- if (predefinedBiometricType == Picture || predefinedBiometricType == HandwrittenSignature)
- {
- obj = new DerInteger(predefinedBiometricType);
- }
- else
- {
- throw new ArgumentException("unknow PredefinedBiometricType : " + predefinedBiometricType);
- }
- }
-
- public TypeOfBiometricData(
- DerObjectIdentifier biometricDataOid)
- {
- obj = biometricDataOid;
- }
-
- public bool IsPredefined
- {
- get { return obj is DerInteger; }
- }
-
- public int PredefinedBiometricType
- {
- get { return ((DerInteger) obj).Value.IntValue; }
- }
-
- public DerObjectIdentifier BiometricDataOid
- {
- get { return (DerObjectIdentifier) obj; }
- }
-
- public override Asn1Object ToAsn1Object()
- {
- return obj.ToAsn1Object();
- }
- }
-}
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+ /**
+ * The TypeOfBiometricData object.
+ *
+ * TypeOfBiometricData ::= CHOICE {
+ * predefinedBiometricType PredefinedBiometricType,
+ * biometricDataOid OBJECT IDENTIFIER }
+ *
+ * PredefinedBiometricType ::= INTEGER {
+ * picture(0),handwritten-signature(1)}
+ * (picture|handwritten-signature)
+ *
+ */
+ public class TypeOfBiometricData
+ : Asn1Encodable, IAsn1Choice
+ {
+ public const int Picture = 0;
+ public const int HandwrittenSignature = 1;
+
+ internal Asn1Encodable obj;
+
+ public static TypeOfBiometricData GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is TypeOfBiometricData)
+ {
+ return (TypeOfBiometricData) obj;
+ }
+
+ if (obj is DerInteger)
+ {
+ DerInteger predefinedBiometricTypeObj = DerInteger.GetInstance(obj);
+ int predefinedBiometricType = predefinedBiometricTypeObj.Value.IntValue;
+
+ return new TypeOfBiometricData(predefinedBiometricType);
+ }
+
+ if (obj is DerObjectIdentifier)
+ {
+ DerObjectIdentifier BiometricDataOid = DerObjectIdentifier.GetInstance(obj);
+ return new TypeOfBiometricData(BiometricDataOid);
+ }
+
+ throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ public TypeOfBiometricData(
+ int predefinedBiometricType)
+ {
+ if (predefinedBiometricType == Picture || predefinedBiometricType == HandwrittenSignature)
+ {
+ obj = new DerInteger(predefinedBiometricType);
+ }
+ else
+ {
+ throw new ArgumentException("unknow PredefinedBiometricType : " + predefinedBiometricType);
+ }
+ }
+
+ public TypeOfBiometricData(
+ DerObjectIdentifier biometricDataOid)
+ {
+ obj = biometricDataOid;
+ }
+
+ public bool IsPredefined
+ {
+ get { return obj is DerInteger; }
+ }
+
+ public int PredefinedBiometricType
+ {
+ get { return ((DerInteger) obj).Value.IntValue; }
+ }
+
+ public DerObjectIdentifier BiometricDataOid
+ {
+ get { return (DerObjectIdentifier) obj; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return obj.ToAsn1Object();
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x509/sigi/NameOrPseudonym.cs b/src/core/srcbc/asn1/x509/sigi/NameOrPseudonym.cs
index 7149b80..222895c 100644
--- a/src/core/srcbc/asn1/x509/sigi/NameOrPseudonym.cs
+++ b/src/core/srcbc/asn1/x509/sigi/NameOrPseudonym.cs
@@ -1,178 +1,177 @@
-using System;
-using System.Collections;
-
-using Org.BouncyCastle.Asn1.X500;
-
-namespace Org.BouncyCastle.Asn1.X509.SigI
-{
- /**
- * Structure for a name or pseudonym.
- *
- *
- * NameOrPseudonym ::= CHOICE {
- * surAndGivenName SEQUENCE {
- * surName DirectoryString,
- * givenName SEQUENCE OF DirectoryString
- * },
- * pseudonym DirectoryString
- * }
- *
- *
- * @see org.bouncycastle.asn1.x509.sigi.PersonalData
- *
- */
- public class NameOrPseudonym
- : Asn1Encodable
- //, Asn1Choice
- {
- private readonly DirectoryString pseudonym;
- private readonly DirectoryString surname;
- private readonly Asn1Sequence givenName;
-
- public static NameOrPseudonym GetInstance(
- object obj)
- {
- if (obj == null || obj is NameOrPseudonym)
- {
- return (NameOrPseudonym)obj;
- }
-
- if (obj is IAsn1String)
- {
- return new NameOrPseudonym(DirectoryString.GetInstance(obj));
- }
-
- if (obj is Asn1Sequence)
- {
- return new NameOrPseudonym((Asn1Sequence) obj);
- }
-
- throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
- }
-
- /**
- * Constructor from DERString.
- *
- * The sequence is of type NameOrPseudonym:
- *
- *
- * NameOrPseudonym ::= CHOICE {
- * surAndGivenName SEQUENCE {
- * surName DirectoryString,
- * givenName SEQUENCE OF DirectoryString
- * },
- * pseudonym DirectoryString
- * }
- *
- * @param pseudonym pseudonym value to use.
- */
- public NameOrPseudonym(
- DirectoryString pseudonym)
- {
- this.pseudonym = pseudonym;
- }
-
- /**
- * Constructor from Asn1Sequence.
- *
- * The sequence is of type NameOrPseudonym:
- *
- *
- * NameOrPseudonym ::= CHOICE {
- * surAndGivenName SEQUENCE {
- * surName DirectoryString,
- * givenName SEQUENCE OF DirectoryString
- * },
- * pseudonym DirectoryString
- * }
- *
- *
- * @param seq The ASN.1 sequence.
- */
- private NameOrPseudonym(
- Asn1Sequence seq)
- {
- if (seq.Count != 2)
- throw new ArgumentException("Bad sequence size: " + seq.Count);
-
- if (!(seq[0] is IAsn1String))
- throw new ArgumentException("Bad object encountered: " + seq[0].GetType().Name);
-
- surname = DirectoryString.GetInstance(seq[0]);
- givenName = Asn1Sequence.GetInstance(seq[1]);
- }
-
- /**
- * Constructor from a given details.
- *
- * @param pseudonym The pseudonym.
- */
- public NameOrPseudonym(
- string pseudonym)
- : this(new DirectoryString(pseudonym))
- {
- }
-
- /**
- * Constructor from a given details.
- *
- * @param surname The surname.
- * @param givenName A sequence of directory strings making up the givenName
- */
- public NameOrPseudonym(
- DirectoryString surname,
- Asn1Sequence givenName)
- {
- this.surname = surname;
- this.givenName = givenName;
- }
-
- public DirectoryString Pseudonym
- {
- get { return pseudonym; }
- }
-
- public DirectoryString Surname
- {
- get { return surname; }
- }
-
- public DirectoryString[] GetGivenName()
- {
- DirectoryString[] items = new DirectoryString[givenName.Count];
- int count = 0;
- foreach (object o in givenName)
- {
- items[count++] = DirectoryString.GetInstance(o);
- }
- return items;
- }
-
- /**
- * Produce an object suitable for an Asn1OutputStream.
- *
- * Returns:
- *
- *
- * NameOrPseudonym ::= CHOICE {
- * surAndGivenName SEQUENCE {
- * surName DirectoryString,
- * givenName SEQUENCE OF DirectoryString
- * },
- * pseudonym DirectoryString
- * }
- *
- *
- * @return an Asn1Object
- */
- public override Asn1Object ToAsn1Object()
- {
- if (pseudonym != null)
- {
- return pseudonym.ToAsn1Object();
- }
-
- return new DerSequence(surname, givenName);
- }
- }
-}
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.X509.SigI
+{
+ /**
+ * Structure for a name or pseudonym.
+ *
+ *
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ *
+ *
+ * @see org.bouncycastle.asn1.x509.sigi.PersonalData
+ *
+ */
+ public class NameOrPseudonym
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly DirectoryString pseudonym;
+ private readonly DirectoryString surname;
+ private readonly Asn1Sequence givenName;
+
+ public static NameOrPseudonym GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is NameOrPseudonym)
+ {
+ return (NameOrPseudonym)obj;
+ }
+
+ if (obj is IAsn1String)
+ {
+ return new NameOrPseudonym(DirectoryString.GetInstance(obj));
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new NameOrPseudonym((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from DERString.
+ *
+ * The sequence is of type NameOrPseudonym:
+ *
+ *
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ *
+ * @param pseudonym pseudonym value to use.
+ */
+ public NameOrPseudonym(
+ DirectoryString pseudonym)
+ {
+ this.pseudonym = pseudonym;
+ }
+
+ /**
+ * Constructor from Asn1Sequence.
+ *
+ * The sequence is of type NameOrPseudonym:
+ *
+ *
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ *
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private NameOrPseudonym(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ if (!(seq[0] is IAsn1String))
+ throw new ArgumentException("Bad object encountered: " + seq[0].GetType().Name);
+
+ surname = DirectoryString.GetInstance(seq[0]);
+ givenName = Asn1Sequence.GetInstance(seq[1]);
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param pseudonym The pseudonym.
+ */
+ public NameOrPseudonym(
+ string pseudonym)
+ : this(new DirectoryString(pseudonym))
+ {
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param surname The surname.
+ * @param givenName A sequence of directory strings making up the givenName
+ */
+ public NameOrPseudonym(
+ DirectoryString surname,
+ Asn1Sequence givenName)
+ {
+ this.surname = surname;
+ this.givenName = givenName;
+ }
+
+ public DirectoryString Pseudonym
+ {
+ get { return pseudonym; }
+ }
+
+ public DirectoryString Surname
+ {
+ get { return surname; }
+ }
+
+ public DirectoryString[] GetGivenName()
+ {
+ DirectoryString[] items = new DirectoryString[givenName.Count];
+ int count = 0;
+ foreach (object o in givenName)
+ {
+ items[count++] = DirectoryString.GetInstance(o);
+ }
+ return items;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ *
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (pseudonym != null)
+ {
+ return pseudonym.ToAsn1Object();
+ }
+
+ return new DerSequence(surname, givenName);
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x9/X962Parameters.cs b/src/core/srcbc/asn1/x9/X962Parameters.cs
index e051716..5b7eaa1 100644
--- a/src/core/srcbc/asn1/x9/X962Parameters.cs
+++ b/src/core/srcbc/asn1/x9/X962Parameters.cs
@@ -1,53 +1,53 @@
-using Org.BouncyCastle.Asn1;
-
-namespace Org.BouncyCastle.Asn1.X9
-{
- public class X962Parameters
- : Asn1Encodable
- {
- private readonly Asn1Object _params;
-
- public X962Parameters(
- X9ECParameters ecParameters)
- {
- this._params = ecParameters.ToAsn1Object();
- }
-
- public X962Parameters(
- DerObjectIdentifier namedCurve)
- {
- this._params = namedCurve;
- }
-
- public X962Parameters(
- Asn1Object obj)
- {
- this._params = obj;
- }
-
- public bool IsNamedCurve
- {
- get { return (_params is DerObjectIdentifier); }
- }
-
- public Asn1Object Parameters
- {
- get { return _params; }
- }
-
- /**
- * Produce an object suitable for an Asn1OutputStream.
- *
- * Parameters ::= CHOICE {
- * ecParameters ECParameters,
- * namedCurve CURVES.&id({CurveNames}),
- * implicitlyCA Null
- * }
- *
- */
- public override Asn1Object ToAsn1Object()
- {
- return _params;
- }
- }
-}
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ public class X962Parameters
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly Asn1Object _params;
+
+ public X962Parameters(
+ X9ECParameters ecParameters)
+ {
+ this._params = ecParameters.ToAsn1Object();
+ }
+
+ public X962Parameters(
+ DerObjectIdentifier namedCurve)
+ {
+ this._params = namedCurve;
+ }
+
+ public X962Parameters(
+ Asn1Object obj)
+ {
+ this._params = obj;
+ }
+
+ public bool IsNamedCurve
+ {
+ get { return (_params is DerObjectIdentifier); }
+ }
+
+ public Asn1Object Parameters
+ {
+ get { return _params; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * Parameters ::= CHOICE {
+ * ecParameters ECParameters,
+ * namedCurve CURVES.&id({CurveNames}),
+ * implicitlyCA Null
+ * }
+ *
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return _params;
+ }
+ }
+}
diff --git a/src/core/srcbc/asn1/x9/X9ECParameters.cs b/src/core/srcbc/asn1/x9/X9ECParameters.cs
index 19aa068..d025b36 100644
--- a/src/core/srcbc/asn1/x9/X9ECParameters.cs
+++ b/src/core/srcbc/asn1/x9/X9ECParameters.cs
@@ -1,165 +1,170 @@
-using System;
-
-using Org.BouncyCastle.Math;
-using Org.BouncyCastle.Math.EC;
-
-namespace Org.BouncyCastle.Asn1.X9
-{
- /**
- * ASN.1 def for Elliptic-Curve ECParameters structure. See
- * X9.62, for further details.
- */
- public class X9ECParameters
- : Asn1Encodable
- {
- private X9FieldID fieldID;
- private ECCurve curve;
- private ECPoint g;
- private BigInteger n;
- private BigInteger h;
- private byte[] seed;
-
- public X9ECParameters(
- Asn1Sequence seq)
- {
- if (!(seq[0] is DerInteger)
- || !((DerInteger) seq[0]).Value.Equals(BigInteger.One))
- {
- throw new ArgumentException("bad version in X9ECParameters");
- }
-
- X9Curve x9c = null;
- if (seq[2] is X9Curve)
- {
- x9c = (X9Curve) seq[2];
- }
- else
- {
- x9c = new X9Curve(
- new X9FieldID(
- (Asn1Sequence) seq[1]),
- (Asn1Sequence) seq[2]);
- }
-
- this.curve = x9c.Curve;
-
- if (seq[3] is X9ECPoint)
- {
- this.g = ((X9ECPoint) seq[3]).Point;
- }
- else
- {
- this.g = new X9ECPoint(curve, (Asn1OctetString) seq[3]).Point;
- }
-
- this.n = ((DerInteger) seq[4]).Value;
- this.seed = x9c.GetSeed();
-
- if (seq.Count == 6)
- {
- this.h = ((DerInteger) seq[5]).Value;
- }
- else
- {
- this.h = BigInteger.One;
- }
- }
-
- public X9ECParameters(
- ECCurve curve,
- ECPoint g,
- BigInteger n)
- : this(curve, g, n, BigInteger.One, null)
- {
- }
-
- public X9ECParameters(
- ECCurve curve,
- ECPoint g,
- BigInteger n,
- BigInteger h)
- : this(curve, g, n, h, null)
- {
- }
-
- public X9ECParameters(
- ECCurve curve,
- ECPoint g,
- BigInteger n,
- BigInteger h,
- byte[] seed)
- {
- this.curve = curve;
- this.g = g;
- this.n = n;
- this.h = h;
- this.seed = seed;
-
- if (curve is FpCurve)
- {
- this.fieldID = new X9FieldID(((FpCurve) curve).Q);
- }
- else if (curve is F2mCurve)
- {
- F2mCurve curveF2m = (F2mCurve) curve;
- this.fieldID = new X9FieldID(curveF2m.M, curveF2m.K1,
- curveF2m.K2, curveF2m.K3);
- }
- }
-
- public ECCurve Curve
- {
- get { return curve; }
- }
-
- public ECPoint G
- {
- get { return g; }
- }
-
- public BigInteger N
- {
- get { return n; }
- }
-
- public BigInteger H
- {
- get { return h; }
- }
-
- public byte[] GetSeed()
- {
- return seed;
- }
-
- /**
- * Produce an object suitable for an Asn1OutputStream.
- *
- * ECParameters ::= Sequence {
- * version Integer { ecpVer1(1) } (ecpVer1),
- * fieldID FieldID {{FieldTypes}},
- * curve X9Curve,
- * base X9ECPoint,
- * order Integer,
- * cofactor Integer OPTIONAL
- * }
- *
- */
- public override Asn1Object ToAsn1Object()
- {
- Asn1EncodableVector v = new Asn1EncodableVector(
- new DerInteger(1),
- fieldID,
- new X9Curve(curve, seed),
- new X9ECPoint(g),
- new DerInteger(n));
-
- if (!h.Equals(BigInteger.One))
- {
- v.Add(new DerInteger(h));
- }
-
- return new DerSequence(v);
- }
- }
-}
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ /**
+ * ASN.1 def for Elliptic-Curve ECParameters structure. See
+ * X9.62, for further details.
+ */
+ public class X9ECParameters
+ : Asn1Encodable
+ {
+ private X9FieldID fieldID;
+ private ECCurve curve;
+ private ECPoint g;
+ private BigInteger n;
+ private BigInteger h;
+ private byte[] seed;
+
+ public X9ECParameters(
+ Asn1Sequence seq)
+ {
+ if (!(seq[0] is DerInteger)
+ || !((DerInteger) seq[0]).Value.Equals(BigInteger.One))
+ {
+ throw new ArgumentException("bad version in X9ECParameters");
+ }
+
+ X9Curve x9c = null;
+ if (seq[2] is X9Curve)
+ {
+ x9c = (X9Curve) seq[2];
+ }
+ else
+ {
+ x9c = new X9Curve(
+ new X9FieldID(
+ (Asn1Sequence) seq[1]),
+ (Asn1Sequence) seq[2]);
+ }
+
+ this.curve = x9c.Curve;
+
+ if (seq[3] is X9ECPoint)
+ {
+ this.g = ((X9ECPoint) seq[3]).Point;
+ }
+ else
+ {
+ this.g = new X9ECPoint(curve, (Asn1OctetString) seq[3]).Point;
+ }
+
+ this.n = ((DerInteger) seq[4]).Value;
+ this.seed = x9c.GetSeed();
+
+ if (seq.Count == 6)
+ {
+ this.h = ((DerInteger) seq[5]).Value;
+ }
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ ECPoint g,
+ BigInteger n)
+ : this(curve, g, n, BigInteger.One, null)
+ {
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ ECPoint g,
+ BigInteger n,
+ BigInteger h)
+ : this(curve, g, n, h, null)
+ {
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ ECPoint g,
+ BigInteger n,
+ BigInteger h,
+ byte[] seed)
+ {
+ this.curve = curve;
+ this.g = g;
+ this.n = n;
+ this.h = h;
+ this.seed = seed;
+
+ if (curve is FpCurve)
+ {
+ this.fieldID = new X9FieldID(((FpCurve) curve).Q);
+ }
+ else if (curve is F2mCurve)
+ {
+ F2mCurve curveF2m = (F2mCurve) curve;
+ this.fieldID = new X9FieldID(curveF2m.M, curveF2m.K1,
+ curveF2m.K2, curveF2m.K3);
+ }
+ }
+
+ public ECCurve Curve
+ {
+ get { return curve; }
+ }
+
+ public ECPoint G
+ {
+ get { return g; }
+ }
+
+ public BigInteger N
+ {
+ get { return n; }
+ }
+
+ public BigInteger H
+ {
+ get
+ {
+ if (h == null)
+ {
+ // TODO - this should be calculated, it will cause issues with custom curves.
+ return BigInteger.One;
+ }
+
+ return h;
+ }
+ }
+
+ public byte[] GetSeed()
+ {
+ return seed;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * ECParameters ::= Sequence {
+ * version Integer { ecpVer1(1) } (ecpVer1),
+ * fieldID FieldID {{FieldTypes}},
+ * curve X9Curve,
+ * base X9ECPoint,
+ * order Integer,
+ * cofactor Integer OPTIONAL
+ * }
+ *
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ new DerInteger(1),
+ fieldID,
+ new X9Curve(curve, seed),
+ new X9ECPoint(g),
+ new DerInteger(n));
+
+ if (h != null)
+ {
+ v.Add(new DerInteger(h));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/src/core/srcbc/bcpg/ArmoredInputStream.cs b/src/core/srcbc/bcpg/ArmoredInputStream.cs
index 084c84d..4e2645c 100644
--- a/src/core/srcbc/bcpg/ArmoredInputStream.cs
+++ b/src/core/srcbc/bcpg/ArmoredInputStream.cs
@@ -1,492 +1,512 @@
-using System;
-using System.Collections;
-using System.IO;
-using System.Text;
-
-using Org.BouncyCastle.Utilities.IO;
-
-namespace Org.BouncyCastle.Bcpg
-{
- /**
- * reader for Base64 armored objects - read the headers and then start returning
- * bytes when the data is reached. An IOException is thrown if the CRC check
- * fails.
- */
- public class ArmoredInputStream
- : BaseInputStream
- {
- /*
- * set up the decoding table.
- */
- private readonly static byte[] decodingTable;
- static ArmoredInputStream()
- {
- decodingTable = new byte[128];
- for (int i = 'A'; i <= 'Z'; i++)
- {
- decodingTable[i] = (byte)(i - 'A');
- }
- for (int i = 'a'; i <= 'z'; i++)
- {
- decodingTable[i] = (byte)(i - 'a' + 26);
- }
- for (int i = '0'; i <= '9'; i++)
- {
- decodingTable[i] = (byte)(i - '0' + 52);
- }
- decodingTable['+'] = 62;
- decodingTable['/'] = 63;
- }
-
- /**
- * decode the base 64 encoded input data.
- *
- * @return the offset the data starts in out.
- */
- private int Decode(
- int in0,
- int in1,
- int in2,
- int in3,
- int[] result)
- {
- if (in3 < 0)
- {
- throw new EndOfStreamException("unexpected end of file in armored stream.");
- }
-
- int b1, b2, b3, b4;
- if (in2 == '=')
- {
- b1 = decodingTable[in0] &0xff;
- b2 = decodingTable[in1] & 0xff;
- result[2] = ((b1 << 2) | (b2 >> 4)) & 0xff;
- return 2;
- }
- else if (in3 == '=')
- {
- b1 = decodingTable[in0];
- b2 = decodingTable[in1];
- b3 = decodingTable[in2];
- result[1] = ((b1 << 2) | (b2 >> 4)) & 0xff;
- result[2] = ((b2 << 4) | (b3 >> 2)) & 0xff;
- return 1;
- }
- else
- {
- b1 = decodingTable[in0];
- b2 = decodingTable[in1];
- b3 = decodingTable[in2];
- b4 = decodingTable[in3];
- result[0] = ((b1 << 2) | (b2 >> 4)) & 0xff;
- result[1] = ((b2 << 4) | (b3 >> 2)) & 0xff;
- result[2] = ((b3 << 6) | b4) & 0xff;
- return 0;
- }
- }
-
- Stream input;
- bool start = true;
- int[] outBuf = new int[3];
- int bufPtr = 3;
- Crc24 crc = new Crc24();
- bool crcFound = false;
- bool hasHeaders = true;
- string header = null;
- bool newLineFound = false;
- bool clearText = false;
- bool restart = false;
- ArrayList headerList= new ArrayList();
- int lastC = 0;
-
- /**
- * Create a stream for reading a PGP armoured message, parsing up to a header
- * and then reading the data that follows.
- *
- * @param input
- */
- public ArmoredInputStream(
- Stream input)
- : this(input, true)
- {
- }
-
- /**
- * Create an armoured input stream which will assume the data starts
- * straight away, or parse for headers first depending on the value of
- * hasHeaders.
- *
- * @param input
- * @param hasHeaders true if headers are to be looked for, false otherwise.
- */
- public ArmoredInputStream(
- Stream input,
- bool hasHeaders)
- {
- this.input = input;
- this.hasHeaders = hasHeaders;
-
- if (hasHeaders)
- {
- ParseHeaders();
- }
-
- start = false;
- }
-
- private bool ParseHeaders()
- {
- header = null;
-
- int c;
- int last = 0;
- bool headerFound = false;
-
- headerList = new ArrayList();
-
- //
- // if restart we already have a header
- //
- if (restart)
- {
- headerFound = true;
- }
- else
- {
- while ((c = input.ReadByte()) >= 0)
- {
- if (c == '-' && (last == 0 || last == '\n' || last == '\r'))
- {
- headerFound = true;
- break;
- }
-
- last = c;
- }
- }
-
- if (headerFound)
- {
- StringBuilder Buffer = new StringBuilder("-");
- bool eolReached = false;
- bool crLf = false;
-
- if (restart) // we've had to look ahead two '-'
- {
- Buffer.Append('-');
- }
-
- while ((c = input.ReadByte()) >= 0)
- {
- if (last == '\r' && c == '\n')
- {
- crLf = true;
- }
- if (eolReached && (last != '\r' && c == '\n'))
- {
- break;
- }
- if (eolReached && c == '\r')
- {
- break;
- }
- if (c == '\r' || (last != '\r' && c == '\n'))
- {
- string line = Buffer.ToString();
- if (line.Trim().Length < 1)
- break;
- headerList.Add(line);
- Buffer.Length = 0;
- }
-
- if (c != '\n' && c != '\r')
- {
- Buffer.Append((char)c);
- eolReached = false;
- }
- else
- {
- if (c == '\r' || (last != '\r' && c == '\n'))
- {
- eolReached = true;
- }
- }
-
- last = c;
- }
-
- if (crLf)
- {
- input.ReadByte(); // skip last \n
- }
- }
-
- if (headerList.Count > 0)
- {
- header = (string) headerList[0];
- }
-
- clearText = "-----BEGIN PGP SIGNED MESSAGE-----".Equals(header);
- newLineFound = true;
-
- return headerFound;
- }
-
- /**
- * @return true if we are inside the clear text section of a PGP
- * signed message.
- */
- public bool IsClearText()
- {
- return clearText;
- }
-
- /**
- * Return the armor header line (if there is one)
- * @return the armor header line, null if none present.
- */
- public string GetArmorHeaderLine()
- {
- return header;
- }
-
- /**
- * Return the armor headers (the lines after the armor header line),
- * @return an array of armor headers, null if there aren't any.
- */
- public string[] GetArmorHeaders()
- {
- if (headerList.Count <= 1)
- {
- return null;
- }
-
- string[] hdrs = new string[headerList.Count - 1];
- for (int i = 0; i != hdrs.Length; i++)
- {
- hdrs[i] = (string) headerList[i + 1];
- }
-
- return hdrs;
- }
-
- private int ReadIgnoreSpace()
- {
- int c;
- do
- {
- c = input.ReadByte();
- }
- while (c == ' ' || c == '\t');
-
- return c;
- }
-
- private int ReadIgnoreWhitespace()
- {
- int c;
- do
- {
- c = input.ReadByte();
- }
- while (c == ' ' || c == '\t' || c == '\r' || c == '\n');
-
- return c;
- }
-
- private int ReadByteClearText()
- {
- int c = input.ReadByte();
-
- if (c == '\r' || (c == '\n' && lastC != '\r'))
- {
- newLineFound = true;
- }
- else if (newLineFound && c == '-')
- {
- c = input.ReadByte();
- if (c == '-') // a header, not dash escaped
- {
- clearText = false;
- start = true;
- restart = true;
- }
- else // a space - must be a dash escape
- {
- c = input.ReadByte();
- }
- newLineFound = false;
- }
- else
- {
- if (c != '\n' && lastC != '\r')
- {
- newLineFound = false;
- }
- }
-
- lastC = c;
-
- return c;
- }
-
- private int ReadClearText(byte[] buffer, int offset, int count)
- {
- int pos = offset;
- try
- {
- int end = offset + count;
- while (pos < end)
- {
- int c = ReadByteClearText();
- if (c == -1)
- {
- break;
- }
- buffer[pos++] = (byte) c;
- }
- }
- catch (IOException ioe)
- {
- if (pos == offset) throw ioe;
- }
-
- return pos - offset;
- }
-
- private int DoReadByte()
- {
- if (bufPtr > 2 || crcFound)
- {
- int c = ReadIgnoreSpace();
- if (c == '\n' || c == '\r')
- {
- c = ReadIgnoreWhitespace();
- if (c == '=') // crc reached
- {
- bufPtr = Decode(ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), outBuf);
-
- if (bufPtr != 0)
- {
- throw new IOException("no crc found in armored message.");
- }
-
- crcFound = true;
-
- int i = ((outBuf[0] & 0xff) << 16)
- | ((outBuf[1] & 0xff) << 8)
- | (outBuf[2] & 0xff);
-
- if (i != crc.Value)
- {
- throw new IOException("crc check failed in armored message.");
- }
-
- return ReadByte();
- }
-
- if (c == '-') // end of record reached
- {
- while ((c = input.ReadByte()) >= 0)
- {
- if (c == '\n' || c == '\r')
- {
- break;
- }
- }
-
- if (!crcFound)
- {
- throw new IOException("crc check not found.");
- }
-
- crcFound = false;
- start = true;
- bufPtr = 3;
-
- return -1;
- }
- }
-
- if (c < 0)
- {
- return -1;
- }
-
- bufPtr = Decode(c, ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), outBuf);
- }
-
- return outBuf[bufPtr++];
- }
-
- public override int ReadByte()
- {
- if (start)
- {
- if (hasHeaders)
- {
- ParseHeaders();
- }
-
- crc.Reset();
- start = false;
- }
-
- if (clearText)
- {
- return ReadByteClearText();
- }
-
- int c = DoReadByte();
-
- crc.Update(c);
-
- return c;
- }
-
- public override int Read(byte[] buffer, int offset, int count)
- {
- if (start && count > 0)
- {
- if (hasHeaders)
- {
- ParseHeaders();
- }
- start = false;
- }
-
- if (clearText)
- {
- return ReadClearText(buffer, offset, count);
- }
-
- int pos = offset;
- try
- {
- int end = offset + count;
- while (pos < end)
- {
- int c = DoReadByte();
- crc.Update(c);
- if (c == -1)
- {
- break;
- }
- buffer[pos++] = (byte) c;
- }
- }
- catch (IOException ioe)
- {
- if (pos == offset) throw ioe;
- }
-
- return pos - offset;
- }
-
- public override void Close()
- {
- input.Close();
- base.Close();
- }
- }
-}
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+ /**
+ * reader for Base64 armored objects - read the headers and then start returning
+ * bytes when the data is reached. An IOException is thrown if the CRC check
+ * fails.
+ */
+ public class ArmoredInputStream
+ : BaseInputStream
+ {
+ /*
+ * set up the decoding table.
+ */
+ private readonly static byte[] decodingTable;
+ static ArmoredInputStream()
+ {
+ decodingTable = new byte[128];
+ for (int i = 'A'; i <= 'Z'; i++)
+ {
+ decodingTable[i] = (byte)(i - 'A');
+ }
+ for (int i = 'a'; i <= 'z'; i++)
+ {
+ decodingTable[i] = (byte)(i - 'a' + 26);
+ }
+ for (int i = '0'; i <= '9'; i++)
+ {
+ decodingTable[i] = (byte)(i - '0' + 52);
+ }
+ decodingTable['+'] = 62;
+ decodingTable['/'] = 63;
+ }
+
+ /**
+ * decode the base 64 encoded input data.
+ *
+ * @return the offset the data starts in out.
+ */
+ private int Decode(
+ int in0,
+ int in1,
+ int in2,
+ int in3,
+ int[] result)
+ {
+ if (in3 < 0)
+ {
+ throw new EndOfStreamException("unexpected end of file in armored stream.");
+ }
+
+ int b1, b2, b3, b4;
+ if (in2 == '=')
+ {
+ b1 = decodingTable[in0] &0xff;
+ b2 = decodingTable[in1] & 0xff;
+ result[2] = ((b1 << 2) | (b2 >> 4)) & 0xff;
+ return 2;
+ }
+ else if (in3 == '=')
+ {
+ b1 = decodingTable[in0];
+ b2 = decodingTable[in1];
+ b3 = decodingTable[in2];
+ result[1] = ((b1 << 2) | (b2 >> 4)) & 0xff;
+ result[2] = ((b2 << 4) | (b3 >> 2)) & 0xff;
+ return 1;
+ }
+ else
+ {
+ b1 = decodingTable[in0];
+ b2 = decodingTable[in1];
+ b3 = decodingTable[in2];
+ b4 = decodingTable[in3];
+ result[0] = ((b1 << 2) | (b2 >> 4)) & 0xff;
+ result[1] = ((b2 << 4) | (b3 >> 2)) & 0xff;
+ result[2] = ((b3 << 6) | b4) & 0xff;
+ return 0;
+ }
+ }
+
+ Stream input;
+ bool start = true;
+ int[] outBuf = new int[3];
+ int bufPtr = 3;
+ Crc24 crc = new Crc24();
+ bool crcFound = false;
+ bool hasHeaders = true;
+ string header = null;
+ bool newLineFound = false;
+ bool clearText = false;
+ bool restart = false;
+ ArrayList headerList= new ArrayList();
+ int lastC = 0;
+ bool isEndOfStream;
+
+ /**
+ * Create a stream for reading a PGP armoured message, parsing up to a header
+ * and then reading the data that follows.
+ *
+ * @param input
+ */
+ public ArmoredInputStream(
+ Stream input)
+ : this(input, true)
+ {
+ }
+
+ /**
+ * Create an armoured input stream which will assume the data starts
+ * straight away, or parse for headers first depending on the value of
+ * hasHeaders.
+ *
+ * @param input
+ * @param hasHeaders true if headers are to be looked for, false otherwise.
+ */
+ public ArmoredInputStream(
+ Stream input,
+ bool hasHeaders)
+ {
+ this.input = input;
+ this.hasHeaders = hasHeaders;
+
+ if (hasHeaders)
+ {
+ ParseHeaders();
+ }
+
+ start = false;
+ }
+
+ private bool ParseHeaders()
+ {
+ header = null;
+
+ int c;
+ int last = 0;
+ bool headerFound = false;
+
+ headerList = new ArrayList();
+
+ //
+ // if restart we already have a header
+ //
+ if (restart)
+ {
+ headerFound = true;
+ }
+ else
+ {
+ while ((c = input.ReadByte()) >= 0)
+ {
+ if (c == '-' && (last == 0 || last == '\n' || last == '\r'))
+ {
+ headerFound = true;
+ break;
+ }
+
+ last = c;
+ }
+ }
+
+ if (headerFound)
+ {
+ StringBuilder Buffer = new StringBuilder("-");
+ bool eolReached = false;
+ bool crLf = false;
+
+ if (restart) // we've had to look ahead two '-'
+ {
+ Buffer.Append('-');
+ }
+
+ while ((c = input.ReadByte()) >= 0)
+ {
+ if (last == '\r' && c == '\n')
+ {
+ crLf = true;
+ }
+ if (eolReached && (last != '\r' && c == '\n'))
+ {
+ break;
+ }
+ if (eolReached && c == '\r')
+ {
+ break;
+ }
+ if (c == '\r' || (last != '\r' && c == '\n'))
+ {
+ string line = Buffer.ToString();
+ if (line.Trim().Length < 1)
+ break;
+ headerList.Add(line);
+ Buffer.Length = 0;
+ }
+
+ if (c != '\n' && c != '\r')
+ {
+ Buffer.Append((char)c);
+ eolReached = false;
+ }
+ else
+ {
+ if (c == '\r' || (last != '\r' && c == '\n'))
+ {
+ eolReached = true;
+ }
+ }
+
+ last = c;
+ }
+
+ if (crLf)
+ {
+ input.ReadByte(); // skip last \n
+ }
+ }
+
+ if (headerList.Count > 0)
+ {
+ header = (string) headerList[0];
+ }
+
+ clearText = "-----BEGIN PGP SIGNED MESSAGE-----".Equals(header);
+ newLineFound = true;
+
+ return headerFound;
+ }
+
+ /**
+ * @return true if we are inside the clear text section of a PGP
+ * signed message.
+ */
+ public bool IsClearText()
+ {
+ return clearText;
+ }
+
+ /**
+ * @return true if the stream is actually at end of file.
+ */
+ public bool IsEndOfStream()
+ {
+ return isEndOfStream;
+ }
+
+ /**
+ * Return the armor header line (if there is one)
+ * @return the armor header line, null if none present.
+ */
+ public string GetArmorHeaderLine()
+ {
+ return header;
+ }
+
+ /**
+ * Return the armor headers (the lines after the armor header line),
+ * @return an array of armor headers, null if there aren't any.
+ */
+ public string[] GetArmorHeaders()
+ {
+ if (headerList.Count <= 1)
+ {
+ return null;
+ }
+
+ string[] hdrs = new string[headerList.Count - 1];
+ for (int i = 0; i != hdrs.Length; i++)
+ {
+ hdrs[i] = (string) headerList[i + 1];
+ }
+
+ return hdrs;
+ }
+
+ private int ReadIgnoreSpace()
+ {
+ int c;
+ do
+ {
+ c = input.ReadByte();
+ }
+ while (c == ' ' || c == '\t');
+
+ return c;
+ }
+
+ private int ReadIgnoreWhitespace()
+ {
+ int c;
+ do
+ {
+ c = input.ReadByte();
+ }
+ while (c == ' ' || c == '\t' || c == '\r' || c == '\n');
+
+ return c;
+ }
+
+ private int ReadByteClearText()
+ {
+ int c = input.ReadByte();
+
+ if (c == '\r' || (c == '\n' && lastC != '\r'))
+ {
+ newLineFound = true;
+ }
+ else if (newLineFound && c == '-')
+ {
+ c = input.ReadByte();
+ if (c == '-') // a header, not dash escaped
+ {
+ clearText = false;
+ start = true;
+ restart = true;
+ }
+ else // a space - must be a dash escape
+ {
+ c = input.ReadByte();
+ }
+ newLineFound = false;
+ }
+ else
+ {
+ if (c != '\n' && lastC != '\r')
+ {
+ newLineFound = false;
+ }
+ }
+
+ lastC = c;
+
+ if (c < 0)
+ {
+ isEndOfStream = true;
+ }
+
+ return c;
+ }
+
+ private int ReadClearText(byte[] buffer, int offset, int count)
+ {
+ int pos = offset;
+ try
+ {
+ int end = offset + count;
+ while (pos < end)
+ {
+ int c = ReadByteClearText();
+ if (c == -1)
+ {
+ break;
+ }
+ buffer[pos++] = (byte) c;
+ }
+ }
+ catch (IOException ioe)
+ {
+ if (pos == offset) throw ioe;
+ }
+
+ return pos - offset;
+ }
+
+ private int DoReadByte()
+ {
+ if (bufPtr > 2 || crcFound)
+ {
+ int c = ReadIgnoreSpace();
+ if (c == '\n' || c == '\r')
+ {
+ c = ReadIgnoreWhitespace();
+ if (c == '=') // crc reached
+ {
+ bufPtr = Decode(ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), outBuf);
+
+ if (bufPtr != 0)
+ {
+ throw new IOException("no crc found in armored message.");
+ }
+
+ crcFound = true;
+
+ int i = ((outBuf[0] & 0xff) << 16)
+ | ((outBuf[1] & 0xff) << 8)
+ | (outBuf[2] & 0xff);
+
+ if (i != crc.Value)
+ {
+ throw new IOException("crc check failed in armored message.");
+ }
+
+ return ReadByte();
+ }
+
+ if (c == '-') // end of record reached
+ {
+ while ((c = input.ReadByte()) >= 0)
+ {
+ if (c == '\n' || c == '\r')
+ {
+ break;
+ }
+ }
+
+ if (!crcFound)
+ {
+ throw new IOException("crc check not found.");
+ }
+
+ crcFound = false;
+ start = true;
+ bufPtr = 3;
+
+ if (c < 0)
+ {
+ isEndOfStream = true;
+ }
+
+ return -1;
+ }
+ }
+
+ if (c < 0)
+ {
+ isEndOfStream = true;
+ return -1;
+ }
+
+ bufPtr = Decode(c, ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), outBuf);
+ }
+
+ return outBuf[bufPtr++];
+ }
+
+ public override int ReadByte()
+ {
+ if (start)
+ {
+ if (hasHeaders)
+ {
+ ParseHeaders();
+ }
+
+ crc.Reset();
+ start = false;
+ }
+
+ if (clearText)
+ {
+ return ReadByteClearText();
+ }
+
+ int c = DoReadByte();
+
+ crc.Update(c);
+
+ return c;
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (start && count > 0)
+ {
+ if (hasHeaders)
+ {
+ ParseHeaders();
+ }
+ start = false;
+ }
+
+ if (clearText)
+ {
+ return ReadClearText(buffer, offset, count);
+ }
+
+ int pos = offset;
+ try
+ {
+ int end = offset + count;
+ while (pos < end)
+ {
+ int c = DoReadByte();
+ crc.Update(c);
+ if (c == -1)
+ {
+ break;
+ }
+ buffer[pos++] = (byte) c;
+ }
+ }
+ catch (IOException ioe)
+ {
+ if (pos == offset) throw ioe;
+ }
+
+ return pos - offset;
+ }
+
+ public override void Close()
+ {
+ input.Close();
+ base.Close();
+ }
+ }
+}
diff --git a/src/core/srcbc/bcpg/ArmoredOutputStream.cs b/src/core/srcbc/bcpg/ArmoredOutputStream.cs
index f1bb9e9..3d47135 100644
--- a/src/core/srcbc/bcpg/ArmoredOutputStream.cs
+++ b/src/core/srcbc/bcpg/ArmoredOutputStream.cs
@@ -1,328 +1,330 @@
-using System;
-using System.Collections;
-using System.Diagnostics;
-using System.IO;
-using System.Text;
-
-using Org.BouncyCastle.Utilities;
-using Org.BouncyCastle.Utilities.IO;
-
-namespace Org.BouncyCastle.Bcpg
-{
- /**
- * Basic output stream.
- */
- public class ArmoredOutputStream
- : BaseOutputStream
- {
- private static readonly byte[] encodingTable =
- {
- (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
- (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
- (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
- (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
- (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
- (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
- (byte)'v',
- (byte)'w', (byte)'x', (byte)'y', (byte)'z',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
- (byte)'7', (byte)'8', (byte)'9',
- (byte)'+', (byte)'/'
- };
-
- /**
- * encode the input data producing a base 64 encoded byte array.
- */
- private static void Encode(
- Stream outStream,
- int[] data,
- int len)
- {
- Debug.Assert(len > 0);
- Debug.Assert(len < 4);
-
- byte[] bs = new byte[4];
- int d1 = data[0];
- bs[0] = encodingTable[(d1 >> 2) & 0x3f];
-
- switch (len)
- {
- case 1:
- {
- bs[1] = encodingTable[(d1 << 4) & 0x3f];
- bs[2] = (byte)'=';
- bs[3] = (byte)'=';
- break;
- }
- case 2:
- {
- int d2 = data[1];
- bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
- bs[2] = encodingTable[(d2 << 2) & 0x3f];
- bs[3] = (byte)'=';
- break;
- }
- case 3:
- {
- int d2 = data[1];
- int d3 = data[2];
- bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
- bs[2] = encodingTable[((d2 << 2) | (d3 >> 6)) & 0x3f];
- bs[3] = encodingTable[d3 & 0x3f];
- break;
- }
- }
-
- outStream.Write(bs, 0, bs.Length);
- }
-
- private readonly Stream outStream;
- private int[] buf = new int[3];
- private int bufPtr = 0;
- private Crc24 crc = new Crc24();
- private int chunkCount = 0;
- private int lastb;
-
- private bool start = true;
- private bool clearText = false;
- private bool newLine = false;
-
- private string nl = Platform.NewLine;
-
- private string type;
- private string headerStart = "-----BEGIN PGP ";
- private string headerTail = "-----";
- private string footerStart = "-----END PGP ";
- private string footerTail = "-----";
-
- private string version = "BCPG v1.32";
-
- private readonly IDictionary headers;
-
- public ArmoredOutputStream(Stream outStream)
- {
- this.outStream = outStream;
- this.headers = new Hashtable();
- this.headers["Version"] = version;
- }
-
- public ArmoredOutputStream(Stream outStream, IDictionary headers)
- {
- this.outStream = outStream;
- this.headers = new Hashtable(headers);
- this.headers["Version"] = version;
- }
-
- /**
- * Set an additional header entry.
- *
- * @param name the name of the header entry.
- * @param v the value of the header entry.
- */
- public void SetHeader(
- string name,
- string v)
- {
- headers[name] = v;
- }
-
- /**
- * Reset the headers to only contain a Version string.
- */
- public void ResetHeaders()
- {
- headers.Clear();
- headers["Version"] = version;
- }
-
- /**
- * Start a clear text signed message.
- * @param hashAlgorithm
- */
- public void BeginClearText(
- HashAlgorithmTag hashAlgorithm)
- {
- string hash;
-
- switch (hashAlgorithm)
- {
- case HashAlgorithmTag.Sha1:
- hash = "SHA1";
- break;
- case HashAlgorithmTag.Sha256:
- hash = "SHA256";
- break;
- case HashAlgorithmTag.Sha384:
- hash = "SHA384";
- break;
- case HashAlgorithmTag.Sha512:
- hash = "SHA512";
- break;
- case HashAlgorithmTag.MD2:
- hash = "MD2";
- break;
- case HashAlgorithmTag.MD5:
- hash = "MD5";
- break;
- case HashAlgorithmTag.RipeMD160:
- hash = "RIPEMD160";
- break;
- default:
- throw new IOException("unknown hash algorithm tag in beginClearText: " + hashAlgorithm);
- }
-
- DoWrite("-----BEGIN PGP SIGNED MESSAGE-----" + nl);
- DoWrite("Hash: " + hash + nl + nl);
-
- clearText = true;
- newLine = true;
- lastb = 0;
- }
-
- public void EndClearText()
- {
- clearText = false;
- }
-
- public override void WriteByte(
- byte b)
- {
- if (clearText)
- {
- outStream.WriteByte(b);
-
- if (newLine)
- {
- if (!(b == '\n' && lastb == '\r'))
- {
- newLine = false;
- }
- if (b == '-')
- {
- outStream.WriteByte((byte)' ');
- outStream.WriteByte((byte)'-'); // dash escape
- }
- }
- if (b == '\r' || (b == '\n' && lastb != '\r'))
- {
- newLine = true;
- }
- lastb = b;
- return;
- }
-
- if (start)
- {
- bool newPacket = (b & 0x40) != 0;
-
- int tag;
- if (newPacket)
- {
- tag = b & 0x3f;
- }
- else
- {
- tag = (b & 0x3f) >> 2;
- }
-
- switch ((PacketTag)tag)
- {
- case PacketTag.PublicKey:
- type = "PUBLIC KEY BLOCK";
- break;
- case PacketTag.SecretKey:
- type = "PRIVATE KEY BLOCK";
- break;
- case PacketTag.Signature:
- type = "SIGNATURE";
- break;
- default:
- type = "MESSAGE";
- break;
- }
-
- DoWrite(headerStart + type + headerTail + nl);
- WriteHeaderEntry("Version", (string) headers["Version"]);
-
- foreach (DictionaryEntry de in headers)
- {
- string k = (string) de.Key;
- if (k != "Version")
- {
- string v = (string) de.Value;
- WriteHeaderEntry(k, v);
- }
- }
-
- DoWrite(nl);
-
- start = false;
- }
-
- if (bufPtr == 3)
- {
- Encode(outStream, buf, bufPtr);
- bufPtr = 0;
- if ((++chunkCount & 0xf) == 0)
- {
- DoWrite(nl);
- }
- }
-
- crc.Update(b);
- buf[bufPtr++] = b & 0xff;
- }
-
- /**
- * Note: close does nor close the underlying stream. So it is possible to write
- * multiple objects using armoring to a single stream.
- */
- public override void Close()
- {
- if (type != null)
- {
- if (bufPtr > 0)
- {
- Encode(outStream, buf, bufPtr);
- }
-
- DoWrite(nl + '=');
-
- int crcV = crc.Value;
-
- buf[0] = ((crcV >> 16) & 0xff);
- buf[1] = ((crcV >> 8) & 0xff);
- buf[2] = (crcV & 0xff);
-
- Encode(outStream, buf, 3);
-
- DoWrite(nl);
- DoWrite(footerStart);
- DoWrite(type);
- DoWrite(footerTail);
- DoWrite(nl);
-
- outStream.Flush();
-
- type = null;
- start = true;
- base.Close();
- }
- }
-
- private void WriteHeaderEntry(
- string name,
- string v)
- {
- DoWrite(name + ": " + v + nl);
- }
-
- private void DoWrite(
- string s)
- {
- byte[] bs = Encoding.ASCII.GetBytes(s);
- outStream.Write(bs, 0, bs.Length);
- }
- }
-}
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+ /**
+ * Basic output stream.
+ */
+ public class ArmoredOutputStream
+ : BaseOutputStream
+ {
+ private static readonly byte[] encodingTable =
+ {
+ (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
+ (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
+ (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
+ (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
+ (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
+ (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
+ (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
+ (byte)'v',
+ (byte)'w', (byte)'x', (byte)'y', (byte)'z',
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
+ (byte)'7', (byte)'8', (byte)'9',
+ (byte)'+', (byte)'/'
+ };
+
+ /**
+ * encode the input data producing a base 64 encoded byte array.
+ */
+ private static void Encode(
+ Stream outStream,
+ int[] data,
+ int len)
+ {
+ Debug.Assert(len > 0);
+ Debug.Assert(len < 4);
+
+ byte[] bs = new byte[4];
+ int d1 = data[0];
+ bs[0] = encodingTable[(d1 >> 2) & 0x3f];
+
+ switch (len)
+ {
+ case 1:
+ {
+ bs[1] = encodingTable[(d1 << 4) & 0x3f];
+ bs[2] = (byte)'=';
+ bs[3] = (byte)'=';
+ break;
+ }
+ case 2:
+ {
+ int d2 = data[1];
+ bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
+ bs[2] = encodingTable[(d2 << 2) & 0x3f];
+ bs[3] = (byte)'=';
+ break;
+ }
+ case 3:
+ {
+ int d2 = data[1];
+ int d3 = data[2];
+ bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
+ bs[2] = encodingTable[((d2 << 2) | (d3 >> 6)) & 0x3f];
+ bs[3] = encodingTable[d3 & 0x3f];
+ break;
+ }
+ }
+
+ outStream.Write(bs, 0, bs.Length);
+ }
+
+ private readonly Stream outStream;
+ private int[] buf = new int[3];
+ private int bufPtr = 0;
+ private Crc24 crc = new Crc24();
+ private int chunkCount = 0;
+ private int lastb;
+
+ private bool start = true;
+ private bool clearText = false;
+ private bool newLine = false;
+
+ private string type;
+
+ private static readonly string nl = Platform.NewLine;
+ private static readonly string headerStart = "-----BEGIN PGP ";
+ private static readonly string headerTail = "-----";
+ private static readonly string footerStart = "-----END PGP ";
+ private static readonly string footerTail = "-----";
+
+ private static readonly string version = "BCPG C# v"
+ + Assembly.GetExecutingAssembly().GetName().Version;
+
+ private readonly IDictionary headers;
+
+ public ArmoredOutputStream(Stream outStream)
+ {
+ this.outStream = outStream;
+ this.headers = new Hashtable();
+ this.headers["Version"] = version;
+ }
+
+ public ArmoredOutputStream(Stream outStream, IDictionary headers)
+ {
+ this.outStream = outStream;
+ this.headers = new Hashtable(headers);
+ this.headers["Version"] = version;
+ }
+
+ /**
+ * Set an additional header entry.
+ *
+ * @param name the name of the header entry.
+ * @param v the value of the header entry.
+ */
+ public void SetHeader(
+ string name,
+ string v)
+ {
+ headers[name] = v;
+ }
+
+ /**
+ * Reset the headers to only contain a Version string.
+ */
+ public void ResetHeaders()
+ {
+ headers.Clear();
+ headers["Version"] = version;
+ }
+
+ /**
+ * Start a clear text signed message.
+ * @param hashAlgorithm
+ */
+ public void BeginClearText(
+ HashAlgorithmTag hashAlgorithm)
+ {
+ string hash;
+
+ switch (hashAlgorithm)
+ {
+ case HashAlgorithmTag.Sha1:
+ hash = "SHA1";
+ break;
+ case HashAlgorithmTag.Sha256:
+ hash = "SHA256";
+ break;
+ case HashAlgorithmTag.Sha384:
+ hash = "SHA384";
+ break;
+ case HashAlgorithmTag.Sha512:
+ hash = "SHA512";
+ break;
+ case HashAlgorithmTag.MD2:
+ hash = "MD2";
+ break;
+ case HashAlgorithmTag.MD5:
+ hash = "MD5";
+ break;
+ case HashAlgorithmTag.RipeMD160:
+ hash = "RIPEMD160";
+ break;
+ default:
+ throw new IOException("unknown hash algorithm tag in beginClearText: " + hashAlgorithm);
+ }
+
+ DoWrite("-----BEGIN PGP SIGNED MESSAGE-----" + nl);
+ DoWrite("Hash: " + hash + nl + nl);
+
+ clearText = true;
+ newLine = true;
+ lastb = 0;
+ }
+
+ public void EndClearText()
+ {
+ clearText = false;
+ }
+
+ public override void WriteByte(
+ byte b)
+ {
+ if (clearText)
+ {
+ outStream.WriteByte(b);
+
+ if (newLine)
+ {
+ if (!(b == '\n' && lastb == '\r'))
+ {
+ newLine = false;
+ }
+ if (b == '-')
+ {
+ outStream.WriteByte((byte)' ');
+ outStream.WriteByte((byte)'-'); // dash escape
+ }
+ }
+ if (b == '\r' || (b == '\n' && lastb != '\r'))
+ {
+ newLine = true;
+ }
+ lastb = b;
+ return;
+ }
+
+ if (start)
+ {
+ bool newPacket = (b & 0x40) != 0;
+
+ int tag;
+ if (newPacket)
+ {
+ tag = b & 0x3f;
+ }
+ else
+ {
+ tag = (b & 0x3f) >> 2;
+ }
+
+ switch ((PacketTag)tag)
+ {
+ case PacketTag.PublicKey:
+ type = "PUBLIC KEY BLOCK";
+ break;
+ case PacketTag.SecretKey:
+ type = "PRIVATE KEY BLOCK";
+ break;
+ case PacketTag.Signature:
+ type = "SIGNATURE";
+ break;
+ default:
+ type = "MESSAGE";
+ break;
+ }
+
+ DoWrite(headerStart + type + headerTail + nl);
+ WriteHeaderEntry("Version", (string) headers["Version"]);
+
+ foreach (DictionaryEntry de in headers)
+ {
+ string k = (string) de.Key;
+ if (k != "Version")
+ {
+ string v = (string) de.Value;
+ WriteHeaderEntry(k, v);
+ }
+ }
+
+ DoWrite(nl);
+
+ start = false;
+ }
+
+ if (bufPtr == 3)
+ {
+ Encode(outStream, buf, bufPtr);
+ bufPtr = 0;
+ if ((++chunkCount & 0xf) == 0)
+ {
+ DoWrite(nl);
+ }
+ }
+
+ crc.Update(b);
+ buf[bufPtr++] = b & 0xff;
+ }
+
+ /**
+ * Note: close does nor close the underlying stream. So it is possible to write
+ * multiple objects using armoring to a single stream.
+ */
+ public override void Close()
+ {
+ if (type != null)
+ {
+ if (bufPtr > 0)
+ {
+ Encode(outStream, buf, bufPtr);
+ }
+
+ DoWrite(nl + '=');
+
+ int crcV = crc.Value;
+
+ buf[0] = ((crcV >> 16) & 0xff);
+ buf[1] = ((crcV >> 8) & 0xff);
+ buf[2] = (crcV & 0xff);
+
+ Encode(outStream, buf, 3);
+
+ DoWrite(nl);
+ DoWrite(footerStart);
+ DoWrite(type);
+ DoWrite(footerTail);
+ DoWrite(nl);
+
+ outStream.Flush();
+
+ type = null;
+ start = true;
+ base.Close();
+ }
+ }
+
+ private void WriteHeaderEntry(
+ string name,
+ string v)
+ {
+ DoWrite(name + ": " + v + nl);
+ }
+
+ private void DoWrite(
+ string s)
+ {
+ byte[] bs = Encoding.ASCII.GetBytes(s);
+ outStream.Write(bs, 0, bs.Length);
+ }
+ }
+}
diff --git a/src/core/srcbc/bcpg/SignatureSubpacketTags.cs b/src/core/srcbc/bcpg/SignatureSubpacketTags.cs
index 056f4aa..1a8e254 100644
--- a/src/core/srcbc/bcpg/SignatureSubpacketTags.cs
+++ b/src/core/srcbc/bcpg/SignatureSubpacketTags.cs
@@ -1,30 +1,33 @@
-namespace Org.BouncyCastle.Bcpg
-{
- /**
- * Basic PGP signature sub-packet tag types.
- */
- public enum SignatureSubpacketTag
- {
- CreationTime = 2, // signature creation time
- ExpireTime = 3, // signature expiration time
- Exportable = 4, // exportable certification
- TrustSig = 5, // trust signature
- RegExp = 6, // regular expression
- Revocable = 7, // revocable
- KeyExpireTime = 9, // key expiration time
- Placeholder = 10, // placeholder for backward compatibility
- PreferredSymmetricAlgorithms = 11, // preferred symmetric algorithms
- RevocationKey = 12, // revocation key
- IssuerKeyId = 16, // issuer key ID
- NotationData = 20, // notation data
- PreferredHashAlgorithms = 21, // preferred hash algorithms
- PreferredCompressionAlgorithms = 22, // preferred compression algorithms
- KeyServerPreferences = 23, // key server preferences
- PreferredKeyServer = 24, // preferred key server
- PrimaryUserId = 25, // primary user id
- PolicyUrl = 26, // policy URL
- KeyFlags = 27, // key flags
- SignerUserId = 28, // signer's user id
- RevocationReason = 29 // reason for revocation
- }
-}
+namespace Org.BouncyCastle.Bcpg
+{
+ /**
+ * Basic PGP signature sub-packet tag types.
+ */
+ public enum SignatureSubpacketTag
+ {
+ CreationTime = 2, // signature creation time
+ ExpireTime = 3, // signature expiration time
+ Exportable = 4, // exportable certification
+ TrustSig = 5, // trust signature
+ RegExp = 6, // regular expression
+ Revocable = 7, // revocable
+ KeyExpireTime = 9, // key expiration time
+ Placeholder = 10, // placeholder for backward compatibility
+ PreferredSymmetricAlgorithms = 11, // preferred symmetric algorithms
+ RevocationKey = 12, // revocation key
+ IssuerKeyId = 16, // issuer key ID
+ NotationData = 20, // notation data
+ PreferredHashAlgorithms = 21, // preferred hash algorithms
+ PreferredCompressionAlgorithms = 22, // preferred compression algorithms
+ KeyServerPreferences = 23, // key server preferences
+ PreferredKeyServer = 24, // preferred key server
+ PrimaryUserId = 25, // primary user id
+ PolicyUrl = 26, // policy URL
+ KeyFlags = 27, // key flags
+ SignerUserId = 28, // signer's user id
+ RevocationReason = 29, // reason for revocation
+ Features = 30, // features
+ SignatureTarget = 31, // signature target
+ EmbeddedSignature = 32 // embedded signature
+ }
+}
diff --git a/src/core/srcbc/bcpg/sig/EmbeddedSignature.cs b/src/core/srcbc/bcpg/sig/EmbeddedSignature.cs
new file mode 100644
index 0000000..e47604a
--- /dev/null
+++ b/src/core/srcbc/bcpg/sig/EmbeddedSignature.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+ /**
+ * Packet embedded signature
+ */
+ public class EmbeddedSignature
+ : SignatureSubpacket
+ {
+ public EmbeddedSignature(
+ bool critical,
+ byte[] data)
+ : base(SignatureSubpacketTag.EmbeddedSignature, critical, data)
+ {
+ }
+ }
+}
diff --git a/src/core/srcbc/bcpg/sig/NotationData.cs b/src/core/srcbc/bcpg/sig/NotationData.cs
index 673102c..ccc9aa7 100644
--- a/src/core/srcbc/bcpg/sig/NotationData.cs
+++ b/src/core/srcbc/bcpg/sig/NotationData.cs
@@ -1,101 +1,112 @@
-using System;
-using System.IO;
-using System.Text;
-
-namespace Org.BouncyCastle.Bcpg.Sig
-{
- /**
- * Class provided a NotationData object according to
- * RFC2440, Chapter 5.2.3.15. Notation Data
- */
- public class NotationData
- : SignatureSubpacket
- {
- public const int HeaderFlagLength = 4;
- public const int HeaderNameLength = 2;
- public const int HeaderValueLength = 2;
-
- public NotationData(
- bool critical,
- byte[] data)
- : base(SignatureSubpacketTag.NotationData, critical, data)
- {
- }
-
- public NotationData(
- bool critical,
- bool humanReadable,
- string notationName,
- string notationValue)
- : base(SignatureSubpacketTag.NotationData, critical,
- createData(humanReadable, notationName, notationValue))
- {
- }
-
- private static byte[] createData(
- bool humanReadable,
- string notationName,
- string notationValue)
- {
- MemoryStream os = new MemoryStream();
-
- // (4 octets of flags, 2 octets of name length (M),
- // 2 octets of value length (N),
- // M octets of name data,
- // N octets of value data)
-
- // flags
- os.WriteByte(humanReadable ? (byte)0x80 : (byte)0x00);
- os.WriteByte(0x0);
- os.WriteByte(0x0);
- os.WriteByte(0x0);
-
- byte[] nameData, valueData = null;
- int nameLength, valueLength;
-
- nameData = Encoding.UTF8.GetBytes(notationName);
- nameLength = System.Math.Min(nameData.Length, 0xFF);
-
- valueData = Encoding.UTF8.GetBytes(notationValue);
- valueLength = System.Math.Min(valueData.Length, 0xFF);
-
- // name length
- os.WriteByte((byte)(nameLength >> 8));
- os.WriteByte((byte)(nameLength >> 0));
-
- // value length
- os.WriteByte((byte)(valueLength >> 8));
- os.WriteByte((byte)(valueLength >> 0));
-
- // name
- os.Write(nameData, 0, nameLength);
-
- // value
- os.Write(valueData, 0, valueLength);
-
- return os.ToArray();
- }
-
- public bool IsHumanReadable
- {
- get { return data[0] == (byte)0x80; }
- }
-
- public string GetNotationName()
- {
- int nameLength = ((data[HeaderFlagLength] << 8) + (data[HeaderFlagLength + 1] << 0));
- int namePos = HeaderFlagLength + HeaderNameLength + HeaderValueLength;
-
- return Encoding.UTF8.GetString(data, namePos, nameLength);
- }
-
- public string GetNotationValue()
- {
- int nameLength = ((data[HeaderFlagLength] << 8) + (data[HeaderFlagLength + 1] << 0));
- int valueLength = ((data[HeaderFlagLength + HeaderNameLength] << 8) + (data[HeaderFlagLength + HeaderNameLength + 1] << 0));
- int valuePos = HeaderFlagLength + HeaderNameLength + HeaderValueLength + nameLength;
-
- return Encoding.UTF8.GetString(data, valuePos, valueLength);
- }
- }
-}
+using System;
+using System.IO;
+using System.Text;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+ /**
+ * Class provided a NotationData object according to
+ * RFC2440, Chapter 5.2.3.15. Notation Data
+ */
+ public class NotationData
+ : SignatureSubpacket
+ {
+ public const int HeaderFlagLength = 4;
+ public const int HeaderNameLength = 2;
+ public const int HeaderValueLength = 2;
+
+ public NotationData(
+ bool critical,
+ byte[] data)
+ : base(SignatureSubpacketTag.NotationData, critical, data)
+ {
+ }
+
+ public NotationData(
+ bool critical,
+ bool humanReadable,
+ string notationName,
+ string notationValue)
+ : base(SignatureSubpacketTag.NotationData, critical,
+ createData(humanReadable, notationName, notationValue))
+ {
+ }
+
+ private static byte[] createData(
+ bool humanReadable,
+ string notationName,
+ string notationValue)
+ {
+ MemoryStream os = new MemoryStream();
+
+ // (4 octets of flags, 2 octets of name length (M),
+ // 2 octets of value length (N),
+ // M octets of name data,
+ // N octets of value data)
+
+ // flags
+ os.WriteByte(humanReadable ? (byte)0x80 : (byte)0x00);
+ os.WriteByte(0x0);
+ os.WriteByte(0x0);
+ os.WriteByte(0x0);
+
+ byte[] nameData, valueData = null;
+ int nameLength, valueLength;
+
+ nameData = Encoding.UTF8.GetBytes(notationName);
+ nameLength = System.Math.Min(nameData.Length, 0xFF);
+
+ valueData = Encoding.UTF8.GetBytes(notationValue);
+ valueLength = System.Math.Min(valueData.Length, 0xFF);
+
+ // name length
+ os.WriteByte((byte)(nameLength >> 8));
+ os.WriteByte((byte)(nameLength >> 0));
+
+ // value length
+ os.WriteByte((byte)(valueLength >> 8));
+ os.WriteByte((byte)(valueLength >> 0));
+
+ // name
+ os.Write(nameData, 0, nameLength);
+
+ // value
+ os.Write(valueData, 0, valueLength);
+
+ return os.ToArray();
+ }
+
+ public bool IsHumanReadable
+ {
+ get { return data[0] == (byte)0x80; }
+ }
+
+ public string GetNotationName()
+ {
+ int nameLength = ((data[HeaderFlagLength] << 8) + (data[HeaderFlagLength + 1] << 0));
+ int namePos = HeaderFlagLength + HeaderNameLength + HeaderValueLength;
+
+ return Encoding.UTF8.GetString(data, namePos, nameLength);
+ }
+
+ public string GetNotationValue()
+ {
+ int nameLength = ((data[HeaderFlagLength] << 8) + (data[HeaderFlagLength + 1] << 0));
+ int valueLength = ((data[HeaderFlagLength + HeaderNameLength] << 8) + (data[HeaderFlagLength + HeaderNameLength + 1] << 0));
+ int valuePos = HeaderFlagLength + HeaderNameLength + HeaderValueLength + nameLength;
+
+ return Encoding.UTF8.GetString(data, valuePos, valueLength);
+ }
+
+ public byte[] GetNotationValueBytes()
+ {
+ int nameLength = ((data[HeaderFlagLength] << 8) + (data[HeaderFlagLength + 1] << 0));
+ int valueLength = ((data[HeaderFlagLength + HeaderNameLength] << 8) + (data[HeaderFlagLength + HeaderNameLength + 1] << 0));
+ int valuePos = HeaderFlagLength + HeaderNameLength + HeaderValueLength + nameLength;
+
+ byte[] bytes = new byte[valueLength];
+ Array.Copy(data, valuePos, bytes, 0, valueLength);
+ return bytes;
+ }
+ }
+}
diff --git a/src/core/srcbc/bcpg/sig/TrustSignature.cs b/src/core/srcbc/bcpg/sig/TrustSignature.cs
index ba8d560..bbadd30 100644
--- a/src/core/srcbc/bcpg/sig/TrustSignature.cs
+++ b/src/core/srcbc/bcpg/sig/TrustSignature.cs
@@ -1,56 +1,43 @@
-using System;
-
-
-
-namespace Org.BouncyCastle.Bcpg.Sig
-{
- /**
- * packet giving signature creation time.
- */
- public class TrustSignature
- : SignatureSubpacket
- {
- private static byte[] IntToByteArray(
- int v1,
- int v2)
- {
- byte[] data = new byte[2];
-
- data[0] = (byte)v1;
- data[1] = (byte)v2;
-
- return data;
- }
-
- public TrustSignature(
- bool critical,
- byte[] data)
- : base(SignatureSubpacketTag.TrustSig, critical, data)
- {
- }
-
- public TrustSignature(
- bool critical,
- int depth,
- int trustAmount)
- : base(SignatureSubpacketTag.TrustSig, critical, IntToByteArray(depth, trustAmount))
- {
- }
-
- public int Depth
- {
- get
- {
- return data[0] & 0xff;
- }
- }
-
- public int TrustAmount
- {
- get
- {
- return data[1] & 0xff;
- }
- }
- }
-}
+using System;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+ /**
+ * packet giving trust.
+ */
+ public class TrustSignature
+ : SignatureSubpacket
+ {
+ private static byte[] IntToByteArray(
+ int v1,
+ int v2)
+ {
+ return new byte[]{ (byte)v1, (byte)v2 };
+ }
+
+ public TrustSignature(
+ bool critical,
+ byte[] data)
+ : base(SignatureSubpacketTag.TrustSig, critical, data)
+ {
+ }
+
+ public TrustSignature(
+ bool critical,
+ int depth,
+ int trustAmount)
+ : base(SignatureSubpacketTag.TrustSig, critical, IntToByteArray(depth, trustAmount))
+ {
+ }
+
+ public int Depth
+ {
+ get { return data[0] & 0xff; }
+ }
+
+ public int TrustAmount
+ {
+ get { return data[1] & 0xff; }
+ }
+ }
+}
diff --git a/src/core/srcbc/cms/CMSPBEKey.cs b/src/core/srcbc/cms/CMSPBEKey.cs
index 5672fce..5c8d895 100644
--- a/src/core/srcbc/cms/CMSPBEKey.cs
+++ b/src/core/srcbc/cms/CMSPBEKey.cs
@@ -1,68 +1,86 @@
-using System;
-
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Utilities;
-
-//import javax.crypto.interfaces.PBEKey;
-
-namespace Org.BouncyCastle.Cms
-{
- public abstract class CmsPbeKey
- // TODO Create an equivalent interface somewhere?
- // : PBEKey
- : ICipherParameters
- {
- private readonly string password;
- private readonly byte[] salt;
- private readonly int iterationCount;
-
- public CmsPbeKey(
- string password,
- byte[] salt,
- int iterationCount)
- {
- this.password = password;
- this.salt = Arrays.Clone(salt);
- this.iterationCount = iterationCount;
- }
-
- public string Password
- {
- get { return password; }
- }
-
- public byte[] Salt
- {
- get { return Arrays.Clone(salt); }
- }
-
- [Obsolete("Use 'Salt' property instead")]
- public byte[] GetSalt()
- {
- return Salt;
- }
-
- public int IterationCount
- {
- get { return iterationCount; }
- }
-
- public string Algorithm
- {
- get { return "PKCS5S2"; }
- }
-
- public string Format
- {
- get { return "RAW"; }
- }
-
- public byte[] GetEncoded()
- {
- return null;
- }
-
- internal abstract KeyParameter GetEncoded(string algorithmOid);
- }
-}
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+//import javax.crypto.interfaces.PBEKey;
+
+namespace Org.BouncyCastle.Cms
+{
+ public abstract class CmsPbeKey
+ // TODO Create an equivalent interface somewhere?
+ // : PBEKey
+ : ICipherParameters
+ {
+ private readonly string password;
+ private readonly byte[] salt;
+ private readonly int iterationCount;
+
+ public CmsPbeKey(
+ string password,
+ byte[] salt,
+ int iterationCount)
+ {
+ this.password = password;
+ this.salt = Arrays.Clone(salt);
+ this.iterationCount = iterationCount;
+ }
+
+ public CmsPbeKey(
+ string password,
+ AlgorithmIdentifier keyDerivationAlgorithm)
+ {
+ if (!keyDerivationAlgorithm.ObjectID.Equals(PkcsObjectIdentifiers.IdPbkdf2))
+ throw new ArgumentException("Unsupported key derivation algorithm: "
+ + keyDerivationAlgorithm.ObjectID);
+
+ Pbkdf2Params kdfParams = Pbkdf2Params.GetInstance(
+ keyDerivationAlgorithm.Parameters.ToAsn1Object());
+
+ this.password = password;
+ this.salt = kdfParams.GetSalt();
+ this.iterationCount = kdfParams.IterationCount.IntValue;
+ }
+
+ public string Password
+ {
+ get { return password; }
+ }
+
+ public byte[] Salt
+ {
+ get { return Arrays.Clone(salt); }
+ }
+
+ [Obsolete("Use 'Salt' property instead")]
+ public byte[] GetSalt()
+ {
+ return Salt;
+ }
+
+ public int IterationCount
+ {
+ get { return iterationCount; }
+ }
+
+ public string Algorithm
+ {
+ get { return "PKCS5S2"; }
+ }
+
+ public string Format
+ {
+ get { return "RAW"; }
+ }
+
+ public byte[] GetEncoded()
+ {
+ return null;
+ }
+
+ internal abstract KeyParameter GetEncoded(string algorithmOid);
+ }
+}
diff --git a/src/core/srcbc/cms/CMSSignedDataGenerator.cs b/src/core/srcbc/cms/CMSSignedDataGenerator.cs
index 3fce2d2..3db7f3d 100644
--- a/src/core/srcbc/cms/CMSSignedDataGenerator.cs
+++ b/src/core/srcbc/cms/CMSSignedDataGenerator.cs
@@ -1,492 +1,577 @@
-using System;
-using System.Collections;
-using System.IO;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Asn1.Cms;
-using Org.BouncyCastle.Asn1.Pkcs;
-using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Security.Certificates;
-using Org.BouncyCastle.Utilities.IO;
-using Org.BouncyCastle.X509;
-
-namespace Org.BouncyCastle.Cms
-{
- /**
- * general class for generating a pkcs7-signature message.
- *
- * A simple example of usage.
- *
- *
- * IX509Store certs...
- * IX509Store crls...
- * CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
- *
- * gen.AddSigner(privKey, cert, CmsSignedGenerator.DigestSha1);
- * gen.AddCertificates(certs);
- * gen.AddCrls(crls);
- *
- * CmsSignedData data = gen.Generate(content);
- *
- *
- */
- public class CmsSignedDataGenerator
- : CmsSignedGenerator
- {
- private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
-
- private readonly ArrayList signerInfs = new ArrayList();
-
- internal class DigOutputStream
- : BaseOutputStream
- {
- private readonly IDigest dig;
-
- public DigOutputStream(
- IDigest dig)
- {
- this.dig = dig;
- }
-
- public override void Write(
- byte[] b,
- int off,
- int len)
- {
- dig.BlockUpdate(b, off, len);
- }
-
- public override void WriteByte(
- byte b)
- {
- dig.Update(b);
- }
- }
-
- internal class SigOutputStream
- : BaseOutputStream
- {
- private readonly ISigner sig;
-
- public SigOutputStream(
- ISigner sig)
- {
- this.sig = sig;
- }
-
- public override void Write(
- byte[] b,
- int off,
- int len)
- {
- try
- {
- sig.BlockUpdate(b, off, len);
- }
- catch (SignatureException e)
- {
- throw new IOException("signature problem: " + e);
- }
- }
-
- public override void WriteByte(
- byte b)
- {
- try
- {
- sig.Update(b);
- }
- catch (SignatureException e)
- {
- throw new IOException("signature problem: " + e);
- }
- }
- }
-
- private class SignerInf
- {
- CmsSignedGenerator outer;
- AsymmetricKeyParameter key;
- X509Certificate cert;
- string digestOID;
- string encOID;
- CmsAttributeTableGenerator sAttr;
- CmsAttributeTableGenerator unsAttr;
- Asn1.Cms.AttributeTable baseSignedTable;
-
- internal SignerInf(
- CmsSignedGenerator outer,
- AsymmetricKeyParameter key,
- X509Certificate cert,
- string digestOID,
- string encOID)
- {
- this.outer = outer;
- this.key = key;
- this.cert = cert;
- this.digestOID = digestOID;
- this.encOID = encOID;
- }
-
- internal SignerInf(
- CmsSignedGenerator outer,
- AsymmetricKeyParameter key,
- X509Certificate cert,
- string digestOID,
- string encOID,
- CmsAttributeTableGenerator sAttr,
- CmsAttributeTableGenerator unsAttr,
- Asn1.Cms.AttributeTable baseSignedTable)
- {
- this.outer = outer;
- this.key = key;
- this.cert = cert;
- this.digestOID = digestOID;
- this.encOID = encOID;
- this.sAttr = sAttr;
- this.unsAttr = unsAttr;
- this.baseSignedTable = baseSignedTable;
- }
-
- internal AsymmetricKeyParameter GetKey()
- {
- return key;
- }
-
- internal X509Certificate GetCertificate()
- {
- return cert;
- }
-
- internal AlgorithmIdentifier DigestAlgorithmID
- {
- get { return new AlgorithmIdentifier(new DerObjectIdentifier(digestOID), null); }
- }
-
- internal string DigestAlgOid
- {
- get { return digestOID; }
- }
-
- internal Asn1Object DigestAlgParams
- {
- get { return null; }
- }
-
- internal AlgorithmIdentifier EncryptionAlgorithmID
- {
- get { return new AlgorithmIdentifier(new DerObjectIdentifier(encOID), DerNull.Instance); }
- }
-
- internal string EncryptionAlgOid
- {
- get { return encOID; }
- }
-
- internal CmsAttributeTableGenerator SignedAttributes
- {
- get { return sAttr; }
- }
-
- internal CmsAttributeTableGenerator UnsignedAttributes
- {
- get { return unsAttr; }
- }
-
- internal Asn1.Cms.SignerInfo ToSignerInfo(
- DerObjectIdentifier contentType,
- CmsProcessable content,
- SecureRandom random,
- bool isCounterSignature)
- {
- AlgorithmIdentifier digAlgId = new AlgorithmIdentifier(
- new DerObjectIdentifier(this.DigestAlgOid), DerNull.Instance);
- AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(this.EncryptionAlgOid);
- string digestName = Helper.GetDigestAlgName(digestOID);
- string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
- ISigner sig = Helper.GetSignatureInstance(signatureName);
- IDigest dig = Helper.GetDigestInstance(digestName);
-
- byte[] hash = null;
-
- if (content != null)
- {
- content.Write(new DigOutputStream(dig));
-
- hash = DigestUtilities.DoFinal(dig);
-
- outer._digests.Add(digestOID, hash.Clone());
- }
-
- IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);
- Asn1.Cms.AttributeTable signed = (sAttr != null)
-// ? sAttr.GetAttributes(Collections.unmodifiableMap(parameters))
- ? sAttr.GetAttributes(parameters)
- : null;
-
- if (isCounterSignature)
- {
- Hashtable ats = signed.ToHashtable();
-
- ats.Remove(CmsAttributes.ContentType);
-
- signed = new Asn1.Cms.AttributeTable(ats);
- }
-
- Asn1Set signedAttr = outer.GetAttributeSet(signed);
-
-
- //
- // sig must be composed from the DER encoding.
- //
- byte[] tmp;
- if (signedAttr != null)
- {
- tmp = signedAttr.GetEncoded(Asn1Encodable.Der);
- }
- else
- {
- MemoryStream bOut = new MemoryStream();
- content.Write(bOut);
- tmp = bOut.ToArray();
- }
-
- sig.Init(true, new ParametersWithRandom(key, random));
- sig.BlockUpdate(tmp, 0, tmp.Length);
-
- Asn1OctetString encDigest = new DerOctetString(sig.GenerateSignature());
-
- IDictionary baseParameters = outer.GetBaseParameters(contentType, digAlgId, hash);
- baseParameters[CmsAttributeTableParameter.Signature] = encDigest.GetOctets().Clone();
-
- Asn1.Cms.AttributeTable unsigned = (unsAttr != null)
-// ? unsAttr.GetAttributes(Collections.unmodifiableMap(baseParameters))
- ? unsAttr.GetAttributes(baseParameters)
- : null;
-
- Asn1Set unsignedAttr = outer.GetAttributeSet(unsigned);
-
- X509Certificate cert = this.GetCertificate();
- TbsCertificateStructure tbs = TbsCertificateStructure.GetInstance(
- Asn1Object.FromByteArray(cert.GetTbsCertificate()));
- Asn1.Cms.IssuerAndSerialNumber encSid = new Asn1.Cms.IssuerAndSerialNumber(
- tbs.Issuer, tbs.SerialNumber.Value);
-
- return new Asn1.Cms.SignerInfo(new SignerIdentifier(encSid), digAlgId,
- signedAttr, encAlgId, encDigest, unsignedAttr);
- }
- }
-
- public CmsSignedDataGenerator()
- {
- }
-
- /// Constructor allowing specific source of randomness
- /// Instance of SecureRandom to use.
- public CmsSignedDataGenerator(
- SecureRandom rand)
- : base(rand)
- {
- }
-
- /**
- * add a signer - no attributes other than the default ones will be
- * provided here.
- */
- public void AddSigner(
- AsymmetricKeyParameter privateKey,
- X509Certificate cert,
- string digestOID)
- {
- string encOID = GetEncOid(privateKey, digestOID);
-
- signerInfs.Add(new SignerInf(this, privateKey, cert, digestOID, encOID,
- new DefaultSignedAttributeTableGenerator(), null, null));
- }
-
- /**
- * add a signer with extra signed/unsigned attributes.
- */
- public void AddSigner(
- AsymmetricKeyParameter privateKey,
- X509Certificate cert,
- string digestOID,
- Asn1.Cms.AttributeTable signedAttr,
- Asn1.Cms.AttributeTable unsignedAttr)
- {
- string encOID = GetEncOid(privateKey, digestOID);
-
- signerInfs.Add(new SignerInf(this, privateKey, cert, digestOID, encOID,
- new DefaultSignedAttributeTableGenerator(signedAttr),
- new SimpleAttributeTableGenerator(unsignedAttr),
- signedAttr));
- }
-
- /**
- * add a signer with extra signed/unsigned attributes based on generators.
- */
- public void AddSigner(
- AsymmetricKeyParameter privateKey,
- X509Certificate cert,
- string digestOID,
- CmsAttributeTableGenerator signedAttrGen,
- CmsAttributeTableGenerator unsignedAttrGen)
- {
- string encOID = GetEncOid(privateKey, digestOID);
-
- signerInfs.Add(new SignerInf(this, privateKey, cert, digestOID, encOID,
- signedAttrGen, unsignedAttrGen, null));
- }
-
- /**
- * generate a signed object that for a CMS Signed Data object
- */
- public CmsSignedData Generate(
- CmsProcessable content)
- {
- return Generate(content, false);
- }
-
- /**
- * generate a signed object that for a CMS Signed Data
- * object - if encapsulate is true a copy
- * of the message will be included in the signature. The content type
- * is set according to the OID represented by the string signedContentType.
- */
- public CmsSignedData Generate(
- string signedContentType,
- CmsProcessable content,
- bool encapsulate)
- {
- Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
- Asn1EncodableVector signerInfos = new Asn1EncodableVector();
-
- _digests.Clear(); // clear the current preserved digest state
-
- //
- // add the precalculated SignerInfo objects.
- //
- foreach (SignerInformation signer in _signers)
- {
- digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
- signerInfos.Add(signer.ToSignerInfo());
- }
-
- //
- // add the SignerInfo objects
- //
- DerObjectIdentifier contentTypeOID;
- bool isCounterSignature;
-
- if (signedContentType != null)
- {
- contentTypeOID = new DerObjectIdentifier(signedContentType);
- isCounterSignature = false;
- }
- else
- {
- contentTypeOID = CmsObjectIdentifiers.Data;
- isCounterSignature = true;
- }
-
- foreach (SignerInf signer in signerInfs)
- {
- try
- {
- digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
- signerInfos.Add(signer.ToSignerInfo(contentTypeOID, content, rand, isCounterSignature));
- }
- catch (IOException e)
- {
- throw new CmsException("encoding error.", e);
- }
- catch (InvalidKeyException e)
- {
- throw new CmsException("key inappropriate for signature.", e);
- }
- catch (SignatureException e)
- {
- throw new CmsException("error creating signature.", e);
- }
- catch (CertificateEncodingException e)
- {
- throw new CmsException("error creating sid.", e);
- }
- }
-
- Asn1Set certificates = null;
-
- if (_certs.Count != 0)
- {
- certificates = CmsUtilities.CreateBerSetFromList(_certs);
- }
-
- Asn1Set certrevlist = null;
-
- if (_crls.Count != 0)
- {
- certrevlist = CmsUtilities.CreateBerSetFromList(_crls);
- }
-
- Asn1OctetString octs = null;
- if (encapsulate)
- {
- MemoryStream bOut = new MemoryStream();
- try
- {
- content.Write(bOut);
- }
- catch (IOException e)
- {
- throw new CmsException("encapsulation error.", e);
- }
-
- octs = new BerOctetString(bOut.ToArray());
- }
-
- Asn1.Cms.ContentInfo encInfo = new Asn1.Cms.ContentInfo(contentTypeOID, octs);
-
- Asn1.Cms.SignedData sd = new Asn1.Cms.SignedData(
- new DerSet(digestAlgs),
- encInfo,
- certificates,
- certrevlist,
- new DerSet(signerInfos));
-
- Asn1.Cms.ContentInfo contentInfo = new Asn1.Cms.ContentInfo(
- PkcsObjectIdentifiers.SignedData, sd);
-
- return new CmsSignedData(content, contentInfo);
- }
-
- /**
- * generate a signed object that for a CMS Signed Data
- * object - if encapsulate is true a copy
- * of the message will be included in the signature with the
- * default content type "data".
- */
- public CmsSignedData Generate(
- CmsProcessable content,
- bool encapsulate)
- {
- return this.Generate(Data, content, encapsulate);
- }
-
- /**
- * generate a set of one or more SignerInformation objects representing counter signatures on
- * the passed in SignerInformation object.
- *
- * @param signer the signer to be countersigned
- * @param sigProvider the provider to be used for counter signing.
- * @return a store containing the signers.
- */
- public SignerInformationStore GenerateCounterSigners(
- SignerInformation signer)
- {
- return this.Generate(null, new CmsProcessableByteArray(signer.GetSignature()), false).GetSignerInfos();
- }
- }
-}
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+ /**
+ * general class for generating a pkcs7-signature message.
+ *
+ * A simple example of usage.
+ *
+ *
+ * IX509Store certs...
+ * IX509Store crls...
+ * CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+ *
+ * gen.AddSigner(privKey, cert, CmsSignedGenerator.DigestSha1);
+ * gen.AddCertificates(certs);
+ * gen.AddCrls(crls);
+ *
+ * CmsSignedData data = gen.Generate(content);
+ *
+ *
+ */
+ public class CmsSignedDataGenerator
+ : CmsSignedGenerator
+ {
+ private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
+
+ private readonly ArrayList signerInfs = new ArrayList();
+
+ internal class DigOutputStream
+ : BaseOutputStream
+ {
+ private readonly IDigest dig;
+
+ public DigOutputStream(
+ IDigest dig)
+ {
+ this.dig = dig;
+ }
+
+ public override void Write(
+ byte[] b,
+ int off,
+ int len)
+ {
+ dig.BlockUpdate(b, off, len);
+ }
+
+ public override void WriteByte(
+ byte b)
+ {
+ dig.Update(b);
+ }
+ }
+
+ internal class SigOutputStream
+ : BaseOutputStream
+ {
+ private readonly ISigner sig;
+
+ public SigOutputStream(
+ ISigner sig)
+ {
+ this.sig = sig;
+ }
+
+ public override void Write(
+ byte[] b,
+ int off,
+ int len)
+ {
+ try
+ {
+ sig.BlockUpdate(b, off, len);
+ }
+ catch (SignatureException e)
+ {
+ throw new IOException("signature problem: " + e);
+ }
+ }
+
+ public override void WriteByte(
+ byte b)
+ {
+ try
+ {
+ sig.Update(b);
+ }
+ catch (SignatureException e)
+ {
+ throw new IOException("signature problem: " + e);
+ }
+ }
+ }
+
+ private class SignerInf
+ {
+ private CmsSignedGenerator outer;
+ private AsymmetricKeyParameter key;
+ private X509Certificate cert;
+ private string digestOID;
+ private string encOID;
+ private CmsAttributeTableGenerator sAttr;
+ private CmsAttributeTableGenerator unsAttr;
+ private Asn1.Cms.AttributeTable baseSignedTable;
+ private byte[] keyIdentifier;
+
+ internal SignerInf(
+ CmsSignedGenerator outer,
+ AsymmetricKeyParameter key,
+ X509Certificate cert,
+ string digestOID,
+ string encOID)
+ : this(outer, key, cert, digestOID, encOID, null, null, null)
+ {
+ }
+
+ internal SignerInf(
+ CmsSignedGenerator outer,
+ AsymmetricKeyParameter key,
+ byte[] keyIdentifier,
+ string digestOID,
+ string encOID)
+ : this(outer, key, keyIdentifier, digestOID, encOID, null, null, null)
+ {
+ }
+
+ internal SignerInf(
+ CmsSignedGenerator outer,
+ AsymmetricKeyParameter key,
+ X509Certificate cert,
+ string digestOID,
+ string encOID,
+ CmsAttributeTableGenerator sAttr,
+ CmsAttributeTableGenerator unsAttr,
+ Asn1.Cms.AttributeTable baseSignedTable)
+ {
+ this.outer = outer;
+ this.key = key;
+ this.cert = cert;
+ this.digestOID = digestOID;
+ this.encOID = encOID;
+ this.sAttr = sAttr;
+ this.unsAttr = unsAttr;
+ this.baseSignedTable = baseSignedTable;
+ }
+
+ internal SignerInf(
+ CmsSignedGenerator outer,
+ AsymmetricKeyParameter key,
+ byte[] keyIdentifier,
+ string digestOID,
+ string encOID,
+ CmsAttributeTableGenerator sAttr,
+ CmsAttributeTableGenerator unsAttr,
+ Asn1.Cms.AttributeTable baseSignedTable)
+ {
+ this.outer = outer;
+ this.key = key;
+ this.keyIdentifier = keyIdentifier;
+ this.digestOID = digestOID;
+ this.encOID = encOID;
+ this.sAttr = sAttr;
+ this.unsAttr = unsAttr;
+ this.baseSignedTable = baseSignedTable;
+ }
+
+ internal AsymmetricKeyParameter GetKey()
+ {
+ return key;
+ }
+
+ internal X509Certificate GetCertificate()
+ {
+ return cert;
+ }
+
+ internal AlgorithmIdentifier DigestAlgorithmID
+ {
+ get { return new AlgorithmIdentifier(new DerObjectIdentifier(digestOID), null); }
+ }
+
+ internal string DigestAlgOid
+ {
+ get { return digestOID; }
+ }
+
+ internal Asn1Object DigestAlgParams
+ {
+ get { return null; }
+ }
+
+ internal AlgorithmIdentifier EncryptionAlgorithmID
+ {
+ get { return new AlgorithmIdentifier(new DerObjectIdentifier(encOID), DerNull.Instance); }
+ }
+
+ internal string EncryptionAlgOid
+ {
+ get { return encOID; }
+ }
+
+ internal CmsAttributeTableGenerator SignedAttributes
+ {
+ get { return sAttr; }
+ }
+
+ internal CmsAttributeTableGenerator UnsignedAttributes
+ {
+ get { return unsAttr; }
+ }
+
+ internal Asn1.Cms.SignerInfo ToSignerInfo(
+ DerObjectIdentifier contentType,
+ CmsProcessable content,
+ SecureRandom random,
+ bool isCounterSignature)
+ {
+ AlgorithmIdentifier digAlgId = new AlgorithmIdentifier(
+ new DerObjectIdentifier(this.DigestAlgOid), DerNull.Instance);
+ AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(this.EncryptionAlgOid);
+ string digestName = Helper.GetDigestAlgName(digestOID);
+ string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
+ ISigner sig = Helper.GetSignatureInstance(signatureName);
+ IDigest dig = Helper.GetDigestInstance(digestName);
+
+ byte[] hash = null;
+
+ if (content != null)
+ {
+ content.Write(new DigOutputStream(dig));
+
+ hash = DigestUtilities.DoFinal(dig);
+
+ outer._digests.Add(digestOID, hash.Clone());
+ }
+
+ IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);
+ Asn1.Cms.AttributeTable signed = (sAttr != null)
+// ? sAttr.GetAttributes(Collections.unmodifiableMap(parameters))
+ ? sAttr.GetAttributes(parameters)
+ : null;
+
+ if (isCounterSignature)
+ {
+ Hashtable ats = signed.ToHashtable();
+
+ ats.Remove(CmsAttributes.ContentType);
+
+ signed = new Asn1.Cms.AttributeTable(ats);
+ }
+
+ Asn1Set signedAttr = outer.GetAttributeSet(signed);
+
+
+ //
+ // sig must be composed from the DER encoding.
+ //
+ byte[] tmp;
+ if (signedAttr != null)
+ {
+ tmp = signedAttr.GetEncoded(Asn1Encodable.Der);
+ }
+ else
+ {
+ MemoryStream bOut = new MemoryStream();
+ content.Write(bOut);
+ tmp = bOut.ToArray();
+ }
+
+ sig.Init(true, new ParametersWithRandom(key, random));
+ sig.BlockUpdate(tmp, 0, tmp.Length);
+
+ Asn1OctetString encDigest = new DerOctetString(sig.GenerateSignature());
+
+ IDictionary baseParameters = outer.GetBaseParameters(contentType, digAlgId, hash);
+ baseParameters[CmsAttributeTableParameter.Signature] = encDigest.GetOctets().Clone();
+
+ Asn1.Cms.AttributeTable unsigned = (unsAttr != null)
+// ? unsAttr.GetAttributes(Collections.unmodifiableMap(baseParameters))
+ ? unsAttr.GetAttributes(baseParameters)
+ : null;
+
+ Asn1Set unsignedAttr = outer.GetAttributeSet(unsigned);
+
+ X509Certificate cert = this.GetCertificate();
+ SignerIdentifier identifier;
+ if (cert != null)
+ {
+ TbsCertificateStructure tbs = TbsCertificateStructure.GetInstance(
+ Asn1Object.FromByteArray(cert.GetTbsCertificate()));
+ Asn1.Cms.IssuerAndSerialNumber encSid = new Asn1.Cms.IssuerAndSerialNumber(
+ tbs.Issuer, tbs.SerialNumber.Value);
+ identifier = new SignerIdentifier(encSid);
+ }
+ else
+ {
+ identifier = new SignerIdentifier(new DerOctetString(keyIdentifier));
+ }
+
+ return new Asn1.Cms.SignerInfo(identifier, digAlgId,
+ signedAttr, encAlgId, encDigest, unsignedAttr);
+ }
+ }
+
+ public CmsSignedDataGenerator()
+ {
+ }
+
+ /// Constructor allowing specific source of randomness
+ /// Instance of SecureRandom to use.
+ public CmsSignedDataGenerator(
+ SecureRandom rand)
+ : base(rand)
+ {
+ }
+
+ /**
+ * add a signer - no attributes other than the default ones will be
+ * provided here.
+ */
+ public void AddSigner(
+ AsymmetricKeyParameter privateKey,
+ X509Certificate cert,
+ string digestOID)
+ {
+ string encOID = GetEncOid(privateKey, digestOID);
+
+ signerInfs.Add(new SignerInf(this, privateKey, cert, digestOID, encOID,
+ new DefaultSignedAttributeTableGenerator(), null, null));
+ }
+
+ /**
+ * add a signer - no attributes other than the default ones will be
+ * provided here.
+ */
+ public void AddSigner(
+ AsymmetricKeyParameter privateKey,
+ byte[] subjectKeyID,
+ string digestOID)
+ {
+ string encOID = GetEncOid(privateKey, digestOID);
+
+ signerInfs.Add(new SignerInf(this, privateKey, subjectKeyID, digestOID, encOID,
+ new DefaultSignedAttributeTableGenerator(), null, null));
+ }
+
+ /**
+ * add a signer with extra signed/unsigned attributes.
+ */
+ public void AddSigner(
+ AsymmetricKeyParameter privateKey,
+ X509Certificate cert,
+ string digestOID,
+ Asn1.Cms.AttributeTable signedAttr,
+ Asn1.Cms.AttributeTable unsignedAttr)
+ {
+ string encOID = GetEncOid(privateKey, digestOID);
+
+ signerInfs.Add(new SignerInf(this, privateKey, cert, digestOID, encOID,
+ new DefaultSignedAttributeTableGenerator(signedAttr),
+ new SimpleAttributeTableGenerator(unsignedAttr),
+ signedAttr));
+ }
+
+ /**
+ * add a signer with extra signed/unsigned attributes.
+ */
+ public void AddSigner(
+ AsymmetricKeyParameter privateKey,
+ byte[] subjectKeyID,
+ string digestOID,
+ Asn1.Cms.AttributeTable signedAttr,
+ Asn1.Cms.AttributeTable unsignedAttr)
+ {
+ string encOID = GetEncOid(privateKey, digestOID);
+
+ signerInfs.Add(new SignerInf(this, privateKey, subjectKeyID, digestOID, encOID,
+ new DefaultSignedAttributeTableGenerator(signedAttr),
+ new SimpleAttributeTableGenerator(unsignedAttr),
+ signedAttr));
+ }
+
+ /**
+ * add a signer with extra signed/unsigned attributes based on generators.
+ */
+ public void AddSigner(
+ AsymmetricKeyParameter privateKey,
+ X509Certificate cert,
+ string digestOID,
+ CmsAttributeTableGenerator signedAttrGen,
+ CmsAttributeTableGenerator unsignedAttrGen)
+ {
+ string encOID = GetEncOid(privateKey, digestOID);
+
+ signerInfs.Add(new SignerInf(this, privateKey, cert, digestOID, encOID,
+ signedAttrGen, unsignedAttrGen, null));
+ }
+
+ /**
+ * add a signer with extra signed/unsigned attributes based on generators.
+ */
+ public void AddSigner(
+ AsymmetricKeyParameter privateKey,
+ byte[] subjectKeyID,
+ string digestOID,
+ CmsAttributeTableGenerator signedAttrGen,
+ CmsAttributeTableGenerator unsignedAttrGen)
+ {
+ string encOID = GetEncOid(privateKey, digestOID);
+
+ signerInfs.Add(new SignerInf(this, privateKey, subjectKeyID, digestOID, encOID,
+ signedAttrGen, unsignedAttrGen, null));
+ }
+
+ /**
+ * generate a signed object that for a CMS Signed Data object
+ */
+ public CmsSignedData Generate(
+ CmsProcessable content)
+ {
+ return Generate(content, false);
+ }
+
+ /**
+ * generate a signed object that for a CMS Signed Data
+ * object - if encapsulate is true a copy
+ * of the message will be included in the signature. The content type
+ * is set according to the OID represented by the string signedContentType.
+ */
+ public CmsSignedData Generate(
+ string signedContentType,
+ CmsProcessable content,
+ bool encapsulate)
+ {
+ Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
+ Asn1EncodableVector signerInfos = new Asn1EncodableVector();
+
+ _digests.Clear(); // clear the current preserved digest state
+
+ //
+ // add the precalculated SignerInfo objects.
+ //
+ foreach (SignerInformation signer in _signers)
+ {
+ digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
+ signerInfos.Add(signer.ToSignerInfo());
+ }
+
+ //
+ // add the SignerInfo objects
+ //
+ DerObjectIdentifier contentTypeOID;
+ bool isCounterSignature;
+
+ if (signedContentType != null)
+ {
+ contentTypeOID = new DerObjectIdentifier(signedContentType);
+ isCounterSignature = false;
+ }
+ else
+ {
+ contentTypeOID = CmsObjectIdentifiers.Data;
+ isCounterSignature = true;
+ }
+
+ foreach (SignerInf signer in signerInfs)
+ {
+ try
+ {
+ digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
+ signerInfos.Add(signer.ToSignerInfo(contentTypeOID, content, rand, isCounterSignature));
+ }
+ catch (IOException e)
+ {
+ throw new CmsException("encoding error.", e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CmsException("key inappropriate for signature.", e);
+ }
+ catch (SignatureException e)
+ {
+ throw new CmsException("error creating signature.", e);
+ }
+ catch (CertificateEncodingException e)
+ {
+ throw new CmsException("error creating sid.", e);
+ }
+ }
+
+ Asn1Set certificates = null;
+
+ if (_certs.Count != 0)
+ {
+ certificates = CmsUtilities.CreateBerSetFromList(_certs);
+ }
+
+ Asn1Set certrevlist = null;
+
+ if (_crls.Count != 0)
+ {
+ certrevlist = CmsUtilities.CreateBerSetFromList(_crls);
+ }
+
+ Asn1OctetString octs = null;
+ if (encapsulate)
+ {
+ MemoryStream bOut = new MemoryStream();
+ try
+ {
+ content.Write(bOut);
+ }
+ catch (IOException e)
+ {
+ throw new CmsException("encapsulation error.", e);
+ }
+
+ octs = new BerOctetString(bOut.ToArray());
+ }
+
+ Asn1.Cms.ContentInfo encInfo = new Asn1.Cms.ContentInfo(contentTypeOID, octs);
+
+ Asn1.Cms.SignedData sd = new Asn1.Cms.SignedData(
+ new DerSet(digestAlgs),
+ encInfo,
+ certificates,
+ certrevlist,
+ new DerSet(signerInfos));
+
+ Asn1.Cms.ContentInfo contentInfo = new Asn1.Cms.ContentInfo(
+ PkcsObjectIdentifiers.SignedData, sd);
+
+ return new CmsSignedData(content, contentInfo);
+ }
+
+ /**
+ * generate a signed object that for a CMS Signed Data
+ * object - if encapsulate is true a copy
+ * of the message will be included in the signature with the
+ * default content type "data".
+ */
+ public CmsSignedData Generate(
+ CmsProcessable content,
+ bool encapsulate)
+ {
+ return this.Generate(Data, content, encapsulate);
+ }
+
+ /**
+ * generate a set of one or more SignerInformation objects representing counter signatures on
+ * the passed in SignerInformation object.
+ *
+ * @param signer the signer to be countersigned
+ * @param sigProvider the provider to be used for counter signing.
+ * @return a store containing the signers.
+ */
+ public SignerInformationStore GenerateCounterSigners(
+ SignerInformation signer)
+ {
+ return this.Generate(null, new CmsProcessableByteArray(signer.GetSignature()), false).GetSignerInfos();
+ }
+ }
+}
diff --git a/src/core/srcbc/cms/CMSSignedDataParser.cs b/src/core/srcbc/cms/CMSSignedDataParser.cs
index 53a1f71..3a862f7 100644
--- a/src/core/srcbc/cms/CMSSignedDataParser.cs
+++ b/src/core/srcbc/cms/CMSSignedDataParser.cs
@@ -1,556 +1,455 @@
-using System;
-using System.Collections;
-using System.IO;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Asn1.Cms;
-using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.IO;
-using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Security.Certificates;
-using Org.BouncyCastle.Utilities;
-using Org.BouncyCastle.Utilities.IO;
-using Org.BouncyCastle.X509;
-using Org.BouncyCastle.X509.Store;
-
-namespace Org.BouncyCastle.Cms
-{
- /**
- * Parsing class for an CMS Signed Data object from an input stream.
- *
- * Note: that because we are in a streaming mode only one signer can be tried and it is important
- * that the methods on the parser are called in the appropriate order.
- *
- *
- * A simple example of usage for an encapsulated signature.
- *
- *
- * Two notes: first, in the example below the validity of
- * the certificate isn't verified, just the fact that one of the certs
- * matches the given signer, and, second, because we are in a streaming
- * mode the order of the operations is important.
- *
- *
- * CmsSignedDataParser sp = new CmsSignedDataParser(encapSigData);
- *
- * sp.GetSignedContent().Drain();
- *
- * IX509Store certs = sp.GetCertificates();
- * SignerInformationStore signers = sp.GetSignerInfos();
- *
- * foreach (SignerInformation signer in signers.GetSigners())
- * {
- * ArrayList certList = new ArrayList(certs.GetMatches(signer.SignerID));
- * X509Certificate cert = (X509Certificate) certList[0];
- *
- * Console.WriteLine("verify returns: " + signer.Verify(cert));
- * }
- *
- * Note also: this class does not introduce buffering - if you are processing large files you should create
- * the parser with:
- *
- * CmsSignedDataParser ep = new CmsSignedDataParser(new BufferedInputStream(encapSigData, bufSize));
- *
- * where bufSize is a suitably large buffer size.
- */
- public class CmsSignedDataParser
- : CmsContentInfoParser
- {
- private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
-
- private SignedDataParser _signedData;
- private CmsTypedStream _signedContent;
- private IDictionary _digests;
-
- private SignerInformationStore _signerInfoStore;
- private Asn1Set _certSet, _crlSet;
- private bool _isCertCrlParsed;
- private IX509Store _attributeStore;
- private IX509Store _certificateStore;
- private IX509Store _crlStore;
-
- public CmsSignedDataParser(
- byte[] sigBlock)
- : this(new MemoryStream(sigBlock, false))
- {
- }
-
- public CmsSignedDataParser(
- CmsTypedStream signedContent,
- byte[] sigBlock)
- : this(signedContent, new MemoryStream(sigBlock, false))
- {
- }
-
- /**
- * base constructor - with encapsulated content
- */
- public CmsSignedDataParser(
- Stream sigData)
- : this(null, sigData)
- {
- }
-
- /**
- * base constructor
- *
- * @param signedContent the content that was signed.
- * @param sigData the signature object.
- */
- public CmsSignedDataParser(
- CmsTypedStream signedContent,
- Stream sigData)
- : base(sigData)
- {
- try
- {
- this._signedContent = signedContent;
- this._signedData = SignedDataParser.GetInstance(this.contentInfo.GetContent(Asn1Tags.Sequence));
- this._digests = new Hashtable();
-
- Asn1SetParser digAlgs = _signedData.GetDigestAlgorithms();
- IAsn1Convertible o;
-
- while ((o = digAlgs.ReadObject()) != null)
- {
- AlgorithmIdentifier id = AlgorithmIdentifier.GetInstance(o.ToAsn1Object());
-
- try
- {
- string digestName = Helper.GetDigestAlgName(id.ObjectID.Id);
- IDigest dig = Helper.GetDigestInstance(digestName);
-
- this._digests[digestName] = dig;
- }
- catch (SecurityUtilityException)
- {
- // ignore
- }
- }
-
- //
- // If the message is simply a certificate chain message GetContent() may return null.
- //
- ContentInfoParser cont = _signedData.GetEncapContentInfo();
- Asn1OctetStringParser octs = (Asn1OctetStringParser)
- cont.GetContent(Asn1Tags.OctetString);
-
- if (octs != null)
- {
- CmsTypedStream ctStr = new CmsTypedStream(
- cont.ContentType.Id, octs.GetOctetStream());
-
- if (_signedContent == null)
- {
- this._signedContent = ctStr;
- }
- else
- {
- //
- // content passed in, need to read past empty encapsulated content info object if present
- //
- ctStr.Drain();
- }
- }
- }
- catch (IOException e)
- {
- throw new CmsException("io exception: " + e.Message, e);
- }
-
- if (_digests.Count < 1)
- {
- throw new CmsException("no digests could be created for message.");
- }
- }
-
- /**
- * Return the version number for the SignedData object
- *
- * @return the version number
- */
- public int Version
- {
- get { return _signedData.Version.Value.IntValue; }
- }
-
- /**
- * return the collection of signers that are associated with the
- * signatures for the message.
- * @throws CmsException
- */
- public SignerInformationStore GetSignerInfos()
- {
- if (_signerInfoStore == null)
- {
- PopulateCertCrlSets();
-
- IList signerInfos = new ArrayList();
- IDictionary hashes = new Hashtable();
-
- foreach (object digestKey in _digests.Keys)
- {
- hashes[digestKey] = DigestUtilities.DoFinal(
- (IDigest)_digests[digestKey]);
- }
-
- try
- {
- Asn1SetParser s = _signedData.GetSignerInfos();
- IAsn1Convertible o;
-
- while ((o = s.ReadObject()) != null)
- {
- SignerInfo info = SignerInfo.GetInstance(o.ToAsn1Object());
- string digestName = Helper.GetDigestAlgName(
- info.DigestAlgorithm.ObjectID.Id);
-
- byte[] hash = (byte[]) hashes[digestName];
- DerObjectIdentifier oid = new DerObjectIdentifier(_signedContent.ContentType);
-
- signerInfos.Add(new SignerInformation(info, oid, null, new BaseDigestCalculator(hash)));
- }
- }
- catch (IOException e)
- {
- throw new CmsException("io exception: " + e.Message, e);
- }
-
- _signerInfoStore = new SignerInformationStore(signerInfos);
- }
-
- return _signerInfoStore;
- }
-
- /**
- * return a X509Store containing the attribute certificates, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @return a store of attribute certificates
- * @exception org.bouncycastle.x509.NoSuchStoreException if the store type isn't available.
- * @exception CmsException if a general exception prevents creation of the X509Store
- */
- public IX509Store GetAttributeCertificates(
- string type)
- {
- if (_attributeStore == null)
- {
- PopulateCertCrlSets();
-
- _attributeStore = Helper.CreateAttributeStore(type, _certSet);
- }
-
- return _attributeStore;
- }
-
- /**
- * return a X509Store containing the public key certificates, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @return a store of public key certificates
- * @exception NoSuchStoreException if the store type isn't available.
- * @exception CmsException if a general exception prevents creation of the X509Store
- */
- public IX509Store GetCertificates(
- string type)
- {
- if (_certificateStore == null)
- {
- PopulateCertCrlSets();
-
- _certificateStore = Helper.CreateCertificateStore(type, _certSet);
- }
-
- return _certificateStore;
- }
-
- /**
- * return a X509Store containing CRLs, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @return a store of CRLs
- * @exception NoSuchStoreException if the store type isn't available.
- * @exception CmsException if a general exception prevents creation of the X509Store
- */
- public IX509Store GetCrls(
- string type)
- {
- if (_crlStore == null)
- {
- PopulateCertCrlSets();
-
- _crlStore = Helper.CreateCrlStore(type, _crlSet);
- }
-
- return _crlStore;
- }
-
- private void PopulateCertCrlSets()
- {
- if (_isCertCrlParsed)
- return;
-
- _isCertCrlParsed = true;
-
- try
- {
- // care! Streaming - Must process the GetCertificates() result before calling GetCrls()
- _certSet = GetAsn1Set(_signedData.GetCertificates());
- _crlSet = GetAsn1Set(_signedData.GetCrls());
- }
- catch (IOException e)
- {
- throw new CmsException("problem parsing cert/crl sets", e);
- }
- }
-
- public CmsTypedStream GetSignedContent()
- {
- if (_signedContent == null)
- {
- return null;
- }
-
- Stream digStream = _signedContent.ContentStream;
-
- foreach (IDigest digest in _digests.Values)
- {
- digStream = new DigestStream(digStream, digest, null);
- }
-
- return new CmsTypedStream(_signedContent.ContentType, digStream);
- }
-
- /**
- * Replace the signerinformation store associated with the passed
- * in message contained in the stream original with the new one passed in.
- * You would probably only want to do this if you wanted to change the unsigned
- * attributes associated with a signer, or perhaps delete one.
- *
- * The output stream is returned unclosed.
- *
- * @param original the signed data stream to be used as a base.
- * @param signerInformationStore the new signer information store to use.
- * @param out the stream to Write the new signed data object to.
- * @return out.
- */
- public static Stream ReplaceSigners(
- Stream original,
- SignerInformationStore signerInformationStore,
- Stream outStr)
- {
- Asn1StreamParser inStr = new Asn1StreamParser(original, CmsUtilities.MaximumMemory);
- ContentInfoParser contentInfo = new ContentInfoParser((Asn1SequenceParser)inStr.ReadObject());
- SignedDataParser signedData = SignedDataParser.GetInstance(contentInfo.GetContent(Asn1Tags.Sequence));
-
- BerSequenceGenerator sGen = new BerSequenceGenerator(outStr);
-
- sGen.AddObject(CmsObjectIdentifiers.SignedData);
-
- BerSequenceGenerator sigGen = new BerSequenceGenerator(sGen.GetRawOutputStream(), 0, true);
-
- // version number
- sigGen.AddObject(signedData.Version);
-
- // digests
- signedData.GetDigestAlgorithms().ToAsn1Object(); // skip old ones
-
- Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
-
- foreach (SignerInformation signer in signerInformationStore.GetSigners())
- {
- digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
- }
-
- WriteToGenerator(sigGen, new DerSet(digestAlgs));
-
- // encap content info
- ContentInfoParser encapContentInfo = signedData.GetEncapContentInfo();
-
- BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());
-
- eiGen.AddObject(encapContentInfo.ContentType);
-
- Asn1OctetStringParser octs = (Asn1OctetStringParser)encapContentInfo.GetContent(Asn1Tags.OctetString);
-
- if (octs != null)
- {
- PipeOctetString(octs, eiGen.GetRawOutputStream());
- }
-
- eiGen.Close();
-
-
- WriteSetToGeneratorTagged(sigGen, signedData.GetCertificates(), 0);
- WriteSetToGeneratorTagged(sigGen, signedData.GetCrls(), 1);
-
-
- Asn1EncodableVector signerInfos = new Asn1EncodableVector();
- foreach (SignerInformation signer in signerInformationStore.GetSigners())
- {
- signerInfos.Add(signer.ToSignerInfo());
- }
-
- WriteToGenerator(sigGen, new DerSet(signerInfos));
-
- sigGen.Close();
-
- sGen.Close();
-
- return outStr;
- }
-
- /**
- * Replace the certificate and CRL information associated with this
- * CMSSignedData object with the new one passed in.
- *
- * The output stream is returned unclosed.
- *
- * @param original the signed data stream to be used as a base.
- * @param certsAndCrls the new certificates and CRLs to be used.
- * @param out the stream to Write the new signed data object to.
- * @return out.
- * @exception CmsException if there is an error processing the CertStore
- */
- public static Stream ReplaceCertificatesAndCrls(
- Stream original,
- IX509Store x509Certs,
- IX509Store x509Crls,
- IX509Store x509AttrCerts,
- Stream outStr)
- {
- if (x509AttrCerts != null)
- throw Platform.CreateNotImplementedException("Currently can't replace attribute certificates");
-
- Asn1StreamParser inStr = new Asn1StreamParser(original, CmsUtilities.MaximumMemory);
- ContentInfoParser contentInfo = new ContentInfoParser((Asn1SequenceParser)inStr.ReadObject());
- SignedDataParser signedData = SignedDataParser.GetInstance(contentInfo.GetContent(Asn1Tags.Sequence));
-
- BerSequenceGenerator sGen = new BerSequenceGenerator(outStr);
-
- sGen.AddObject(CmsObjectIdentifiers.SignedData);
-
- BerSequenceGenerator sigGen = new BerSequenceGenerator(sGen.GetRawOutputStream(), 0, true);
-
- // version number
- sigGen.AddObject(signedData.Version);
-
- // digests
- WriteToGenerator(sigGen, signedData.GetDigestAlgorithms().ToAsn1Object());
-
- // encap content info
- ContentInfoParser encapContentInfo = signedData.GetEncapContentInfo();
-
- BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());
-
- eiGen.AddObject(encapContentInfo.ContentType);
-
- Asn1OctetStringParser octs = (Asn1OctetStringParser)
- encapContentInfo.GetContent(Asn1Tags.OctetString);
-
- if (octs != null)
- {
- PipeOctetString(octs, eiGen.GetRawOutputStream());
- }
-
- eiGen.Close();
-
- //
- // skip existing certs and CRLs
- //
- GetAsn1Set(signedData.GetCertificates());
- GetAsn1Set(signedData.GetCrls());
-
- //
- // replace the certs and crls in the SignedData object
- //
- Asn1Set certs;
- try
- {
- certs = CmsUtilities.CreateBerSetFromList(
- CmsUtilities.GetCertificatesFromStore(x509Certs));
- }
- catch (X509StoreException e)
- {
- throw new CmsException("error getting certs from certStore", e);
- }
-
- if (certs.Count > 0)
- {
- WriteToGenerator(sigGen, new DerTaggedObject(false, 0, certs));
- }
-
- Asn1Set crls;
- try
- {
- crls = CmsUtilities.CreateBerSetFromList(
- CmsUtilities.GetCrlsFromStore(x509Crls));
- }
- catch (X509StoreException e)
- {
- throw new CmsException("error getting crls from certStore", e);
- }
-
- if (crls.Count > 0)
- {
- WriteToGenerator(sigGen, new DerTaggedObject(false, 1, crls));
- }
-
- WriteToGenerator(sigGen, signedData.GetSignerInfos().ToAsn1Object());
-
- sigGen.Close();
-
- sGen.Close();
-
- return outStr;
- }
-
- private static void WriteSetToGeneratorTagged(
- Asn1Generator asn1Gen,
- Asn1SetParser asn1SetParser,
- int tagNo)
- {
- Asn1Set asn1Set = GetAsn1Set(asn1SetParser);
-
- if (asn1Set != null)
- {
- Asn1TaggedObject taggedObj = (asn1SetParser is BerSetParser)
- ? new BerTaggedObject(false, tagNo, asn1Set)
- : new DerTaggedObject(false, tagNo, asn1Set);
-
- WriteToGenerator(asn1Gen, taggedObj);
- }
- }
-
- private static Asn1Set GetAsn1Set(
- Asn1SetParser asn1SetParser)
- {
- return asn1SetParser == null
- ? null
- : Asn1Set.GetInstance(asn1SetParser.ToAsn1Object());
- }
-
- private static void WriteToGenerator(
- Asn1Generator ag,
- Asn1Encodable ae)
- {
- byte[] encoded = ae.GetEncoded();
- ag.GetRawOutputStream().Write(encoded, 0, encoded.Length);
- }
-
- private static void PipeOctetString(
- Asn1OctetStringParser octs,
- Stream output)
- {
- BerOctetStringGenerator octGen = new BerOctetStringGenerator(output, 0, true);
- // TODO Allow specification of a specific fragment size?
- Stream outOctets = octGen.GetOctetOutputStream();
- Streams.PipeAll(octs.GetOctetStream(), outOctets);
- outOctets.Close();
- }
- }
-}
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms
+{
+ /**
+ * Parsing class for an CMS Signed Data object from an input stream.
+ *
+ * Note: that because we are in a streaming mode only one signer can be tried and it is important
+ * that the methods on the parser are called in the appropriate order.
+ *
+ *
+ * A simple example of usage for an encapsulated signature.
+ *
+ *
+ * Two notes: first, in the example below the validity of
+ * the certificate isn't verified, just the fact that one of the certs
+ * matches the given signer, and, second, because we are in a streaming
+ * mode the order of the operations is important.
+ *
+ *
+ * CmsSignedDataParser sp = new CmsSignedDataParser(encapSigData);
+ *
+ * sp.GetSignedContent().Drain();
+ *
+ * IX509Store certs = sp.GetCertificates();
+ * SignerInformationStore signers = sp.GetSignerInfos();
+ *
+ * foreach (SignerInformation signer in signers.GetSigners())
+ * {
+ * ArrayList certList = new ArrayList(certs.GetMatches(signer.SignerID));
+ * X509Certificate cert = (X509Certificate) certList[0];
+ *
+ * Console.WriteLine("verify returns: " + signer.Verify(cert));
+ * }
+ *
+ * Note also: this class does not introduce buffering - if you are processing large files you should create
+ * the parser with:
+ *
+ * CmsSignedDataParser ep = new CmsSignedDataParser(new BufferedInputStream(encapSigData, bufSize));
+ *
+ * where bufSize is a suitably large buffer size.
+ */
+ public class CmsSignedDataParser
+ : CmsContentInfoParser
+ {
+ private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
+
+ private SignedDataParser _signedData;
+ private DerObjectIdentifier _signedContentType;
+ private CmsTypedStream _signedContent;
+ private IDictionary _digests;
+ private ISet _digestOids;
+
+ private SignerInformationStore _signerInfoStore;
+ private Asn1Set _certSet, _crlSet;
+ private bool _isCertCrlParsed;
+ private IX509Store _attributeStore;
+ private IX509Store _certificateStore;
+ private IX509Store _crlStore;
+
+ public CmsSignedDataParser(
+ byte[] sigBlock)
+ : this(new MemoryStream(sigBlock, false))
+ {
+ }
+
+ public CmsSignedDataParser(
+ CmsTypedStream signedContent,
+ byte[] sigBlock)
+ : this(signedContent, new MemoryStream(sigBlock, false))
+ {
+ }
+
+ /**
+ * base constructor - with encapsulated content
+ */
+ public CmsSignedDataParser(
+ Stream sigData)
+ : this(null, sigData)
+ {
+ }
+
+ /**
+ * base constructor
+ *
+ * @param signedContent the content that was signed.
+ * @param sigData the signature object.
+ */
+ public CmsSignedDataParser(
+ CmsTypedStream signedContent,
+ Stream sigData)
+ : base(sigData)
+ {
+ try
+ {
+ this._signedContent = signedContent;
+ this._signedData = SignedDataParser.GetInstance(this.contentInfo.GetContent(Asn1Tags.Sequence));
+ this._digests = new Hashtable();
+ this._digestOids = new HashSet();
+
+ Asn1SetParser digAlgs = _signedData.GetDigestAlgorithms();
+ IAsn1Convertible o;
+
+ while ((o = digAlgs.ReadObject()) != null)
+ {
+ AlgorithmIdentifier id = AlgorithmIdentifier.GetInstance(o.ToAsn1Object());
+
+ try
+ {
+ string digestOid = id.ObjectID.Id;
+ string digestName = Helper.GetDigestAlgName(digestOid);
+
+ if (!this._digests.Contains(digestName))
+ {
+ this._digests[digestName] = Helper.GetDigestInstance(digestName);
+ this._digestOids.Add(digestOid);
+ }
+ }
+ catch (SecurityUtilityException)
+ {
+ // TODO Should do something other than ignore it
+ }
+ }
+
+ //
+ // If the message is simply a certificate chain message GetContent() may return null.
+ //
+ ContentInfoParser cont = _signedData.GetEncapContentInfo();
+ Asn1OctetStringParser octs = (Asn1OctetStringParser)
+ cont.GetContent(Asn1Tags.OctetString);
+
+ if (octs != null)
+ {
+ CmsTypedStream ctStr = new CmsTypedStream(
+ cont.ContentType.Id, octs.GetOctetStream());
+
+ if (_signedContent == null)
+ {
+ this._signedContent = ctStr;
+ }
+ else
+ {
+ //
+ // content passed in, need to read past empty encapsulated content info object if present
+ //
+ ctStr.Drain();
+ }
+ }
+
+ _signedContentType = _signedContent == null
+ ? cont.ContentType
+ : new DerObjectIdentifier(_signedContent.ContentType);
+ }
+ catch (IOException e)
+ {
+ throw new CmsException("io exception: " + e.Message, e);
+ }
+
+ if (_digests.Count < 1)
+ {
+ throw new CmsException("no digests could be created for message.");
+ }
+ }
+
+ /**
+ * Return the version number for the SignedData object
+ *
+ * @return the version number
+ */
+ public int Version
+ {
+ get { return _signedData.Version.Value.IntValue; }
+ }
+
+ public ISet DigestOids
+ {
+ get { return new HashSet(_digestOids); }
+ }
+
+ /**
+ * return the collection of signers that are associated with the
+ * signatures for the message.
+ * @throws CmsException
+ */
+ public SignerInformationStore GetSignerInfos()
+ {
+ if (_signerInfoStore == null)
+ {
+ PopulateCertCrlSets();
+
+ IList signerInfos = new ArrayList();
+ IDictionary hashes = new Hashtable();
+
+ foreach (object digestKey in _digests.Keys)
+ {
+ hashes[digestKey] = DigestUtilities.DoFinal(
+ (IDigest)_digests[digestKey]);
+ }
+
+ try
+ {
+ Asn1SetParser s = _signedData.GetSignerInfos();
+ IAsn1Convertible o;
+
+ while ((o = s.ReadObject()) != null)
+ {
+ SignerInfo info = SignerInfo.GetInstance(o.ToAsn1Object());
+ string digestName = Helper.GetDigestAlgName(
+ info.DigestAlgorithm.ObjectID.Id);
+
+ byte[] hash = (byte[]) hashes[digestName];
+
+ signerInfos.Add(new SignerInformation(info, _signedContentType, null, new BaseDigestCalculator(hash)));
+ }
+ }
+ catch (IOException e)
+ {
+ throw new CmsException("io exception: " + e.Message, e);
+ }
+
+ _signerInfoStore = new SignerInformationStore(signerInfos);
+ }
+
+ return _signerInfoStore;
+ }
+
+ /**
+ * return a X509Store containing the attribute certificates, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @return a store of attribute certificates
+ * @exception org.bouncycastle.x509.NoSuchStoreException if the store type isn't available.
+ * @exception CmsException if a general exception prevents creation of the X509Store
+ */
+ public IX509Store GetAttributeCertificates(
+ string type)
+ {
+ if (_attributeStore == null)
+ {
+ PopulateCertCrlSets();
+
+ _attributeStore = Helper.CreateAttributeStore(type, _certSet);
+ }
+
+ return _attributeStore;
+ }
+
+ /**
+ * return a X509Store containing the public key certificates, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @return a store of public key certificates
+ * @exception NoSuchStoreException if the store type isn't available.
+ * @exception CmsException if a general exception prevents creation of the X509Store
+ */
+ public IX509Store GetCertificates(
+ string type)
+ {
+ if (_certificateStore == null)
+ {
+ PopulateCertCrlSets();
+
+ _certificateStore = Helper.CreateCertificateStore(type, _certSet);
+ }
+
+ return _certificateStore;
+ }
+
+ /**
+ * return a X509Store containing CRLs, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @return a store of CRLs
+ * @exception NoSuchStoreException if the store type isn't available.
+ * @exception CmsException if a general exception prevents creation of the X509Store
+ */
+ public IX509Store GetCrls(
+ string type)
+ {
+ if (_crlStore == null)
+ {
+ PopulateCertCrlSets();
+
+ _crlStore = Helper.CreateCrlStore(type, _crlSet);
+ }
+
+ return _crlStore;
+ }
+
+ private void PopulateCertCrlSets()
+ {
+ if (_isCertCrlParsed)
+ return;
+
+ _isCertCrlParsed = true;
+
+ try
+ {
+ // care! Streaming - Must process the GetCertificates() result before calling GetCrls()
+ _certSet = GetAsn1Set(_signedData.GetCertificates());
+ _crlSet = GetAsn1Set(_signedData.GetCrls());
+ }
+ catch (IOException e)
+ {
+ throw new CmsException("problem parsing cert/crl sets", e);
+ }
+ }
+
+ ///
+ /// Return the DerObjectIdentifier associated with the encapsulated
+ /// content info structure carried in the signed data.
+ ///
+ public DerObjectIdentifier SignedContentType
+ {
+ get { return _signedContentType; }
+ }
+
+ public CmsTypedStream GetSignedContent()
+ {
+ if (_signedContent == null)
+ {
+ return null;
+ }
+
+ Stream digStream = _signedContent.ContentStream;
+
+ foreach (IDigest digest in _digests.Values)
+ {
+ digStream = new DigestStream(digStream, digest, null);
+ }
+
+ return new CmsTypedStream(_signedContent.ContentType, digStream);
+ }
+
+ /**
+ * Replace the signerinformation store associated with the passed
+ * in message contained in the stream original with the new one passed in.
+ * You would probably only want to do this if you wanted to change the unsigned
+ * attributes associated with a signer, or perhaps delete one.
+ *
+ * The output stream is returned unclosed.
+ *
+ * @param original the signed data stream to be used as a base.
+ * @param signerInformationStore the new signer information store to use.
+ * @param out the stream to Write the new signed data object to.
+ * @return out.
+ */
+ public static Stream ReplaceSigners(
+ Stream original,
+ SignerInformationStore signerInformationStore,
+ Stream outStr)
+ {
+ // NB: SecureRandom would be ignored since using existing signatures only
+ CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+ CmsSignedDataParser parser = new CmsSignedDataParser(original);
+
+// gen.AddDigests(parser.DigestOids);
+ gen.AddSigners(signerInformationStore);
+
+ CmsTypedStream signedContent = parser.GetSignedContent();
+ bool encapsulate = (signedContent != null);
+ Stream contentOut = gen.Open(outStr, parser.SignedContentType.Id, encapsulate);
+ if (encapsulate)
+ {
+ Streams.PipeAll(signedContent.ContentStream, contentOut);
+ }
+
+ gen.AddAttributeCertificates(parser.GetAttributeCertificates("Collection"));
+ gen.AddCertificates(parser.GetCertificates("Collection"));
+ gen.AddCrls(parser.GetCrls("Collection"));
+
+// gen.AddSigners(parser.GetSignerInfos());
+
+ contentOut.Close();
+
+ return outStr;
+ }
+
+ /**
+ * Replace the certificate and CRL information associated with this
+ * CMSSignedData object with the new one passed in.
+ *
+ * The output stream is returned unclosed.
+ *
+ * @param original the signed data stream to be used as a base.
+ * @param certsAndCrls the new certificates and CRLs to be used.
+ * @param out the stream to Write the new signed data object to.
+ * @return out.
+ * @exception CmsException if there is an error processing the CertStore
+ */
+ public static Stream ReplaceCertificatesAndCrls(
+ Stream original,
+ IX509Store x509Certs,
+ IX509Store x509Crls,
+ IX509Store x509AttrCerts,
+ Stream outStr)
+ {
+ // NB: SecureRandom would be ignored since using existing signatures only
+ CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+ CmsSignedDataParser parser = new CmsSignedDataParser(original);
+
+ gen.AddDigests(parser.DigestOids);
+
+ CmsTypedStream signedContent = parser.GetSignedContent();
+ bool encapsulate = (signedContent != null);
+ Stream contentOut = gen.Open(outStr, parser.SignedContentType.Id, encapsulate);
+ if (encapsulate)
+ {
+ Streams.PipeAll(signedContent.ContentStream, contentOut);
+ }
+
+// gen.AddAttributeCertificates(parser.GetAttributeCertificates("Collection"));
+// gen.AddCertificates(parser.GetCertificates("Collection"));
+// gen.AddCrls(parser.GetCrls("Collection"));
+ if (x509AttrCerts != null)
+ gen.AddAttributeCertificates(x509AttrCerts);
+ if (x509Certs != null)
+ gen.AddCertificates(x509Certs);
+ if (x509Crls != null)
+ gen.AddCrls(x509Crls);
+
+ gen.AddSigners(parser.GetSignerInfos());
+
+ contentOut.Close();
+
+ return outStr;
+ }
+
+ private static Asn1Set GetAsn1Set(
+ Asn1SetParser asn1SetParser)
+ {
+ return asn1SetParser == null
+ ? null
+ : Asn1Set.GetInstance(asn1SetParser.ToAsn1Object());
+ }
+ }
+}
diff --git a/src/core/srcbc/cms/CMSSignedDataStreamGenerator.cs b/src/core/srcbc/cms/CMSSignedDataStreamGenerator.cs
index 1b4c6bf..67b5910 100644
--- a/src/core/srcbc/cms/CMSSignedDataStreamGenerator.cs
+++ b/src/core/srcbc/cms/CMSSignedDataStreamGenerator.cs
@@ -1,681 +1,795 @@
-using System;
-using System.Collections;
-using System.Diagnostics;
-using System.IO;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Asn1.Cms;
-using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.IO;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Security.Certificates;
-using Org.BouncyCastle.Utilities.IO;
-using Org.BouncyCastle.X509;
-
-namespace Org.BouncyCastle.Cms
-{
- /**
- * General class for generating a pkcs7-signature message stream.
- *
- * A simple example of usage.
- *
- *
- * IX509Store certs...
- * CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
- *
- * gen.AddSigner(privateKey, cert, CmsSignedDataStreamGenerator.DIGEST_SHA1);
- *
- * gen.AddCertificates(certs);
- *
- * Stream sigOut = gen.Open(bOut);
- *
- * sigOut.Write(Encoding.UTF8.GetBytes("Hello World!"));
- *
- * sigOut.Close();
- *
- */
- public class CmsSignedDataStreamGenerator
- : CmsSignedGenerator
- {
- private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
-
- private readonly ArrayList _signerInfs = new ArrayList();
- private readonly ArrayList _messageDigests = new ArrayList();
- private int _bufferSize;
-
- private class SignerInf
- {
- private readonly CmsSignedDataStreamGenerator outer;
-
- AsymmetricKeyParameter _key;
- X509Certificate _cert;
- string _digestOID;
- string _encOID;
- CmsAttributeTableGenerator _sAttr;
- CmsAttributeTableGenerator _unsAttr;
- IDigest _digest;
- ISigner _signature;
-
- internal SignerInf(
- CmsSignedDataStreamGenerator outer,
- AsymmetricKeyParameter key,
- X509Certificate cert,
- string digestOID,
- string encOID,
- CmsAttributeTableGenerator sAttr,
- CmsAttributeTableGenerator unsAttr,
- IDigest digest,
- ISigner signature)
- {
- this.outer = outer;
-
- _key = key;
- _cert = cert;
- _digestOID = digestOID;
- _encOID = encOID;
- _sAttr = sAttr;
- _unsAttr = unsAttr;
- _digest = digest;
- _signature = signature;
- }
-
- internal AsymmetricKeyParameter Key
- {
- get { return _key; }
- }
-
- internal X509Certificate Certificate
- {
- get { return _cert; }
- }
-
- internal AlgorithmIdentifier DigestAlgorithmID
- {
- get { return new AlgorithmIdentifier(new DerObjectIdentifier(_digestOID), null); }
- }
-
- internal string DigestAlgOid
- {
- get { return _digestOID; }
- }
-
- internal Asn1Object DigestAlgParams
- {
- get { return null; }
- }
-
- internal string EncryptionAlgOid
- {
- get { return _encOID; }
- }
-
-// internal Asn1.Cms.AttributeTable SignedAttributes
-// {
-// get { return _sAttr; }
-// }
-//
-// internal Asn1.Cms.AttributeTable UnsignedAttributes
-// {
-// get { return _unsAttr; }
-// }
-
- internal SignerInfo ToSignerInfo(
- DerObjectIdentifier contentType)
- {
- AlgorithmIdentifier digAlgId = new AlgorithmIdentifier(
- new DerObjectIdentifier(this.DigestAlgOid), DerNull.Instance);
- AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(this.EncryptionAlgOid);
-
- byte[] hash = DigestUtilities.DoFinal(_digest);
-
- outer._digests.Add(_digestOID, hash.Clone());
-
- IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);
-
- Asn1.Cms.AttributeTable signed = (_sAttr != null)
-// ? _sAttr.GetAttributes(Collections.unmodifiableMap(parameters))
- ? _sAttr.GetAttributes(parameters)
- : null;
-
- Asn1Set signedAttr = outer.GetAttributeSet(signed);
-
- //
- // sig must be composed from the DER encoding.
- //
- byte[] tmp;
- if (signedAttr != null)
- {
- tmp = signedAttr.GetEncoded(Asn1Encodable.Der);
- }
- else
- {
- throw new Exception("signatures without signed attributes not implemented.");
- }
-
- _signature.BlockUpdate(tmp, 0, tmp.Length);
-
- Asn1OctetString encDigest = new DerOctetString(_signature.GenerateSignature());
-
- parameters = outer.GetBaseParameters(contentType, digAlgId, hash);
- parameters[CmsAttributeTableParameter.Signature] = encDigest.GetOctets().Clone();
-
- Asn1.Cms.AttributeTable unsigned = (_unsAttr != null)
-// ? _unsAttr.getAttributes(Collections.unmodifiableMap(parameters))
- ? _unsAttr.GetAttributes(parameters)
- : null;
-
- Asn1Set unsignedAttr = outer.GetAttributeSet(unsigned);
-
- X509Certificate cert = this.Certificate;
- TbsCertificateStructure tbs = TbsCertificateStructure.GetInstance(
- Asn1Object.FromByteArray(cert.GetTbsCertificate()));
- IssuerAndSerialNumber encSid = new IssuerAndSerialNumber(
- tbs.Issuer, tbs.SerialNumber.Value);
-
- return new SignerInfo(new SignerIdentifier(encSid), digAlgId,
- signedAttr, encAlgId, encDigest, unsignedAttr);
- }
-
- }
-
- public CmsSignedDataStreamGenerator()
- {
- }
-
- /// Constructor allowing specific source of randomness
- /// Instance of SecureRandom to use.
- public CmsSignedDataStreamGenerator(
- SecureRandom rand)
- : base(rand)
- {
- }
-
- /**
- * Set the underlying string size for encapsulated data
- *
- * @param bufferSize length of octet strings to buffer the data.
- */
- public void SetBufferSize(
- int bufferSize)
- {
- _bufferSize = bufferSize;
- }
-
- /**
- * add a signer - no attributes other than the default ones will be
- * provided here.
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- */
- public void AddSigner(
- AsymmetricKeyParameter privateKey,
- X509Certificate cert,
- string digestOID)
- {
- AddSigner(privateKey, cert, digestOID,
- new DefaultSignedAttributeTableGenerator(), null);
- }
-
- /**
- * add a signer with extra signed/unsigned attributes.
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- */
- public void AddSigner(
- AsymmetricKeyParameter privateKey,
- X509Certificate cert,
- string digestOID,
- Asn1.Cms.AttributeTable signedAttr,
- Asn1.Cms.AttributeTable unsignedAttr)
- {
- AddSigner(privateKey, cert, digestOID,
- new DefaultSignedAttributeTableGenerator(signedAttr),
- new SimpleAttributeTableGenerator(unsignedAttr));
- }
-
- public void AddSigner(
- AsymmetricKeyParameter privateKey,
- X509Certificate cert,
- string digestOID,
- CmsAttributeTableGenerator signedAttrGenerator,
- CmsAttributeTableGenerator unsignedAttrGenerator)
- {
- string encOID = GetEncOid(privateKey, digestOID);
- string digestName = Helper.GetDigestAlgName(digestOID);
- string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
- ISigner sig = Helper.GetSignatureInstance(signatureName);
- IDigest dig = Helper.GetDigestInstance(digestName);
-
- sig.Init(true, new ParametersWithRandom(privateKey, rand));
-
- _signerInfs.Add(new SignerInf(this, privateKey, cert, digestOID, encOID,
- signedAttrGenerator, unsignedAttrGenerator, dig, sig));
- _messageDigests.Add(dig);
- }
-
- /**
- * generate a signed object that for a CMS Signed Data object
- */
- public Stream Open(
- Stream outStream)
- {
- return Open(outStream, false);
- }
-
- /**
- * generate a signed object that for a CMS Signed Data
- * object - if encapsulate is true a copy
- * of the message will be included in the signature with the
- * default content type "data".
- */
- public Stream Open(
- Stream outStream,
- bool encapsulate)
- {
- return Open(outStream, Data, encapsulate);
- }
-
- /**
- * generate a signed object that for a CMS Signed Data
- * object using the given provider - if encapsulate is true a copy
- * of the message will be included in the signature with the
- * default content type "data". If dataOutputStream is non null the data
- * being signed will be written to the stream as it is processed.
- * @param out stream the CMS object is to be written to.
- * @param encapsulate true if data should be encapsulated.
- * @param dataOutputStream output stream to copy the data being signed to.
- */
- public Stream Open(
- Stream outStream,
- bool encapsulate,
- Stream dataOutputStream)
- {
- return Open(outStream, Data, encapsulate, dataOutputStream);
- }
-
- /**
- * generate a signed object that for a CMS Signed Data
- * object - if encapsulate is true a copy
- * of the message will be included in the signature. The content type
- * is set according to the OID represented by the string signedContentType.
- */
- public Stream Open(
- Stream outStream,
- string signedContentType,
- bool encapsulate)
- {
- return Open(outStream, signedContentType, encapsulate, null);
- }
-
- /**
- * generate a signed object that for a CMS Signed Data
- * object using the given provider - if encapsulate is true a copy
- * of the message will be included in the signature. The content type
- * is set according to the OID represented by the string signedContentType.
- * @param out stream the CMS object is to be written to.
- * @param signedContentType OID for data to be signed.
- * @param encapsulate true if data should be encapsulated.
- * @param dataOutputStream output stream to copy the data being signed to.
- */
- public Stream Open(
- Stream outStream,
- string signedContentType,
- bool encapsulate,
- Stream dataOutputStream)
- {
- if (outStream == null)
- throw new ArgumentNullException("outStream");
- if (!outStream.CanWrite)
- throw new ArgumentException("Expected writeable stream", "outStream");
- if (dataOutputStream != null && !dataOutputStream.CanWrite)
- throw new ArgumentException("Expected writeable stream", "dataOutputStream");
-
- //
- // ContentInfo
- //
- BerSequenceGenerator sGen = new BerSequenceGenerator(outStream);
-
- sGen.AddObject(CmsObjectIdentifiers.SignedData);
-
- //
- // Signed Data
- //
- BerSequenceGenerator sigGen = new BerSequenceGenerator(
- sGen.GetRawOutputStream(), 0, true);
-
- sigGen.AddObject(CalculateVersion(signedContentType));
-
- Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
-
- //
- // add the precalculated SignerInfo digest algorithms.
- //
- foreach (SignerInformation signer in _signers)
- {
- digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
- }
-
- //
- // add the new digests
- //
- foreach (SignerInf signer in _signerInfs)
- {
- digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
- }
-
- {
- byte[] tmp = new DerSet(digestAlgs).GetEncoded();
- sigGen.GetRawOutputStream().Write(tmp, 0, tmp.Length);
- }
-
- BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());
-
- eiGen.AddObject(new DerObjectIdentifier(signedContentType));
-
- Stream digStream;
- if (encapsulate)
- {
- BerOctetStringGenerator octGen = new BerOctetStringGenerator(
- eiGen.GetRawOutputStream(), 0, true);
-
- digStream = octGen.GetOctetOutputStream(_bufferSize);
-
- if (dataOutputStream != null)
- {
- digStream = new TeeOutputStream(dataOutputStream, digStream);
- }
- }
- else
- {
- if (dataOutputStream != null)
- {
- digStream = dataOutputStream;
- }
- else
- {
- digStream = new NullOutputStream();
- }
- }
-
- foreach (IDigest d in _messageDigests)
- {
- digStream = new DigestStream(digStream, null, d);
- }
-
- return new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen);
- }
-
- // RFC3852, section 5.1:
- // IF ((certificates is present) AND
- // (any certificates with a type of other are present)) OR
- // ((crls is present) AND
- // (any crls with a type of other are present))
- // THEN version MUST be 5
- // ELSE
- // IF (certificates is present) AND
- // (any version 2 attribute certificates are present)
- // THEN version MUST be 4
- // ELSE
- // IF ((certificates is present) AND
- // (any version 1 attribute certificates are present)) OR
- // (any SignerInfo structures are version 3) OR
- // (encapContentInfo eContentType is other than id-data)
- // THEN version MUST be 3
- // ELSE version MUST be 1
- //
- private DerInteger CalculateVersion(
- string contentOid)
- {
- bool otherCert = false;
- bool otherCrl = false;
- bool attrCertV1Found = false;
- bool attrCertV2Found = false;
-
- if (_certs != null)
- {
- foreach (object obj in _certs)
- {
- if (obj is Asn1TaggedObject)
- {
- Asn1TaggedObject tagged = (Asn1TaggedObject) obj;
-
- if (tagged.TagNo == 1)
- {
- attrCertV1Found = true;
- }
- else if (tagged.TagNo == 2)
- {
- attrCertV2Found = true;
- }
- else if (tagged.TagNo == 3)
- {
- otherCert = true;
- break;
- }
- }
- }
- }
-
- if (otherCert)
- {
- return new DerInteger(5);
- }
-
- if (_crls != null)
- {
- foreach (object obj in _crls)
- {
- if (obj is Asn1TaggedObject)
- {
- otherCrl = true;
- break;
- }
- }
- }
-
- if (otherCrl)
- {
- return new DerInteger(5);
- }
-
- if (attrCertV2Found)
- {
- return new DerInteger(4);
- }
-
- if (attrCertV1Found)
- {
- return new DerInteger(3);
- }
-
- if (contentOid.Equals(Data)
- && !CheckForVersion3(_signers))
- {
- return new DerInteger(1);
- }
-
- return new DerInteger(3);
- }
-
- private bool CheckForVersion3(
- IList signerInfos)
- {
- foreach (SignerInformation si in signerInfos)
- {
- SignerInfo s = SignerInfo.GetInstance(si.ToSignerInfo());
-
- if (s.Version.Value.IntValue == 3)
- {
- return true;
- }
- }
-
- return false;
- }
-
- private class NullOutputStream
- : BaseOutputStream
- {
- public override void WriteByte(
- byte b)
- {
- // do nothing
- }
-
- public override void Write(
- byte[] buffer,
- int offset,
- int count)
- {
- // do nothing
- }
- }
-
- private class TeeOutputStream
- : BaseOutputStream
- {
- private readonly Stream s1, s2;
-
- public TeeOutputStream(Stream dataOutputStream, Stream digStream)
- {
- Debug.Assert(dataOutputStream.CanWrite);
- Debug.Assert(digStream.CanWrite);
-
- this.s1 = dataOutputStream;
- this.s2 = digStream;
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- s1.Write(buffer, offset, count);
- s2.Write(buffer, offset, count);
- }
-
- public override void WriteByte(byte b)
- {
- s1.WriteByte(b);
- s2.WriteByte(b);
- }
-
- public override void Close()
- {
- s1.Close();
- s2.Close();
- }
- }
-
- private class CmsSignedDataOutputStream
- : BaseOutputStream
- {
- private readonly CmsSignedDataStreamGenerator outer;
-
- private Stream _out;
- private DerObjectIdentifier _contentOID;
- private BerSequenceGenerator _sGen;
- private BerSequenceGenerator _sigGen;
- private BerSequenceGenerator _eiGen;
-
- public CmsSignedDataOutputStream(
- CmsSignedDataStreamGenerator outer,
- Stream outStream,
- string contentOID,
- BerSequenceGenerator sGen,
- BerSequenceGenerator sigGen,
- BerSequenceGenerator eiGen)
- {
- this.outer = outer;
-
- _out = outStream;
- _contentOID = new DerObjectIdentifier(contentOID);
- _sGen = sGen;
- _sigGen = sigGen;
- _eiGen = eiGen;
- }
-
- public override void WriteByte(
- byte b)
- {
- _out.WriteByte(b);
- }
-
- public override void Write(
- byte[] bytes,
- int off,
- int len)
- {
- _out.Write(bytes, off, len);
- }
-
- public override void Close()
- {
- _out.Close();
- _eiGen.Close();
-
- outer._digests.Clear(); // clear the current preserved digest state
-
- if (outer._certs.Count > 0)
- {
- Asn1Set certs = CmsUtilities.CreateBerSetFromList(outer._certs);
-
- WriteToGenerator(_sigGen, new BerTaggedObject(false, 0, certs));
- }
-
- if (outer._crls.Count > 0)
- {
- Asn1Set crls = CmsUtilities.CreateBerSetFromList(outer._crls);
-
- WriteToGenerator(_sigGen, new BerTaggedObject(false, 1, crls));
- }
-
- //
- // add the precalculated SignerInfo objects.
- //
- Asn1EncodableVector signerInfos = new Asn1EncodableVector();
-
- foreach (SignerInformation signer in outer._signers)
- {
- signerInfos.Add(signer.ToSignerInfo());
- }
-
- //
- // add the SignerInfo objects
- //
- foreach (SignerInf signer in outer._signerInfs)
- {
- try
- {
- signerInfos.Add(signer.ToSignerInfo(_contentOID));
- }
- catch (IOException e)
- {
- throw new IOException("encoding error." + e);
- }
- catch (SignatureException e)
- {
- throw new IOException("error creating signature." + e);
- }
- catch (CertificateEncodingException e)
- {
- throw new IOException("error creating sid." + e);
- }
- }
-
- WriteToGenerator(_sigGen, new DerSet(signerInfos));
-
- _sigGen.Close();
- _sGen.Close();
- base.Close();
- }
-
- private static void WriteToGenerator(
- Asn1Generator ag,
- Asn1Encodable ae)
- {
- byte[] encoded = ae.GetEncoded();
- ag.GetRawOutputStream().Write(encoded, 0, encoded.Length);
- }
- }
- }
-}
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+ /**
+ * General class for generating a pkcs7-signature message stream.
+ *
+ * A simple example of usage.
+ *
+ *
+ * IX509Store certs...
+ * CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+ *
+ * gen.AddSigner(privateKey, cert, CmsSignedDataStreamGenerator.DIGEST_SHA1);
+ *
+ * gen.AddCertificates(certs);
+ *
+ * Stream sigOut = gen.Open(bOut);
+ *
+ * sigOut.Write(Encoding.UTF8.GetBytes("Hello World!"));
+ *
+ * sigOut.Close();
+ *
+ */
+ public class CmsSignedDataStreamGenerator
+ : CmsSignedGenerator
+ {
+ private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
+
+ private readonly ArrayList _signerInfs = new ArrayList();
+ private readonly ISet _messageDigestOids = new HashSet();
+ private readonly Hashtable _messageDigests = new Hashtable();
+ private readonly Hashtable _messageHashes = new Hashtable();
+ private bool _messageDigestsLocked;
+ private int _bufferSize;
+
+ private class SignerInf
+ {
+ private readonly CmsSignedDataStreamGenerator outer;
+
+ private AsymmetricKeyParameter _key;
+ private X509Certificate _cert;
+ private string _digestOID;
+ private string _encOID;
+ private CmsAttributeTableGenerator _sAttr;
+ private CmsAttributeTableGenerator _unsAttr;
+ private ISigner _signature;
+ private byte[] _subjectKeyID;
+
+ internal SignerInf(
+ CmsSignedDataStreamGenerator outer,
+ AsymmetricKeyParameter key,
+ X509Certificate cert,
+ string digestOID,
+ string encOID,
+ CmsAttributeTableGenerator sAttr,
+ CmsAttributeTableGenerator unsAttr,
+ ISigner signature)
+ {
+ this.outer = outer;
+
+ _key = key;
+ _cert = cert;
+ _digestOID = digestOID;
+ _encOID = encOID;
+ _sAttr = sAttr;
+ _unsAttr = unsAttr;
+ _signature = signature;
+ }
+
+ internal SignerInf(
+ CmsSignedDataStreamGenerator outer,
+ AsymmetricKeyParameter key,
+ byte[] subjectKeyID,
+ string digestOID,
+ string encOID,
+ CmsAttributeTableGenerator sAttr,
+ CmsAttributeTableGenerator unsAttr,
+ ISigner signature)
+ {
+ this.outer = outer;
+
+ _key = key;
+ _subjectKeyID = subjectKeyID;
+ _digestOID = digestOID;
+ _encOID = encOID;
+ _sAttr = sAttr;
+ _unsAttr = unsAttr;
+ _signature = signature;
+ }
+
+ internal AsymmetricKeyParameter Key
+ {
+ get { return _key; }
+ }
+
+ internal X509Certificate Certificate
+ {
+ get { return _cert; }
+ }
+
+ internal string EncryptionAlgOid
+ {
+ get { return _encOID; }
+ }
+
+ internal SignerInfo ToSignerInfo(
+ DerObjectIdentifier contentType)
+ {
+ AlgorithmIdentifier digAlgId = new AlgorithmIdentifier(
+ new DerObjectIdentifier(this._digestOID), DerNull.Instance);
+ AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(this.EncryptionAlgOid);
+
+ byte[] hash = (byte[])outer._messageHashes[Helper.GetDigestAlgName(this._digestOID)];
+
+ outer._digests[_digestOID] = hash.Clone();
+
+ IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);
+
+ Asn1.Cms.AttributeTable signed = (_sAttr != null)
+// ? _sAttr.GetAttributes(Collections.unmodifiableMap(parameters))
+ ? _sAttr.GetAttributes(parameters)
+ : null;
+
+ Asn1Set signedAttr = outer.GetAttributeSet(signed);
+
+ //
+ // sig must be composed from the DER encoding.
+ //
+ byte[] tmp;
+ if (signedAttr != null)
+ {
+ tmp = signedAttr.GetEncoded(Asn1Encodable.Der);
+ }
+ else
+ {
+ throw new Exception("signatures without signed attributes not implemented.");
+ }
+
+ _signature.BlockUpdate(tmp, 0, tmp.Length);
+
+ Asn1OctetString encDigest = new DerOctetString(_signature.GenerateSignature());
+
+ parameters = outer.GetBaseParameters(contentType, digAlgId, hash);
+ parameters[CmsAttributeTableParameter.Signature] = encDigest.GetOctets().Clone();
+
+ Asn1.Cms.AttributeTable unsigned = (_unsAttr != null)
+// ? _unsAttr.getAttributes(Collections.unmodifiableMap(parameters))
+ ? _unsAttr.GetAttributes(parameters)
+ : null;
+
+ Asn1Set unsignedAttr = outer.GetAttributeSet(unsigned);
+
+ X509Certificate cert = this.Certificate;
+ SignerIdentifier signerIdentifier;
+ if (cert != null)
+ {
+ TbsCertificateStructure tbs = TbsCertificateStructure.GetInstance(
+ Asn1Object.FromByteArray(cert.GetTbsCertificate()));
+ IssuerAndSerialNumber encSid = new IssuerAndSerialNumber(
+ tbs.Issuer, tbs.SerialNumber.Value);
+
+ signerIdentifier = new SignerIdentifier(encSid);
+ }
+ else
+ {
+ signerIdentifier = new SignerIdentifier(new DerOctetString(_subjectKeyID));
+ }
+
+ return new SignerInfo(signerIdentifier, digAlgId,
+ signedAttr, encAlgId, encDigest, unsignedAttr);
+ }
+
+ }
+
+ public CmsSignedDataStreamGenerator()
+ {
+ }
+
+ /// Constructor allowing specific source of randomness
+ /// Instance of SecureRandom to use.
+ public CmsSignedDataStreamGenerator(
+ SecureRandom rand)
+ : base(rand)
+ {
+ }
+
+ /**
+ * Set the underlying string size for encapsulated data
+ *
+ * @param bufferSize length of octet strings to buffer the data.
+ */
+ public void SetBufferSize(
+ int bufferSize)
+ {
+ _bufferSize = bufferSize;
+ }
+
+ public void AddDigests(
+ params string[] digestOids)
+ {
+ AddDigests((IEnumerable) digestOids);
+ }
+
+ public void AddDigests(
+ IEnumerable digestOids)
+ {
+ foreach (string digestOid in digestOids)
+ {
+ ConfigureDigest(digestOid);
+ }
+ }
+
+ /**
+ * add a signer - no attributes other than the default ones will be
+ * provided here.
+ * @throws NoSuchAlgorithmException
+ * @throws InvalidKeyException
+ */
+ public void AddSigner(
+ AsymmetricKeyParameter privateKey,
+ X509Certificate cert,
+ string digestOid)
+ {
+ AddSigner(privateKey, cert, digestOid,
+ new DefaultSignedAttributeTableGenerator(), null);
+ }
+
+ /**
+ * add a signer with extra signed/unsigned attributes.
+ * @throws NoSuchAlgorithmException
+ * @throws InvalidKeyException
+ */
+ public void AddSigner(
+ AsymmetricKeyParameter privateKey,
+ X509Certificate cert,
+ string digestOid,
+ Asn1.Cms.AttributeTable signedAttr,
+ Asn1.Cms.AttributeTable unsignedAttr)
+ {
+ AddSigner(privateKey, cert, digestOid,
+ new DefaultSignedAttributeTableGenerator(signedAttr),
+ new SimpleAttributeTableGenerator(unsignedAttr));
+ }
+
+ public void AddSigner(
+ AsymmetricKeyParameter privateKey,
+ X509Certificate cert,
+ string digestOid,
+ CmsAttributeTableGenerator signedAttrGenerator,
+ CmsAttributeTableGenerator unsignedAttrGenerator)
+ {
+ ConfigureDigest(digestOid);
+
+ string digestName = Helper.GetDigestAlgName(digestOid);
+ string encOID = GetEncOid(privateKey, digestOid);
+ string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
+ ISigner sig = Helper.GetSignatureInstance(signatureName);
+ sig.Init(true, new ParametersWithRandom(privateKey, rand));
+
+ _signerInfs.Add(new SignerInf(this, privateKey, cert, digestOid, encOID,
+ signedAttrGenerator, unsignedAttrGenerator, sig));
+ }
+
+ /**
+ * add a signer - no attributes other than the default ones will be
+ * provided here.
+ * @throws NoSuchAlgorithmException
+ * @throws InvalidKeyException
+ */
+ public void AddSigner(
+ AsymmetricKeyParameter privateKey,
+ byte[] subjectKeyID,
+ string digestOid)
+ {
+ AddSigner(privateKey, subjectKeyID, digestOid, new DefaultSignedAttributeTableGenerator(),
+ (CmsAttributeTableGenerator)null);
+ }
+
+ /**
+ * add a signer with extra signed/unsigned attributes.
+ * @throws NoSuchAlgorithmException
+ * @throws InvalidKeyException
+ */
+ public void AddSigner(
+ AsymmetricKeyParameter privateKey,
+ byte[] subjectKeyID,
+ string digestOid,
+ Asn1.Cms.AttributeTable signedAttr,
+ Asn1.Cms.AttributeTable unsignedAttr)
+ {
+ AddSigner(privateKey, subjectKeyID, digestOid,
+ new DefaultSignedAttributeTableGenerator(signedAttr),
+ new SimpleAttributeTableGenerator(unsignedAttr));
+ }
+
+ public void AddSigner(
+ AsymmetricKeyParameter privateKey,
+ byte[] subjectKeyID,
+ string digestOid,
+ CmsAttributeTableGenerator signedAttrGenerator,
+ CmsAttributeTableGenerator unsignedAttrGenerator)
+ {
+ ConfigureDigest(digestOid);
+
+ string digestName = Helper.GetDigestAlgName(digestOid);
+ string encOID = GetEncOid(privateKey, digestOid);
+ string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
+ ISigner sig = Helper.GetSignatureInstance(signatureName);
+ sig.Init(true, new ParametersWithRandom(privateKey, rand));
+
+ _signerInfs.Add(new SignerInf(this, privateKey, subjectKeyID, digestOid, encOID,
+ signedAttrGenerator, unsignedAttrGenerator, sig));
+ }
+
+ internal override void AddSignerCallback(
+ SignerInformation si)
+ {
+ // For precalculated signers, just need to register the algorithm, not configure a digest
+ RegisterDigestOid(si.DigestAlgOid);
+ }
+
+ /**
+ * generate a signed object that for a CMS Signed Data object
+ */
+ public Stream Open(
+ Stream outStream)
+ {
+ return Open(outStream, false);
+ }
+
+ /**
+ * generate a signed object that for a CMS Signed Data
+ * object - if encapsulate is true a copy
+ * of the message will be included in the signature with the
+ * default content type "data".
+ */
+ public Stream Open(
+ Stream outStream,
+ bool encapsulate)
+ {
+ return Open(outStream, Data, encapsulate);
+ }
+
+ /**
+ * generate a signed object that for a CMS Signed Data
+ * object using the given provider - if encapsulate is true a copy
+ * of the message will be included in the signature with the
+ * default content type "data". If dataOutputStream is non null the data
+ * being signed will be written to the stream as it is processed.
+ * @param out stream the CMS object is to be written to.
+ * @param encapsulate true if data should be encapsulated.
+ * @param dataOutputStream output stream to copy the data being signed to.
+ */
+ public Stream Open(
+ Stream outStream,
+ bool encapsulate,
+ Stream dataOutputStream)
+ {
+ return Open(outStream, Data, encapsulate, dataOutputStream);
+ }
+
+ /**
+ * generate a signed object that for a CMS Signed Data
+ * object - if encapsulate is true a copy
+ * of the message will be included in the signature. The content type
+ * is set according to the OID represented by the string signedContentType.
+ */
+ public Stream Open(
+ Stream outStream,
+ string signedContentType,
+ bool encapsulate)
+ {
+ return Open(outStream, signedContentType, encapsulate, null);
+ }
+
+ /**
+ * generate a signed object that for a CMS Signed Data
+ * object using the given provider - if encapsulate is true a copy
+ * of the message will be included in the signature. The content type
+ * is set according to the OID represented by the string signedContentType.
+ * @param out stream the CMS object is to be written to.
+ * @param signedContentType OID for data to be signed.
+ * @param encapsulate true if data should be encapsulated.
+ * @param dataOutputStream output stream to copy the data being signed to.
+ */
+ public Stream Open(
+ Stream outStream,
+ string signedContentType,
+ bool encapsulate,
+ Stream dataOutputStream)
+ {
+ if (outStream == null)
+ throw new ArgumentNullException("outStream");
+ if (!outStream.CanWrite)
+ throw new ArgumentException("Expected writeable stream", "outStream");
+ if (dataOutputStream != null && !dataOutputStream.CanWrite)
+ throw new ArgumentException("Expected writeable stream", "dataOutputStream");
+
+ _messageDigestsLocked = true;
+
+ //
+ // ContentInfo
+ //
+ BerSequenceGenerator sGen = new BerSequenceGenerator(outStream);
+
+ sGen.AddObject(CmsObjectIdentifiers.SignedData);
+
+ //
+ // Signed Data
+ //
+ BerSequenceGenerator sigGen = new BerSequenceGenerator(
+ sGen.GetRawOutputStream(), 0, true);
+
+ sigGen.AddObject(CalculateVersion(signedContentType));
+
+ Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
+
+ foreach (string digestOid in _messageDigestOids)
+ {
+ digestAlgs.Add(
+ new AlgorithmIdentifier(new DerObjectIdentifier(digestOid), DerNull.Instance));
+ }
+
+ {
+ byte[] tmp = new DerSet(digestAlgs).GetEncoded();
+ sigGen.GetRawOutputStream().Write(tmp, 0, tmp.Length);
+ }
+
+ BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());
+
+ eiGen.AddObject(new DerObjectIdentifier(signedContentType));
+
+ Stream digStream;
+ if (encapsulate)
+ {
+ BerOctetStringGenerator octGen = new BerOctetStringGenerator(
+ eiGen.GetRawOutputStream(), 0, true);
+
+ digStream = octGen.GetOctetOutputStream(_bufferSize);
+
+ if (dataOutputStream != null)
+ {
+ digStream = new TeeOutputStream(dataOutputStream, digStream);
+ }
+ }
+ else
+ {
+ if (dataOutputStream != null)
+ {
+ digStream = dataOutputStream;
+ }
+ else
+ {
+ digStream = new NullOutputStream();
+ }
+ }
+
+ foreach (IDigest d in _messageDigests.Values)
+ {
+ digStream = new DigestStream(digStream, null, d);
+ }
+
+ return new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen);
+ }
+
+ private void RegisterDigestOid(
+ string digestOid)
+ {
+ if (_messageDigestsLocked)
+ {
+ if (!_messageDigestOids.Contains(digestOid))
+ throw new InvalidOperationException("Cannot register new digest OIDs after the data stream is opened");
+ }
+ else
+ {
+ _messageDigestOids.Add(digestOid);
+ }
+ }
+
+ private void ConfigureDigest(
+ string digestOid)
+ {
+ RegisterDigestOid(digestOid);
+
+ string digestName = Helper.GetDigestAlgName(digestOid);
+ IDigest dig = (IDigest)_messageDigests[digestName];
+ if (dig == null)
+ {
+ if (_messageDigestsLocked)
+ throw new InvalidOperationException("Cannot configure new digests after the data stream is opened");
+
+ dig = Helper.GetDigestInstance(digestName);
+ _messageDigests[digestName] = dig;
+ }
+ }
+
+ // RFC3852, section 5.1:
+ // IF ((certificates is present) AND
+ // (any certificates with a type of other are present)) OR
+ // ((crls is present) AND
+ // (any crls with a type of other are present))
+ // THEN version MUST be 5
+ // ELSE
+ // IF (certificates is present) AND
+ // (any version 2 attribute certificates are present)
+ // THEN version MUST be 4
+ // ELSE
+ // IF ((certificates is present) AND
+ // (any version 1 attribute certificates are present)) OR
+ // (any SignerInfo structures are version 3) OR
+ // (encapContentInfo eContentType is other than id-data)
+ // THEN version MUST be 3
+ // ELSE version MUST be 1
+ //
+ private DerInteger CalculateVersion(
+ string contentOid)
+ {
+ bool otherCert = false;
+ bool otherCrl = false;
+ bool attrCertV1Found = false;
+ bool attrCertV2Found = false;
+
+ if (_certs != null)
+ {
+ foreach (object obj in _certs)
+ {
+ if (obj is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tagged = (Asn1TaggedObject) obj;
+
+ if (tagged.TagNo == 1)
+ {
+ attrCertV1Found = true;
+ }
+ else if (tagged.TagNo == 2)
+ {
+ attrCertV2Found = true;
+ }
+ else if (tagged.TagNo == 3)
+ {
+ otherCert = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (otherCert)
+ {
+ return new DerInteger(5);
+ }
+
+ if (_crls != null)
+ {
+ foreach (object obj in _crls)
+ {
+ if (obj is Asn1TaggedObject)
+ {
+ otherCrl = true;
+ break;
+ }
+ }
+ }
+
+ if (otherCrl)
+ {
+ return new DerInteger(5);
+ }
+
+ if (attrCertV2Found)
+ {
+ return new DerInteger(4);
+ }
+
+ if (attrCertV1Found)
+ {
+ return new DerInteger(3);
+ }
+
+ if (contentOid.Equals(Data)
+ && !CheckForVersion3(_signers))
+ {
+ return new DerInteger(1);
+ }
+
+ return new DerInteger(3);
+ }
+
+ private bool CheckForVersion3(
+ IList signerInfos)
+ {
+ foreach (SignerInformation si in signerInfos)
+ {
+ SignerInfo s = SignerInfo.GetInstance(si.ToSignerInfo());
+
+ if (s.Version.Value.IntValue == 3)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private class NullOutputStream
+ : BaseOutputStream
+ {
+ public override void WriteByte(
+ byte b)
+ {
+ // do nothing
+ }
+
+ public override void Write(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ // do nothing
+ }
+ }
+
+ private class TeeOutputStream
+ : BaseOutputStream
+ {
+ private readonly Stream s1, s2;
+
+ public TeeOutputStream(Stream dataOutputStream, Stream digStream)
+ {
+ Debug.Assert(dataOutputStream.CanWrite);
+ Debug.Assert(digStream.CanWrite);
+
+ this.s1 = dataOutputStream;
+ this.s2 = digStream;
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ s1.Write(buffer, offset, count);
+ s2.Write(buffer, offset, count);
+ }
+
+ public override void WriteByte(byte b)
+ {
+ s1.WriteByte(b);
+ s2.WriteByte(b);
+ }
+
+ public override void Close()
+ {
+ s1.Close();
+ s2.Close();
+ }
+ }
+
+ private class CmsSignedDataOutputStream
+ : BaseOutputStream
+ {
+ private readonly CmsSignedDataStreamGenerator outer;
+
+ private Stream _out;
+ private DerObjectIdentifier _contentOID;
+ private BerSequenceGenerator _sGen;
+ private BerSequenceGenerator _sigGen;
+ private BerSequenceGenerator _eiGen;
+
+ public CmsSignedDataOutputStream(
+ CmsSignedDataStreamGenerator outer,
+ Stream outStream,
+ string contentOID,
+ BerSequenceGenerator sGen,
+ BerSequenceGenerator sigGen,
+ BerSequenceGenerator eiGen)
+ {
+ this.outer = outer;
+
+ _out = outStream;
+ _contentOID = new DerObjectIdentifier(contentOID);
+ _sGen = sGen;
+ _sigGen = sigGen;
+ _eiGen = eiGen;
+ }
+
+ public override void WriteByte(
+ byte b)
+ {
+ _out.WriteByte(b);
+ }
+
+ public override void Write(
+ byte[] bytes,
+ int off,
+ int len)
+ {
+ _out.Write(bytes, off, len);
+ }
+
+ public override void Close()
+ {
+ _out.Close();
+ _eiGen.Close();
+
+ outer._digests.Clear(); // clear the current preserved digest state
+
+ if (outer._certs.Count > 0)
+ {
+ Asn1Set certs = CmsUtilities.CreateBerSetFromList(outer._certs);
+
+ WriteToGenerator(_sigGen, new BerTaggedObject(false, 0, certs));
+ }
+
+ if (outer._crls.Count > 0)
+ {
+ Asn1Set crls = CmsUtilities.CreateBerSetFromList(outer._crls);
+
+ WriteToGenerator(_sigGen, new BerTaggedObject(false, 1, crls));
+ }
+
+ //
+ // Calculate the digest hashes
+ //
+ foreach (DictionaryEntry de in outer._messageDigests)
+ {
+ outer._messageHashes.Add(de.Key, DigestUtilities.DoFinal((IDigest)de.Value));
+ }
+
+ // TODO If the digest OIDs for precalculated signers weren't mixed in with
+ // the others, we could fill in outer._digests here, instead of SignerInf.ToSignerInfo
+
+ //
+ // add the precalculated SignerInfo objects.
+ //
+ Asn1EncodableVector signerInfos = new Asn1EncodableVector();
+
+ foreach (SignerInformation signer in outer._signers)
+ {
+ signerInfos.Add(signer.ToSignerInfo());
+ }
+
+ //
+ // add the SignerInfo objects
+ //
+ foreach (SignerInf signer in outer._signerInfs)
+ {
+ try
+ {
+ signerInfos.Add(signer.ToSignerInfo(_contentOID));
+ }
+ catch (IOException e)
+ {
+ throw new IOException("encoding error." + e);
+ }
+ catch (SignatureException e)
+ {
+ throw new IOException("error creating signature." + e);
+ }
+ catch (CertificateEncodingException e)
+ {
+ throw new IOException("error creating sid." + e);
+ }
+ }
+
+ WriteToGenerator(_sigGen, new DerSet(signerInfos));
+
+ _sigGen.Close();
+ _sGen.Close();
+ base.Close();
+ }
+
+ private static void WriteToGenerator(
+ Asn1Generator ag,
+ Asn1Encodable ae)
+ {
+ byte[] encoded = ae.GetEncoded();
+ ag.GetRawOutputStream().Write(encoded, 0, encoded.Length);
+ }
+ }
+ }
+}
diff --git a/src/core/srcbc/cms/PKCS5Scheme2PBEKey.cs b/src/core/srcbc/cms/PKCS5Scheme2PBEKey.cs
index a5234ef..8fc9834 100644
--- a/src/core/srcbc/cms/PKCS5Scheme2PBEKey.cs
+++ b/src/core/srcbc/cms/PKCS5Scheme2PBEKey.cs
@@ -1,38 +1,47 @@
-using System;
-
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Generators;
-using Org.BouncyCastle.Crypto.Parameters;
-
-namespace Org.BouncyCastle.Cms
-{
- ///
- /// PKCS5 scheme-2 - password converted to bytes assuming ASCII.
- ///
- public class Pkcs5Scheme2PbeKey
- : CmsPbeKey
- {
- public Pkcs5Scheme2PbeKey(
- string password,
- byte[] salt,
- int iterationCount)
- : base(password, salt, iterationCount)
- {
- }
-
- internal override KeyParameter GetEncoded(
- string algorithmOid)
- {
- Pkcs5S2ParametersGenerator gen = new Pkcs5S2ParametersGenerator();
-
- gen.Init(
- PbeParametersGenerator.Pkcs5PasswordToBytes(this.Password),
- this.Salt,
- this.IterationCount);
-
- return (KeyParameter) gen.GenerateDerivedParameters(
- algorithmOid,
- CmsEnvelopedHelper.Instance.GetKeySize(algorithmOid));
- }
- }
-}
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Cms
+{
+ ///
+ /// PKCS5 scheme-2 - password converted to bytes assuming ASCII.
+ ///
+ public class Pkcs5Scheme2PbeKey
+ : CmsPbeKey
+ {
+ public Pkcs5Scheme2PbeKey(
+ string password,
+ byte[] salt,
+ int iterationCount)
+ : base(password, salt, iterationCount)
+ {
+ }
+
+ public Pkcs5Scheme2PbeKey(
+ string password,
+ AlgorithmIdentifier keyDerivationAlgorithm)
+ : base(password, keyDerivationAlgorithm)
+ {
+ }
+
+ internal override KeyParameter GetEncoded(
+ string algorithmOid)
+ {
+ Pkcs5S2ParametersGenerator gen = new Pkcs5S2ParametersGenerator();
+
+ gen.Init(
+ PbeParametersGenerator.Pkcs5PasswordToBytes(this.Password),
+ this.Salt,
+ this.IterationCount);
+
+ return (KeyParameter) gen.GenerateDerivedParameters(
+ algorithmOid,
+ CmsEnvelopedHelper.Instance.GetKeySize(algorithmOid));
+ }
+ }
+}
diff --git a/src/core/srcbc/cms/PKCS5Scheme2UTF8PBEKey.cs b/src/core/srcbc/cms/PKCS5Scheme2UTF8PBEKey.cs
index a5291bc..84dad0f 100644
--- a/src/core/srcbc/cms/PKCS5Scheme2UTF8PBEKey.cs
+++ b/src/core/srcbc/cms/PKCS5Scheme2UTF8PBEKey.cs
@@ -1,38 +1,47 @@
-using System;
-
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Generators;
-using Org.BouncyCastle.Crypto.Parameters;
-
-namespace Org.BouncyCastle.Cms
-{
- /**
- * PKCS5 scheme-2 - password converted to bytes using UTF-8.
- */
- public class Pkcs5Scheme2Utf8PbeKey
- : CmsPbeKey
- {
- public Pkcs5Scheme2Utf8PbeKey(
- string password,
- byte[] salt,
- int iterationCount)
- : base(password, salt, iterationCount)
- {
- }
-
- internal override KeyParameter GetEncoded(
- string algorithmOid)
- {
- Pkcs5S2ParametersGenerator gen = new Pkcs5S2ParametersGenerator();
-
- gen.Init(
- PbeParametersGenerator.Pkcs5PasswordToUtf8Bytes(this.Password),
- this.Salt,
- this.IterationCount);
-
- return (KeyParameter) gen.GenerateDerivedParameters(
- algorithmOid,
- CmsEnvelopedHelper.Instance.GetKeySize(algorithmOid));
- }
- }
-}
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Cms
+{
+ /**
+ * PKCS5 scheme-2 - password converted to bytes using UTF-8.
+ */
+ public class Pkcs5Scheme2Utf8PbeKey
+ : CmsPbeKey
+ {
+ public Pkcs5Scheme2Utf8PbeKey(
+ string password,
+ byte[] salt,
+ int iterationCount)
+ : base(password, salt, iterationCount)
+ {
+ }
+
+ public Pkcs5Scheme2Utf8PbeKey(
+ string password,
+ AlgorithmIdentifier keyDerivationAlgorithm)
+ : base(password, keyDerivationAlgorithm)
+ {
+ }
+
+ internal override KeyParameter GetEncoded(
+ string algorithmOid)
+ {
+ Pkcs5S2ParametersGenerator gen = new Pkcs5S2ParametersGenerator();
+
+ gen.Init(
+ PbeParametersGenerator.Pkcs5PasswordToUtf8Bytes(this.Password),
+ this.Salt,
+ this.IterationCount);
+
+ return (KeyParameter) gen.GenerateDerivedParameters(
+ algorithmOid,
+ CmsEnvelopedHelper.Instance.GetKeySize(algorithmOid));
+ }
+ }
+}
diff --git a/src/core/srcbc/cms/PasswordRecipientInformation.cs b/src/core/srcbc/cms/PasswordRecipientInformation.cs
index 15a67bc..e27f326 100644
--- a/src/core/srcbc/cms/PasswordRecipientInformation.cs
+++ b/src/core/srcbc/cms/PasswordRecipientInformation.cs
@@ -1,88 +1,85 @@
-using System;
-using System.IO;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Asn1.Cms;
-using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Security;
-
-namespace Org.BouncyCastle.Cms
-{
- /**
- * the RecipientInfo class for a recipient who has been sent a message
- * encrypted using a password.
- */
- public class PasswordRecipientInformation
- : RecipientInformation
- {
- private readonly PasswordRecipientInfo _info;
-// private readonly AlgorithmIdentifier _encAlg;
-
- public PasswordRecipientInformation(
- PasswordRecipientInfo info,
- AlgorithmIdentifier encAlg,
- Stream data)
- : base(encAlg, AlgorithmIdentifier.GetInstance(info.KeyEncryptionAlgorithm), data)
- {
- this._info = info;
-// this._encAlg = encAlg;
- this._rid = new RecipientID();
- }
-
- /**
- * return the object identifier for the key derivation algorithm, or null
- * if there is none present.
- *
- * @return OID for key derivation algorithm, if present.
- */
- public virtual AlgorithmIdentifier KeyDerivationAlgorithm
- {
- get
- {
- return _info.KeyDerivationAlgorithm;
- }
- }
-
- /**
- * decrypt the content and return an input stream.
- */
- public override CmsTypedStream GetContentStream(
- ICipherParameters key)
- {
- try
- {
- AlgorithmIdentifier kekAlg = AlgorithmIdentifier.GetInstance(_info.KeyEncryptionAlgorithm);
- Asn1Sequence kekAlgParams = (Asn1Sequence)kekAlg.Parameters;
- byte[] encryptedKey = _info.EncryptedKey.GetOctets();
- string kekAlgName = DerObjectIdentifier.GetInstance(kekAlgParams[0]).Id;
- string cName = CmsEnvelopedHelper.Instance.GetRfc3211WrapperName(kekAlgName);
- IWrapper keyWrapper = WrapperUtilities.GetWrapper(cName);
-
- byte[] iv = Asn1OctetString.GetInstance(kekAlgParams[1]).GetOctets();
-
- ICipherParameters parameters = ((CmsPbeKey)key).GetEncoded(kekAlgName);
- parameters = new ParametersWithIV(parameters, iv);
-
- keyWrapper.Init(false, parameters);
-
- AlgorithmIdentifier aid = _encAlg;
- string alg = aid.ObjectID.Id;
-
- KeyParameter sKey = ParameterUtilities.CreateKeyParameter(
- alg, keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length));
-
- return GetContentFromSessionKey(sKey);
- }
- catch (SecurityUtilityException e)
- {
- throw new CmsException("couldn't create cipher.", e);
- }
- catch (InvalidKeyException e)
- {
- throw new CmsException("key invalid in message.", e);
- }
- }
- }
-}
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Cms
+{
+ /**
+ * the RecipientInfo class for a recipient who has been sent a message
+ * encrypted using a password.
+ */
+ public class PasswordRecipientInformation
+ : RecipientInformation
+ {
+ private readonly PasswordRecipientInfo _info;
+// private readonly AlgorithmIdentifier _encAlg;
+
+ public PasswordRecipientInformation(
+ PasswordRecipientInfo info,
+ AlgorithmIdentifier encAlg,
+ Stream data)
+ : base(encAlg, AlgorithmIdentifier.GetInstance(info.KeyEncryptionAlgorithm), data)
+ {
+ this._info = info;
+// this._encAlg = encAlg;
+ this._rid = new RecipientID();
+ }
+
+ /**
+ * return the object identifier for the key derivation algorithm, or null
+ * if there is none present.
+ *
+ * @return OID for key derivation algorithm, if present.
+ */
+ public virtual AlgorithmIdentifier KeyDerivationAlgorithm
+ {
+ get { return _info.KeyDerivationAlgorithm; }
+ }
+
+ /**
+ * decrypt the content and return an input stream.
+ */
+ public override CmsTypedStream GetContentStream(
+ ICipherParameters key)
+ {
+ try
+ {
+ AlgorithmIdentifier kekAlg = AlgorithmIdentifier.GetInstance(_info.KeyEncryptionAlgorithm);
+ Asn1Sequence kekAlgParams = (Asn1Sequence)kekAlg.Parameters;
+ byte[] encryptedKey = _info.EncryptedKey.GetOctets();
+ string kekAlgName = DerObjectIdentifier.GetInstance(kekAlgParams[0]).Id;
+ string cName = CmsEnvelopedHelper.Instance.GetRfc3211WrapperName(kekAlgName);
+ IWrapper keyWrapper = WrapperUtilities.GetWrapper(cName);
+
+ byte[] iv = Asn1OctetString.GetInstance(kekAlgParams[1]).GetOctets();
+
+ ICipherParameters parameters = ((CmsPbeKey)key).GetEncoded(kekAlgName);
+ parameters = new ParametersWithIV(parameters, iv);
+
+ keyWrapper.Init(false, parameters);
+
+ AlgorithmIdentifier aid = _encAlg;
+ string alg = aid.ObjectID.Id;
+
+ KeyParameter sKey = ParameterUtilities.CreateKeyParameter(
+ alg, keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length));
+
+ return GetContentFromSessionKey(sKey);
+ }
+ catch (SecurityUtilityException e)
+ {
+ throw new CmsException("couldn't create cipher.", e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CmsException("key invalid in message.", e);
+ }
+ }
+ }
+}
diff --git a/src/core/srcbc/cms/SignerInformation.cs b/src/core/srcbc/cms/SignerInformation.cs
index df7fa16..440a49f 100644
--- a/src/core/srcbc/cms/SignerInformation.cs
+++ b/src/core/srcbc/cms/SignerInformation.cs
@@ -1,637 +1,637 @@
-using System;
-using System.Collections;
-using System.Diagnostics;
-using System.IO;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Asn1.Cms;
-using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Engines;
-using Org.BouncyCastle.Crypto.Signers;
-using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Utilities;
-using Org.BouncyCastle.X509;
-
-namespace Org.BouncyCastle.Cms
-{
- /**
- * an expanded SignerInfo block from a CMS Signed message
- */
- public class SignerInformation
- {
- private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
-
- private SignerID sid;
- private SignerInfo info;
- private AlgorithmIdentifier digestAlgorithm;
- private AlgorithmIdentifier encryptionAlgorithm;
- private Asn1Set signedAttributes;
- private Asn1Set unsignedAttributes;
- private CmsProcessable content;
- private byte[] signature;
- private DerObjectIdentifier contentType;
- private IDigestCalculator digestCalculator;
- private byte[] resultDigest;
-
- internal SignerInformation(
- SignerInfo info,
- DerObjectIdentifier contentType,
- CmsProcessable content,
- IDigestCalculator digestCalculator)
- {
- this.info = info;
- this.sid = new SignerID();
- this.contentType = contentType;
-
- try
- {
- SignerIdentifier s = info.SignerID;
-
- if (s.IsTagged)
- {
- Asn1OctetString octs = Asn1OctetString.GetInstance(s.ID);
-
- sid.SubjectKeyIdentifier = octs.GetOctets();
- }
- else
- {
- Asn1.Cms.IssuerAndSerialNumber iAnds =
- Asn1.Cms.IssuerAndSerialNumber.GetInstance(s.ID);
-
- sid.Issuer = iAnds.Name;
- sid.SerialNumber = iAnds.SerialNumber.Value;
- }
- }
- catch (IOException)
- {
- throw new ArgumentException("invalid sid in SignerInfo");
- }
-
- this.digestAlgorithm = info.DigestAlgorithm;
- this.signedAttributes = info.AuthenticatedAttributes;
- this.unsignedAttributes = info.UnauthenticatedAttributes;
- this.encryptionAlgorithm = info.DigestEncryptionAlgorithm;
- this.signature = info.EncryptedDigest.GetOctets();
-
- this.content = content;
- this.digestCalculator = digestCalculator;
- }
-
- public SignerID SignerID
- {
- get { return sid; }
- }
-
- /**
- * return the version number for this objects underlying SignerInfo structure.
- */
- public int Version
- {
- get { return info.Version.Value.IntValue; }
- }
-
- public AlgorithmIdentifier DigestAlgorithmID
- {
- get { return digestAlgorithm; }
- }
-
- /**
- * return the object identifier for the signature.
- */
- public string DigestAlgOid
- {
- get { return digestAlgorithm.ObjectID.Id; }
- }
-
- /**
- * return the signature parameters, or null if there aren't any.
- */
- public Asn1Object DigestAlgParams
- {
- get
- {
- Asn1Encodable ae = digestAlgorithm.Parameters;
-
- return ae == null ? null : ae.ToAsn1Object();
- }
- }
-
- /**
- * return the content digest that was calculated during verification.
- */
- public byte[] GetContentDigest()
- {
- if (resultDigest == null)
- {
- throw new InvalidOperationException("method can only be called after verify.");
- }
-
- return (byte[])resultDigest.Clone();
- }
-
- public AlgorithmIdentifier EncryptionAlgorithmID
- {
- get { return encryptionAlgorithm; }
- }
-
- /**
- * return the object identifier for the signature.
- */
- public string EncryptionAlgOid
- {
- get { return encryptionAlgorithm.ObjectID.Id; }
- }
-
- /**
- * return the signature/encryption algorithm parameters, or null if
- * there aren't any.
- */
- public Asn1Object EncryptionAlgParams
- {
- get
- {
- Asn1Encodable ae = encryptionAlgorithm.Parameters;
-
- return ae == null ? null : ae.ToAsn1Object();
- }
- }
-
- /**
- * return a table of the signed attributes - indexed by
- * the OID of the attribute.
- */
- public Asn1.Cms.AttributeTable SignedAttributes
- {
- get
- {
- return signedAttributes == null
- ? null
- : new Asn1.Cms.AttributeTable(signedAttributes);
- }
- }
-
- /**
- * return a table of the unsigned attributes indexed by
- * the OID of the attribute.
- */
- public Asn1.Cms.AttributeTable UnsignedAttributes
- {
- get
- {
- return unsignedAttributes == null
- ? null
- : new Asn1.Cms.AttributeTable(unsignedAttributes);
- }
- }
-
- /**
- * return the encoded signature
- */
- public byte[] GetSignature()
- {
- return (byte[]) signature.Clone();
- }
-
- /**
- * Return a SignerInformationStore containing the counter signatures attached to this
- * signer. If no counter signatures are present an empty store is returned.
- */
- public SignerInformationStore GetCounterSignatures()
- {
- Asn1.Cms.AttributeTable unsignedAttributeTable = UnsignedAttributes;
- if (unsignedAttributeTable == null)
- {
- return new SignerInformationStore(new ArrayList(0));
- }
-
- IList counterSignatures = new ArrayList();
-
- Asn1.Cms.Attribute counterSignatureAttribute = unsignedAttributeTable[CmsAttributes.CounterSignature];
- if (counterSignatureAttribute != null)
- {
- Asn1Set values = counterSignatureAttribute.AttrValues;
- counterSignatures = new ArrayList(values.Count);
-
- foreach (Asn1Encodable asn1Obj in values)
- {
- SignerInfo si = SignerInfo.GetInstance(asn1Obj.ToAsn1Object());
-
- string digestName = CmsSignedHelper.Instance.GetDigestAlgName(si.DigestAlgorithm.ObjectID.Id);
-
- counterSignatures.Add(new SignerInformation(si, CmsAttributes.CounterSignature, null, new CounterSignatureDigestCalculator(digestName, GetSignature())));
- }
- }
-
- return new SignerInformationStore(counterSignatures);
- }
-
- /**
- * return the DER encoding of the signed attributes.
- * @throws IOException if an encoding error occurs.
- */
- public byte[] GetEncodedSignedAttributes()
- {
- return signedAttributes == null
- ? null
- : signedAttributes.GetEncoded(Asn1Encodable.Der);
- }
-
- private bool DoVerify(
- AsymmetricKeyParameter key,
- Asn1.Cms.AttributeTable signedAttrTable)
- {
- string digestName = Helper.GetDigestAlgName(this.DigestAlgOid);
- IDigest digest = Helper.GetDigestInstance(digestName);
-
- DerObjectIdentifier sigAlgOid = this.encryptionAlgorithm.ObjectID;
- Asn1Encodable sigParams = this.encryptionAlgorithm.Parameters;
- ISigner sig;
-
- if (sigAlgOid.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdRsassaPss))
- {
- // RFC 4056 2.2
- // When the id-RSASSA-PSS algorithm identifier is used for a signature,
- // the AlgorithmIdentifier parameters field MUST contain RSASSA-PSS-params.
- if (sigParams == null)
- throw new CmsException("RSASSA-PSS signature must specify algorithm parameters");
-
- try
- {
- // TODO Provide abstract configuration mechanism
-
- Asn1.Pkcs.RsassaPssParameters pss = Asn1.Pkcs.RsassaPssParameters.GetInstance(
- sigParams.ToAsn1Object());
-
- if (!pss.HashAlgorithm.ObjectID.Equals(this.digestAlgorithm.ObjectID))
- throw new CmsException("RSASSA-PSS signature parameters specified incorrect hash algorithm");
- if (!pss.MaskGenAlgorithm.ObjectID.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdMgf1))
- throw new CmsException("RSASSA-PSS signature parameters specified unknown MGF");
-
- IDigest pssDigest = DigestUtilities.GetDigest(pss.HashAlgorithm.ObjectID);
- int saltLength = pss.SaltLength.Value.IntValue;
- byte trailerField = (byte) pss.TrailerField.Value.IntValue;
-
- // RFC 4055 3.1
- // The value MUST be 1, which represents the trailer field with hexadecimal value 0xBC
- if (trailerField != 1)
- throw new CmsException("RSASSA-PSS signature parameters must have trailerField of 1");
-
- sig = new PssSigner(new RsaBlindedEngine(), pssDigest, saltLength);
- }
- catch (Exception e)
- {
- throw new CmsException("failed to set RSASSA-PSS signature parameters", e);
- }
- }
- else
- {
- // TODO Probably too strong a check at the moment
-// if (sigParams != null)
-// throw new CmsException("unrecognised signature parameters provided");
-
- string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(this.EncryptionAlgOid);
-
- sig = Helper.GetSignatureInstance(signatureName);
- }
-
- try
- {
- sig.Init(false, key);
-
- if (signedAttributes == null)
- {
- if (content != null)
- {
- content.Write(new CmsSignedDataGenerator.SigOutputStream(sig));
- content.Write(new CmsSignedDataGenerator.DigOutputStream(digest));
-
- resultDigest = DigestUtilities.DoFinal(digest);
- }
- else
- {
- resultDigest = digestCalculator.GetDigest();
-
- // need to decrypt signature and check message bytes
- return VerifyDigest(resultDigest, key, this.GetSignature());
- }
- }
- else
- {
- byte[] hash;
- if (content != null)
- {
- content.Write(
- new CmsSignedDataGenerator.DigOutputStream(digest));
-
- hash = DigestUtilities.DoFinal(digest);
- }
- else if (digestCalculator != null)
- {
- hash = digestCalculator.GetDigest();
- }
- else
- {
- hash = null;
- }
-
- resultDigest = hash;
-
- Asn1.Cms.Attribute dig = signedAttrTable[Asn1.Cms.CmsAttributes.MessageDigest];
- Asn1.Cms.Attribute type = signedAttrTable[Asn1.Cms.CmsAttributes.ContentType];
-
- if (dig == null)
- {
- throw new SignatureException("no hash for content found in signed attributes");
- }
-
- if (type == null && !contentType.Equals(CmsAttributes.CounterSignature))
- {
- throw new SignatureException("no content type id found in signed attributes");
- }
-
- Asn1Object hashObj = dig.AttrValues[0].ToAsn1Object();
-
- if (hashObj is Asn1OctetString)
- {
- byte[] signedHash = ((Asn1OctetString)hashObj).GetOctets();
-
- if (!Arrays.AreEqual(hash, signedHash))
- {
- throw new SignatureException("content hash found in signed attributes different");
- }
- }
- else if (hashObj is DerNull)
- {
- if (hash != null)
- {
- throw new SignatureException("NULL hash found in signed attributes when one expected");
- }
- }
-
- if (type != null)
- {
- DerObjectIdentifier typeOID = (DerObjectIdentifier)type.AttrValues[0];
-
- if (!typeOID.Equals(contentType))
- {
- throw new SignatureException("contentType in signed attributes different");
- }
- }
-
- byte[] tmp = this.GetEncodedSignedAttributes();
- sig.BlockUpdate(tmp, 0, tmp.Length);
- }
-
- return sig.VerifySignature(this.GetSignature());
- }
- catch (InvalidKeyException e)
- {
- throw new CmsException(
- "key not appropriate to signature in message.", e);
- }
- catch (IOException e)
- {
- throw new CmsException(
- "can't process mime object to create signature.", e);
- }
- catch (SignatureException e)
- {
- throw new CmsException(
- "invalid signature format in message: " + e.Message, e);
- }
- }
-
- private bool IsNull(
- Asn1Encodable o)
- {
- return (o is Asn1Null) || (o == null);
- }
-
- private DigestInfo DerDecode(
- byte[] encoding)
- {
- if (encoding[0] != (int)(Asn1Tags.Constructed | Asn1Tags.Sequence))
- {
- throw new IOException("not a digest info object");
- }
-
- DigestInfo digInfo = DigestInfo.GetInstance(Asn1Object.FromByteArray(encoding));
-
- // length check to avoid Bleichenbacher vulnerability
-
- if (digInfo.GetEncoded().Length != encoding.Length)
- {
- throw new CmsException("malformed RSA signature");
- }
-
- return digInfo;
- }
-
- private bool VerifyDigest(
- byte[] digest,
- AsymmetricKeyParameter key,
- byte[] signature)
- {
- string algorithm = Helper.GetEncryptionAlgName(this.EncryptionAlgOid);
-
- try
- {
- if (algorithm.Equals("RSA"))
- {
- IBufferedCipher c = CipherUtilities.GetCipher("RSA//PKCS1Padding");
-
- c.Init(false, key);
-
- byte[] decrypt = c.DoFinal(signature);
-
- DigestInfo digInfo = DerDecode(decrypt);
-
- if (!digInfo.AlgorithmID.ObjectID.Equals(digestAlgorithm.ObjectID))
- {
- return false;
- }
-
- if (!IsNull(digInfo.AlgorithmID.Parameters))
- {
- return false;
- }
-
- byte[] sigHash = digInfo.GetDigest();
-
- return Arrays.AreEqual(digest, sigHash);
- }
- else if (algorithm.Equals("DSA"))
- {
- ISigner sig = SignerUtilities.GetSigner("NONEwithDSA");
-
- sig.Init(false, key);
-
- sig.BlockUpdate(digest, 0, digest.Length);
-
- return sig.VerifySignature(signature);
- }
- else
- {
- throw new CmsException("algorithm: " + algorithm + " not supported in base signatures.");
- }
- }
- catch (SecurityUtilityException e)
- {
- throw e;
- }
- catch (GeneralSecurityException e)
- {
- throw new CmsException("Exception processing signature: " + e, e);
- }
- catch (IOException e)
- {
- throw new CmsException("Exception decoding signature: " + e, e);
- }
- }
-
- /**
- * verify that the given public key succesfully handles and confirms the
- * signature associated with this signer.
- */
- public bool Verify(
- AsymmetricKeyParameter pubKey)
- {
- if (pubKey.IsPrivate)
- throw new ArgumentException("Expected public key", "pubKey");
-
- return DoVerify(pubKey, this.SignedAttributes);
- }
-
- /**
- * verify that the given certificate successfully handles and confirms
- * the signature associated with this signer and, if a signingTime
- * attribute is available, that the certificate was valid at the time the
- * signature was generated.
- */
- public bool Verify(
- X509Certificate cert)
- {
- Asn1.Cms.AttributeTable attr = this.SignedAttributes;
-
- if (attr != null)
- {
- Asn1EncodableVector v = attr.GetAll(CmsAttributes.SigningTime);
- switch (v.Count)
- {
- case 0:
- break;
- case 1:
- {
- Asn1.Cms.Attribute t = (Asn1.Cms.Attribute) v[0];
- Debug.Assert(t != null);
-
- Asn1Set attrValues = t.AttrValues;
- if (attrValues.Count != 1)
- throw new CmsException("A signing-time attribute MUST have a single attribute value");
-
- Asn1.Cms.Time time = Asn1.Cms.Time.GetInstance(attrValues[0].ToAsn1Object());
-
- cert.CheckValidity(time.Date);
- break;
- }
- default:
- throw new CmsException("The SignedAttributes in a signerInfo MUST NOT include multiple instances of the signing-time attribute");
- }
- }
-
- return DoVerify(cert.GetPublicKey(), attr);
- }
-
- /**
- * Return the base ASN.1 CMS structure that this object contains.
- *
- * @return an object containing a CMS SignerInfo structure.
- */
- public SignerInfo ToSignerInfo()
- {
- return info;
- }
-
- /**
- * Return a signer information object with the passed in unsigned
- * attributes replacing the ones that are current associated with
- * the object passed in.
- *
- * @param signerInformation the signerInfo to be used as the basis.
- * @param unsignedAttributes the unsigned attributes to add.
- * @return a copy of the original SignerInformationObject with the changed attributes.
- */
- public static SignerInformation ReplaceUnsignedAttributes(
- SignerInformation signerInformation,
- Asn1.Cms.AttributeTable unsignedAttributes)
- {
- SignerInfo sInfo = signerInformation.info;
- Asn1Set unsignedAttr = null;
-
- if (unsignedAttributes != null)
- {
- unsignedAttr = new DerSet(unsignedAttributes.ToAsn1EncodableVector());
- }
-
- return new SignerInformation(
- new SignerInfo(
- sInfo.SignerID,
- sInfo.DigestAlgorithm,
- sInfo.AuthenticatedAttributes,
- sInfo.DigestEncryptionAlgorithm,
- sInfo.EncryptedDigest,
- unsignedAttr),
- signerInformation.contentType,
- signerInformation.content,
- null);
- }
-
- /**
- * Return a signer information object with passed in SignerInformationStore representing counter
- * signatures attached as an unsigned attribute.
- *
- * @param signerInformation the signerInfo to be used as the basis.
- * @param counterSigners signer info objects carrying counter signature.
- * @return a copy of the original SignerInformationObject with the changed attributes.
- */
- public static SignerInformation AddCounterSigners(
- SignerInformation signerInformation,
- SignerInformationStore counterSigners)
- {
- SignerInfo sInfo = signerInformation.info;
- Asn1.Cms.AttributeTable unsignedAttr = signerInformation.UnsignedAttributes;
- Asn1EncodableVector v;
-
- if (unsignedAttr != null)
- {
- v = unsignedAttr.ToAsn1EncodableVector();
- }
- else
- {
- v = new Asn1EncodableVector();
- }
-
- Asn1EncodableVector sigs = new Asn1EncodableVector();
-
- foreach (SignerInformation sigInf in counterSigners.GetSigners())
- {
- sigs.Add(sigInf.ToSignerInfo());
- }
-
- v.Add(new Asn1.Cms.Attribute(CmsAttributes.CounterSignature, new DerSet(sigs)));
-
- return new SignerInformation(
- new SignerInfo(
- sInfo.SignerID,
- sInfo.DigestAlgorithm,
- sInfo.AuthenticatedAttributes,
- sInfo.DigestEncryptionAlgorithm,
- sInfo.EncryptedDigest,
- new DerSet(v)),
- signerInformation.contentType,
- signerInformation.content,
- null);
- }
- }
-}
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+ /**
+ * an expanded SignerInfo block from a CMS Signed message
+ */
+ public class SignerInformation
+ {
+ private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
+
+ private SignerID sid;
+ private SignerInfo info;
+ private AlgorithmIdentifier digestAlgorithm;
+ private AlgorithmIdentifier encryptionAlgorithm;
+ private Asn1Set signedAttributes;
+ private Asn1Set unsignedAttributes;
+ private CmsProcessable content;
+ private byte[] signature;
+ private DerObjectIdentifier contentType;
+ private IDigestCalculator digestCalculator;
+ private byte[] resultDigest;
+
+ internal SignerInformation(
+ SignerInfo info,
+ DerObjectIdentifier contentType,
+ CmsProcessable content,
+ IDigestCalculator digestCalculator)
+ {
+ this.info = info;
+ this.sid = new SignerID();
+ this.contentType = contentType;
+
+ try
+ {
+ SignerIdentifier s = info.SignerID;
+
+ if (s.IsTagged)
+ {
+ Asn1OctetString octs = Asn1OctetString.GetInstance(s.ID);
+
+ sid.SubjectKeyIdentifier = octs.GetEncoded();
+ }
+ else
+ {
+ Asn1.Cms.IssuerAndSerialNumber iAnds =
+ Asn1.Cms.IssuerAndSerialNumber.GetInstance(s.ID);
+
+ sid.Issuer = iAnds.Name;
+ sid.SerialNumber = iAnds.SerialNumber.Value;
+ }
+ }
+ catch (IOException)
+ {
+ throw new ArgumentException("invalid sid in SignerInfo");
+ }
+
+ this.digestAlgorithm = info.DigestAlgorithm;
+ this.signedAttributes = info.AuthenticatedAttributes;
+ this.unsignedAttributes = info.UnauthenticatedAttributes;
+ this.encryptionAlgorithm = info.DigestEncryptionAlgorithm;
+ this.signature = info.EncryptedDigest.GetOctets();
+
+ this.content = content;
+ this.digestCalculator = digestCalculator;
+ }
+
+ public SignerID SignerID
+ {
+ get { return sid; }
+ }
+
+ /**
+ * return the version number for this objects underlying SignerInfo structure.
+ */
+ public int Version
+ {
+ get { return info.Version.Value.IntValue; }
+ }
+
+ public AlgorithmIdentifier DigestAlgorithmID
+ {
+ get { return digestAlgorithm; }
+ }
+
+ /**
+ * return the object identifier for the signature.
+ */
+ public string DigestAlgOid
+ {
+ get { return digestAlgorithm.ObjectID.Id; }
+ }
+
+ /**
+ * return the signature parameters, or null if there aren't any.
+ */
+ public Asn1Object DigestAlgParams
+ {
+ get
+ {
+ Asn1Encodable ae = digestAlgorithm.Parameters;
+
+ return ae == null ? null : ae.ToAsn1Object();
+ }
+ }
+
+ /**
+ * return the content digest that was calculated during verification.
+ */
+ public byte[] GetContentDigest()
+ {
+ if (resultDigest == null)
+ {
+ throw new InvalidOperationException("method can only be called after verify.");
+ }
+
+ return (byte[])resultDigest.Clone();
+ }
+
+ public AlgorithmIdentifier EncryptionAlgorithmID
+ {
+ get { return encryptionAlgorithm; }
+ }
+
+ /**
+ * return the object identifier for the signature.
+ */
+ public string EncryptionAlgOid
+ {
+ get { return encryptionAlgorithm.ObjectID.Id; }
+ }
+
+ /**
+ * return the signature/encryption algorithm parameters, or null if
+ * there aren't any.
+ */
+ public Asn1Object EncryptionAlgParams
+ {
+ get
+ {
+ Asn1Encodable ae = encryptionAlgorithm.Parameters;
+
+ return ae == null ? null : ae.ToAsn1Object();
+ }
+ }
+
+ /**
+ * return a table of the signed attributes - indexed by
+ * the OID of the attribute.
+ */
+ public Asn1.Cms.AttributeTable SignedAttributes
+ {
+ get
+ {
+ return signedAttributes == null
+ ? null
+ : new Asn1.Cms.AttributeTable(signedAttributes);
+ }
+ }
+
+ /**
+ * return a table of the unsigned attributes indexed by
+ * the OID of the attribute.
+ */
+ public Asn1.Cms.AttributeTable UnsignedAttributes
+ {
+ get
+ {
+ return unsignedAttributes == null
+ ? null
+ : new Asn1.Cms.AttributeTable(unsignedAttributes);
+ }
+ }
+
+ /**
+ * return the encoded signature
+ */
+ public byte[] GetSignature()
+ {
+ return (byte[]) signature.Clone();
+ }
+
+ /**
+ * Return a SignerInformationStore containing the counter signatures attached to this
+ * signer. If no counter signatures are present an empty store is returned.
+ */
+ public SignerInformationStore GetCounterSignatures()
+ {
+ Asn1.Cms.AttributeTable unsignedAttributeTable = UnsignedAttributes;
+ if (unsignedAttributeTable == null)
+ {
+ return new SignerInformationStore(new ArrayList(0));
+ }
+
+ IList counterSignatures = new ArrayList();
+
+ Asn1.Cms.Attribute counterSignatureAttribute = unsignedAttributeTable[CmsAttributes.CounterSignature];
+ if (counterSignatureAttribute != null)
+ {
+ Asn1Set values = counterSignatureAttribute.AttrValues;
+ counterSignatures = new ArrayList(values.Count);
+
+ foreach (Asn1Encodable asn1Obj in values)
+ {
+ SignerInfo si = SignerInfo.GetInstance(asn1Obj.ToAsn1Object());
+
+ string digestName = CmsSignedHelper.Instance.GetDigestAlgName(si.DigestAlgorithm.ObjectID.Id);
+
+ counterSignatures.Add(new SignerInformation(si, CmsAttributes.CounterSignature, null, new CounterSignatureDigestCalculator(digestName, GetSignature())));
+ }
+ }
+
+ return new SignerInformationStore(counterSignatures);
+ }
+
+ /**
+ * return the DER encoding of the signed attributes.
+ * @throws IOException if an encoding error occurs.
+ */
+ public byte[] GetEncodedSignedAttributes()
+ {
+ return signedAttributes == null
+ ? null
+ : signedAttributes.GetEncoded(Asn1Encodable.Der);
+ }
+
+ private bool DoVerify(
+ AsymmetricKeyParameter key,
+ Asn1.Cms.AttributeTable signedAttrTable)
+ {
+ string digestName = Helper.GetDigestAlgName(this.DigestAlgOid);
+ IDigest digest = Helper.GetDigestInstance(digestName);
+
+ DerObjectIdentifier sigAlgOid = this.encryptionAlgorithm.ObjectID;
+ Asn1Encodable sigParams = this.encryptionAlgorithm.Parameters;
+ ISigner sig;
+
+ if (sigAlgOid.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdRsassaPss))
+ {
+ // RFC 4056 2.2
+ // When the id-RSASSA-PSS algorithm identifier is used for a signature,
+ // the AlgorithmIdentifier parameters field MUST contain RSASSA-PSS-params.
+ if (sigParams == null)
+ throw new CmsException("RSASSA-PSS signature must specify algorithm parameters");
+
+ try
+ {
+ // TODO Provide abstract configuration mechanism
+
+ Asn1.Pkcs.RsassaPssParameters pss = Asn1.Pkcs.RsassaPssParameters.GetInstance(
+ sigParams.ToAsn1Object());
+
+ if (!pss.HashAlgorithm.ObjectID.Equals(this.digestAlgorithm.ObjectID))
+ throw new CmsException("RSASSA-PSS signature parameters specified incorrect hash algorithm");
+ if (!pss.MaskGenAlgorithm.ObjectID.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdMgf1))
+ throw new CmsException("RSASSA-PSS signature parameters specified unknown MGF");
+
+ IDigest pssDigest = DigestUtilities.GetDigest(pss.HashAlgorithm.ObjectID);
+ int saltLength = pss.SaltLength.Value.IntValue;
+ byte trailerField = (byte) pss.TrailerField.Value.IntValue;
+
+ // RFC 4055 3.1
+ // The value MUST be 1, which represents the trailer field with hexadecimal value 0xBC
+ if (trailerField != 1)
+ throw new CmsException("RSASSA-PSS signature parameters must have trailerField of 1");
+
+ sig = new PssSigner(new RsaBlindedEngine(), pssDigest, saltLength);
+ }
+ catch (Exception e)
+ {
+ throw new CmsException("failed to set RSASSA-PSS signature parameters", e);
+ }
+ }
+ else
+ {
+ // TODO Probably too strong a check at the moment
+// if (sigParams != null)
+// throw new CmsException("unrecognised signature parameters provided");
+
+ string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(this.EncryptionAlgOid);
+
+ sig = Helper.GetSignatureInstance(signatureName);
+ }
+
+ try
+ {
+ sig.Init(false, key);
+
+ if (signedAttributes == null)
+ {
+ if (content != null)
+ {
+ content.Write(new CmsSignedDataGenerator.SigOutputStream(sig));
+ content.Write(new CmsSignedDataGenerator.DigOutputStream(digest));
+
+ resultDigest = DigestUtilities.DoFinal(digest);
+ }
+ else
+ {
+ resultDigest = digestCalculator.GetDigest();
+
+ // need to decrypt signature and check message bytes
+ return VerifyDigest(resultDigest, key, this.GetSignature());
+ }
+ }
+ else
+ {
+ byte[] hash;
+ if (content != null)
+ {
+ content.Write(
+ new CmsSignedDataGenerator.DigOutputStream(digest));
+
+ hash = DigestUtilities.DoFinal(digest);
+ }
+ else if (digestCalculator != null)
+ {
+ hash = digestCalculator.GetDigest();
+ }
+ else
+ {
+ hash = null;
+ }
+
+ resultDigest = hash;
+
+ Asn1.Cms.Attribute dig = signedAttrTable[Asn1.Cms.CmsAttributes.MessageDigest];
+ Asn1.Cms.Attribute type = signedAttrTable[Asn1.Cms.CmsAttributes.ContentType];
+
+ if (dig == null)
+ {
+ throw new SignatureException("no hash for content found in signed attributes");
+ }
+
+ if (type == null && !contentType.Equals(CmsAttributes.CounterSignature))
+ {
+ throw new SignatureException("no content type id found in signed attributes");
+ }
+
+ Asn1Object hashObj = dig.AttrValues[0].ToAsn1Object();
+
+ if (hashObj is Asn1OctetString)
+ {
+ byte[] signedHash = ((Asn1OctetString)hashObj).GetOctets();
+
+ if (!Arrays.AreEqual(hash, signedHash))
+ {
+ throw new SignatureException("content hash found in signed attributes different");
+ }
+ }
+ else if (hashObj is DerNull)
+ {
+ if (hash != null)
+ {
+ throw new SignatureException("NULL hash found in signed attributes when one expected");
+ }
+ }
+
+ if (type != null)
+ {
+ DerObjectIdentifier typeOID = (DerObjectIdentifier)type.AttrValues[0];
+
+ if (!typeOID.Equals(contentType))
+ {
+ throw new SignatureException("contentType in signed attributes different");
+ }
+ }
+
+ byte[] tmp = this.GetEncodedSignedAttributes();
+ sig.BlockUpdate(tmp, 0, tmp.Length);
+ }
+
+ return sig.VerifySignature(this.GetSignature());
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CmsException(
+ "key not appropriate to signature in message.", e);
+ }
+ catch (IOException e)
+ {
+ throw new CmsException(
+ "can't process mime object to create signature.", e);
+ }
+ catch (SignatureException e)
+ {
+ throw new CmsException(
+ "invalid signature format in message: " + e.Message, e);
+ }
+ }
+
+ private bool IsNull(
+ Asn1Encodable o)
+ {
+ return (o is Asn1Null) || (o == null);
+ }
+
+ private DigestInfo DerDecode(
+ byte[] encoding)
+ {
+ if (encoding[0] != (int)(Asn1Tags.Constructed | Asn1Tags.Sequence))
+ {
+ throw new IOException("not a digest info object");
+ }
+
+ DigestInfo digInfo = DigestInfo.GetInstance(Asn1Object.FromByteArray(encoding));
+
+ // length check to avoid Bleichenbacher vulnerability
+
+ if (digInfo.GetEncoded().Length != encoding.Length)
+ {
+ throw new CmsException("malformed RSA signature");
+ }
+
+ return digInfo;
+ }
+
+ private bool VerifyDigest(
+ byte[] digest,
+ AsymmetricKeyParameter key,
+ byte[] signature)
+ {
+ string algorithm = Helper.GetEncryptionAlgName(this.EncryptionAlgOid);
+
+ try
+ {
+ if (algorithm.Equals("RSA"))
+ {
+ IBufferedCipher c = CipherUtilities.GetCipher("RSA//PKCS1Padding");
+
+ c.Init(false, key);
+
+ byte[] decrypt = c.DoFinal(signature);
+
+ DigestInfo digInfo = DerDecode(decrypt);
+
+ if (!digInfo.AlgorithmID.ObjectID.Equals(digestAlgorithm.ObjectID))
+ {
+ return false;
+ }
+
+ if (!IsNull(digInfo.AlgorithmID.Parameters))
+ {
+ return false;
+ }
+
+ byte[] sigHash = digInfo.GetDigest();
+
+ return Arrays.AreEqual(digest, sigHash);
+ }
+ else if (algorithm.Equals("DSA"))
+ {
+ ISigner sig = SignerUtilities.GetSigner("NONEwithDSA");
+
+ sig.Init(false, key);
+
+ sig.BlockUpdate(digest, 0, digest.Length);
+
+ return sig.VerifySignature(signature);
+ }
+ else
+ {
+ throw new CmsException("algorithm: " + algorithm + " not supported in base signatures.");
+ }
+ }
+ catch (SecurityUtilityException e)
+ {
+ throw e;
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new CmsException("Exception processing signature: " + e, e);
+ }
+ catch (IOException e)
+ {
+ throw new CmsException("Exception decoding signature: " + e, e);
+ }
+ }
+
+ /**
+ * verify that the given public key succesfully handles and confirms the
+ * signature associated with this signer.
+ */
+ public bool Verify(
+ AsymmetricKeyParameter pubKey)
+ {
+ if (pubKey.IsPrivate)
+ throw new ArgumentException("Expected public key", "pubKey");
+
+ return DoVerify(pubKey, this.SignedAttributes);
+ }
+
+ /**
+ * verify that the given certificate successfully handles and confirms
+ * the signature associated with this signer and, if a signingTime
+ * attribute is available, that the certificate was valid at the time the
+ * signature was generated.
+ */
+ public bool Verify(
+ X509Certificate cert)
+ {
+ Asn1.Cms.AttributeTable attr = this.SignedAttributes;
+
+ if (attr != null)
+ {
+ Asn1EncodableVector v = attr.GetAll(CmsAttributes.SigningTime);
+ switch (v.Count)
+ {
+ case 0:
+ break;
+ case 1:
+ {
+ Asn1.Cms.Attribute t = (Asn1.Cms.Attribute) v[0];
+ Debug.Assert(t != null);
+
+ Asn1Set attrValues = t.AttrValues;
+ if (attrValues.Count != 1)
+ throw new CmsException("A signing-time attribute MUST have a single attribute value");
+
+ Asn1.Cms.Time time = Asn1.Cms.Time.GetInstance(attrValues[0].ToAsn1Object());
+
+ cert.CheckValidity(time.Date);
+ break;
+ }
+ default:
+ throw new CmsException("The SignedAttributes in a signerInfo MUST NOT include multiple instances of the signing-time attribute");
+ }
+ }
+
+ return DoVerify(cert.GetPublicKey(), attr);
+ }
+
+ /**
+ * Return the base ASN.1 CMS structure that this object contains.
+ *
+ * @return an object containing a CMS SignerInfo structure.
+ */
+ public SignerInfo ToSignerInfo()
+ {
+ return info;
+ }
+
+ /**
+ * Return a signer information object with the passed in unsigned
+ * attributes replacing the ones that are current associated with
+ * the object passed in.
+ *
+ * @param signerInformation the signerInfo to be used as the basis.
+ * @param unsignedAttributes the unsigned attributes to add.
+ * @return a copy of the original SignerInformationObject with the changed attributes.
+ */
+ public static SignerInformation ReplaceUnsignedAttributes(
+ SignerInformation signerInformation,
+ Asn1.Cms.AttributeTable unsignedAttributes)
+ {
+ SignerInfo sInfo = signerInformation.info;
+ Asn1Set unsignedAttr = null;
+
+ if (unsignedAttributes != null)
+ {
+ unsignedAttr = new DerSet(unsignedAttributes.ToAsn1EncodableVector());
+ }
+
+ return new SignerInformation(
+ new SignerInfo(
+ sInfo.SignerID,
+ sInfo.DigestAlgorithm,
+ sInfo.AuthenticatedAttributes,
+ sInfo.DigestEncryptionAlgorithm,
+ sInfo.EncryptedDigest,
+ unsignedAttr),
+ signerInformation.contentType,
+ signerInformation.content,
+ null);
+ }
+
+ /**
+ * Return a signer information object with passed in SignerInformationStore representing counter
+ * signatures attached as an unsigned attribute.
+ *
+ * @param signerInformation the signerInfo to be used as the basis.
+ * @param counterSigners signer info objects carrying counter signature.
+ * @return a copy of the original SignerInformationObject with the changed attributes.
+ */
+ public static SignerInformation AddCounterSigners(
+ SignerInformation signerInformation,
+ SignerInformationStore counterSigners)
+ {
+ SignerInfo sInfo = signerInformation.info;
+ Asn1.Cms.AttributeTable unsignedAttr = signerInformation.UnsignedAttributes;
+ Asn1EncodableVector v;
+
+ if (unsignedAttr != null)
+ {
+ v = unsignedAttr.ToAsn1EncodableVector();
+ }
+ else
+ {
+ v = new Asn1EncodableVector();
+ }
+
+ Asn1EncodableVector sigs = new Asn1EncodableVector();
+
+ foreach (SignerInformation sigInf in counterSigners.GetSigners())
+ {
+ sigs.Add(sigInf.ToSignerInfo());
+ }
+
+ v.Add(new Asn1.Cms.Attribute(CmsAttributes.CounterSignature, new DerSet(sigs)));
+
+ return new SignerInformation(
+ new SignerInfo(
+ sInfo.SignerID,
+ sInfo.DigestAlgorithm,
+ sInfo.AuthenticatedAttributes,
+ sInfo.DigestEncryptionAlgorithm,
+ sInfo.EncryptedDigest,
+ new DerSet(v)),
+ signerInformation.contentType,
+ signerInformation.content,
+ null);
+ }
+ }
+}
diff --git a/src/core/srcbc/crypto/BufferedBlockCipher.cs b/src/core/srcbc/crypto/BufferedBlockCipher.cs
index 3c6cc49..2a3b20f 100644
--- a/src/core/srcbc/crypto/BufferedBlockCipher.cs
+++ b/src/core/srcbc/crypto/BufferedBlockCipher.cs
@@ -1,372 +1,380 @@
-using System;
-using System.Diagnostics;
-
-using Org.BouncyCastle.Crypto.Parameters;
-
-namespace Org.BouncyCastle.Crypto
-{
- /**
- * A wrapper class that allows block ciphers to be used to process data in
- * a piecemeal fashion. The BufferedBlockCipher outputs a block only when the
- * buffer is full and more data is being added, or on a doFinal.
- *
- * Note: in the case where the underlying cipher is either a CFB cipher or an
- * OFB one the last block may not be a multiple of the block size.
- *
- */
- public class BufferedBlockCipher
- : BufferedCipherBase
- {
- internal byte[] buf;
- internal int bufOff;
- internal bool forEncryption;
- internal IBlockCipher cipher;
-
- /**
- * constructor for subclasses
- */
- protected BufferedBlockCipher()
- {
- }
-
- /**
- * Create a buffered block cipher without padding.
- *
- * @param cipher the underlying block cipher this buffering object wraps.
- * false otherwise.
- */
- public BufferedBlockCipher(
- IBlockCipher cipher)
- {
- if (cipher == null)
- throw new ArgumentNullException("cipher");
-
- this.cipher = cipher;
- buf = new byte[cipher.GetBlockSize()];
- bufOff = 0;
- }
-
- public override string AlgorithmName
- {
- get { return cipher.AlgorithmName; }
- }
-
- /**
- * initialise the cipher.
- *
- * @param forEncryption if true the cipher is initialised for
- * encryption, if false for decryption.
- * @param param the key and other data required by the cipher.
- * @exception ArgumentException if the parameters argument is
- * inappropriate.
- */
- // Note: This doubles as the Init in the event that this cipher is being used as an IWrapper
- public override void Init(
- bool forEncryption,
- ICipherParameters parameters)
- {
- this.forEncryption = forEncryption;
-
- if (parameters is ParametersWithRandom)
- {
- parameters = ((ParametersWithRandom) parameters).Parameters;
- }
-
- Reset();
-
- cipher.Init(forEncryption, parameters);
- }
-
- /**
- * return the blocksize for the underlying cipher.
- *
- * @return the blocksize for the underlying cipher.
- */
- public override int GetBlockSize()
- {
- return cipher.GetBlockSize();
- }
-
- /**
- * return the size of the output buffer required for an update
- * an input of len bytes.
- *
- * @param len the length of the input.
- * @return the space required to accommodate a call to update
- * with len bytes of input.
- */
- public override int GetUpdateOutputSize(
- int length)
- {
- int total = length + bufOff;
- int leftOver = total % buf.Length;
- return total - leftOver;
- }
-
- /**
- * return the size of the output buffer required for an update plus a
- * doFinal with an input of len bytes.
- *
- * @param len the length of the input.
- * @return the space required to accommodate a call to update and doFinal
- * with len bytes of input.
- */
- public override int GetOutputSize(
- int length)
- {
- int total = length + bufOff;
- int leftOver = total % buf.Length;
- if (leftOver == 0)
- {
- return total;
- }
- return total - leftOver + buf.Length;
- }
-
- /**
- * process a single byte, producing an output block if neccessary.
- *
- * @param in the input byte.
- * @param out the space for any output that might be produced.
- * @param outOff the offset from which the output will be copied.
- * @return the number of output bytes copied to out.
- * @exception DataLengthException if there isn't enough space in out.
- * @exception InvalidOperationException if the cipher isn't initialised.
- */
- public override int ProcessByte(
- byte input,
- byte[] output,
- int outOff)
- {
- buf[bufOff++] = input;
-
- if (bufOff == buf.Length)
- {
- if ((outOff + buf.Length) > output.Length)
- throw new DataLengthException("output buffer too short");
-
- bufOff = 0;
- return cipher.ProcessBlock(buf, 0, output, outOff);
- }
-
- return 0;
- }
-
- public override byte[] ProcessByte(
- byte input)
- {
- int outLength = GetUpdateOutputSize(1);
-
- byte[] outBytes = outLength > 0 ? new byte[outLength] : null;
-
- int pos = ProcessByte(input, outBytes, 0);
-
- if (outLength > 0 && pos < outLength)
- {
- byte[] tmp = new byte[pos];
- Array.Copy(outBytes, 0, tmp, 0, pos);
- outBytes = tmp;
- }
-
- return outBytes;
- }
-
- public override byte[] ProcessBytes(
- byte[] input,
- int inOff,
- int length)
- {
- if (input == null)
- throw new ArgumentNullException("input");
- if (length < 1)
- return null;
-
- int outLength = GetUpdateOutputSize(length);
-
- byte[] outBytes = outLength > 0 ? new byte[outLength] : null;
-
- int pos = ProcessBytes(input, inOff, length, outBytes, 0);
-
- if (outLength > 0 && pos < outLength)
- {
- byte[] tmp = new byte[pos];
- Array.Copy(outBytes, 0, tmp, 0, pos);
- outBytes = tmp;
- }
-
- return outBytes;
- }
-
- /**
- * process an array of bytes, producing output if necessary.
- *
- * @param in the input byte array.
- * @param inOff the offset at which the input data starts.
- * @param len the number of bytes to be copied out of the input array.
- * @param out the space for any output that might be produced.
- * @param outOff the offset from which the output will be copied.
- * @return the number of output bytes copied to out.
- * @exception DataLengthException if there isn't enough space in out.
- * @exception InvalidOperationException if the cipher isn't initialised.
- */
- public override int ProcessBytes(
- byte[] input,
- int inOff,
- int length,
- byte[] output,
- int outOff)
- {
- if (length < 1)
- {
- if (length < 0)
- throw new ArgumentException("Can't have a negative input length!");
-
- return 0;
- }
-
- int blockSize = GetBlockSize();
- int outLength = GetUpdateOutputSize(length);
-
- if (outLength > 0)
- {
- if ((outOff + outLength) > output.Length)
- {
- throw new DataLengthException("output buffer too short");
- }
- }
-
- int resultLen = 0;
- int gapLen = buf.Length - bufOff;
- if (length > gapLen)
- {
- Array.Copy(input, inOff, buf, bufOff, gapLen);
- resultLen += cipher.ProcessBlock(buf, 0, output, outOff);
- bufOff = 0;
- length -= gapLen;
- inOff += gapLen;
- while (length > buf.Length)
- {
- resultLen += cipher.ProcessBlock(input, inOff, output, outOff + resultLen);
- length -= blockSize;
- inOff += blockSize;
- }
- }
- Array.Copy(input, inOff, buf, bufOff, length);
- bufOff += length;
- if (bufOff == buf.Length)
- {
- resultLen += cipher.ProcessBlock(buf, 0, output, outOff + resultLen);
- bufOff = 0;
- }
- return resultLen;
- }
-
- public override byte[] DoFinal()
- {
- byte[] outBytes = EmptyBuffer;
-
- int length = GetOutputSize(0);
- if (length > 0)
- {
- outBytes = new byte[length];
-
- int pos = DoFinal(outBytes, 0);
- if (pos < outBytes.Length)
- {
- byte[] tmp = new byte[pos];
- Array.Copy(outBytes, 0, tmp, 0, pos);
- outBytes = tmp;
- }
- }
-
- return outBytes;
- }
-
- public override byte[] DoFinal(
- byte[] input,
- int inOff,
- int inLen)
- {
- if (input == null)
- throw new ArgumentNullException("input");
-
- int length = GetOutputSize(inLen);
-
- byte[] outBytes = EmptyBuffer;
-
- if (length > 0)
- {
- outBytes = new byte[length];
-
- int pos = (inLen > 0)
- ? ProcessBytes(input, inOff, inLen, outBytes, 0)
- : 0;
-
- pos += DoFinal(outBytes, pos);
-
- if (pos < outBytes.Length)
- {
- byte[] tmp = new byte[pos];
- Array.Copy(outBytes, 0, tmp, 0, pos);
- outBytes = tmp;
- }
- }
-
- return outBytes;
- }
-
- /**
- * Process the last block in the buffer.
- *
- * @param out the array the block currently being held is copied into.
- * @param outOff the offset at which the copying starts.
- * @return the number of output bytes copied to out.
- * @exception DataLengthException if there is insufficient space in out for
- * the output, or the input is not block size aligned and should be.
- * @exception InvalidOperationException if the underlying cipher is not
- * initialised.
- * @exception InvalidCipherTextException if padding is expected and not found.
- * @exception DataLengthException if the input is not block size
- * aligned.
- */
- public override int DoFinal(
- byte[] output,
- int outOff)
- {
- if (bufOff != 0)
- {
- if (!cipher.IsPartialBlockOkay)
- {
- throw new DataLengthException("data not block size aligned");
- }
-
- if (outOff + bufOff > output.Length)
- {
- throw new DataLengthException("output buffer too short for DoFinal()");
- }
-
- // NB: Can't copy directly, or we may write too much output
- cipher.ProcessBlock(buf, 0, buf, 0);
- Array.Copy(buf, 0, output, outOff, bufOff);
- }
-
- int resultLen = bufOff;
-
- Reset();
-
- return resultLen;
- }
-
- /**
- * Reset the buffer and cipher. After resetting the object is in the same
- * state as it was after the last init (if there was one).
- */
- public override void Reset()
- {
- Array.Clear(buf, 0, buf.Length);
- bufOff = 0;
-
- cipher.Reset();
- }
- }
-}
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto
+{
+ /**
+ * A wrapper class that allows block ciphers to be used to process data in
+ * a piecemeal fashion. The BufferedBlockCipher outputs a block only when the
+ * buffer is full and more data is being added, or on a doFinal.
+ *
+ * Note: in the case where the underlying cipher is either a CFB cipher or an
+ * OFB one the last block may not be a multiple of the block size.
+ *
+ */
+ public class BufferedBlockCipher
+ : BufferedCipherBase
+ {
+ internal byte[] buf;
+ internal int bufOff;
+ internal bool forEncryption;
+ internal IBlockCipher cipher;
+
+ /**
+ * constructor for subclasses
+ */
+ protected BufferedBlockCipher()
+ {
+ }
+
+ /**
+ * Create a buffered block cipher without padding.
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ * false otherwise.
+ */
+ public BufferedBlockCipher(
+ IBlockCipher cipher)
+ {
+ if (cipher == null)
+ throw new ArgumentNullException("cipher");
+
+ this.cipher = cipher;
+ buf = new byte[cipher.GetBlockSize()];
+ bufOff = 0;
+ }
+
+ public override string AlgorithmName
+ {
+ get { return cipher.AlgorithmName; }
+ }
+
+ /**
+ * initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param param the key and other data required by the cipher.
+ * @exception ArgumentException if the parameters argument is
+ * inappropriate.
+ */
+ // Note: This doubles as the Init in the event that this cipher is being used as an IWrapper
+ public override void Init(
+ bool forEncryption,
+ ICipherParameters parameters)
+ {
+ this.forEncryption = forEncryption;
+
+ if (parameters is ParametersWithRandom)
+ {
+ parameters = ((ParametersWithRandom) parameters).Parameters;
+ }
+
+ Reset();
+
+ cipher.Init(forEncryption, parameters);
+ }
+
+ /**
+ * return the blocksize for the underlying cipher.
+ *
+ * @return the blocksize for the underlying cipher.
+ */
+ public override int GetBlockSize()
+ {
+ return cipher.GetBlockSize();
+ }
+
+ /**
+ * return the size of the output buffer required for an update
+ * an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update
+ * with len bytes of input.
+ */
+ public override int GetUpdateOutputSize(
+ int length)
+ {
+ int total = length + bufOff;
+ int leftOver = total % buf.Length;
+ return total - leftOver;
+ }
+
+ /**
+ * return the size of the output buffer required for an update plus a
+ * doFinal with an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update and doFinal
+ * with len bytes of input.
+ */
+ public override int GetOutputSize(
+ int length)
+ {
+ int total = length + bufOff;
+ int leftOver = total % buf.Length;
+ if (leftOver == 0)
+ {
+ return total;
+ }
+ return total - leftOver + buf.Length;
+ }
+
+ /**
+ * process a single byte, producing an output block if neccessary.
+ *
+ * @param in the input byte.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception InvalidOperationException if the cipher isn't initialised.
+ */
+ public override int ProcessByte(
+ byte input,
+ byte[] output,
+ int outOff)
+ {
+ buf[bufOff++] = input;
+
+ if (bufOff == buf.Length)
+ {
+ if ((outOff + buf.Length) > output.Length)
+ throw new DataLengthException("output buffer too short");
+
+ bufOff = 0;
+ return cipher.ProcessBlock(buf, 0, output, outOff);
+ }
+
+ return 0;
+ }
+
+ public override byte[] ProcessByte(
+ byte input)
+ {
+ int outLength = GetUpdateOutputSize(1);
+
+ byte[] outBytes = outLength > 0 ? new byte[outLength] : null;
+
+ int pos = ProcessByte(input, outBytes, 0);
+
+ if (outLength > 0 && pos < outLength)
+ {
+ byte[] tmp = new byte[pos];
+ Array.Copy(outBytes, 0, tmp, 0, pos);
+ outBytes = tmp;
+ }
+
+ return outBytes;
+ }
+
+ public override byte[] ProcessBytes(
+ byte[] input,
+ int inOff,
+ int length)
+ {
+ if (input == null)
+ throw new ArgumentNullException("input");
+ if (length < 1)
+ return null;
+
+ int outLength = GetUpdateOutputSize(length);
+
+ byte[] outBytes = outLength > 0 ? new byte[outLength] : null;
+
+ int pos = ProcessBytes(input, inOff, length, outBytes, 0);
+
+ if (outLength > 0 && pos < outLength)
+ {
+ byte[] tmp = new byte[pos];
+ Array.Copy(outBytes, 0, tmp, 0, pos);
+ outBytes = tmp;
+ }
+
+ return outBytes;
+ }
+
+ /**
+ * process an array of bytes, producing output if necessary.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset at which the input data starts.
+ * @param len the number of bytes to be copied out of the input array.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception InvalidOperationException if the cipher isn't initialised.
+ */
+ public override int ProcessBytes(
+ byte[] input,
+ int inOff,
+ int length,
+ byte[] output,
+ int outOff)
+ {
+ if (length < 1)
+ {
+ if (length < 0)
+ throw new ArgumentException("Can't have a negative input length!");
+
+ return 0;
+ }
+
+ int blockSize = GetBlockSize();
+ int outLength = GetUpdateOutputSize(length);
+
+ if (outLength > 0)
+ {
+ if ((outOff + outLength) > output.Length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.Length - bufOff;
+ if (length > gapLen)
+ {
+ Array.Copy(input, inOff, buf, bufOff, gapLen);
+ resultLen += cipher.ProcessBlock(buf, 0, output, outOff);
+ bufOff = 0;
+ length -= gapLen;
+ inOff += gapLen;
+ while (length > buf.Length)
+ {
+ resultLen += cipher.ProcessBlock(input, inOff, output, outOff + resultLen);
+ length -= blockSize;
+ inOff += blockSize;
+ }
+ }
+ Array.Copy(input, inOff, buf, bufOff, length);
+ bufOff += length;
+ if (bufOff == buf.Length)
+ {
+ resultLen += cipher.ProcessBlock(buf, 0, output, outOff + resultLen);
+ bufOff = 0;
+ }
+ return resultLen;
+ }
+
+ public override byte[] DoFinal()
+ {
+ byte[] outBytes = EmptyBuffer;
+
+ int length = GetOutputSize(0);
+ if (length > 0)
+ {
+ outBytes = new byte[length];
+
+ int pos = DoFinal(outBytes, 0);
+ if (pos < outBytes.Length)
+ {
+ byte[] tmp = new byte[pos];
+ Array.Copy(outBytes, 0, tmp, 0, pos);
+ outBytes = tmp;
+ }
+ }
+ else
+ {
+ Reset();
+ }
+
+ return outBytes;
+ }
+
+ public override byte[] DoFinal(
+ byte[] input,
+ int inOff,
+ int inLen)
+ {
+ if (input == null)
+ throw new ArgumentNullException("input");
+
+ int length = GetOutputSize(inLen);
+
+ byte[] outBytes = EmptyBuffer;
+
+ if (length > 0)
+ {
+ outBytes = new byte[length];
+
+ int pos = (inLen > 0)
+ ? ProcessBytes(input, inOff, inLen, outBytes, 0)
+ : 0;
+
+ pos += DoFinal(outBytes, pos);
+
+ if (pos < outBytes.Length)
+ {
+ byte[] tmp = new byte[pos];
+ Array.Copy(outBytes, 0, tmp, 0, pos);
+ outBytes = tmp;
+ }
+ }
+ else
+ {
+ Reset();
+ }
+
+ return outBytes;
+ }
+
+ /**
+ * Process the last block in the buffer.
+ *
+ * @param out the array the block currently being held is copied into.
+ * @param outOff the offset at which the copying starts.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there is insufficient space in out for
+ * the output, or the input is not block size aligned and should be.
+ * @exception InvalidOperationException if the underlying cipher is not
+ * initialised.
+ * @exception InvalidCipherTextException if padding is expected and not found.
+ * @exception DataLengthException if the input is not block size
+ * aligned.
+ */
+ public override int DoFinal(
+ byte[] output,
+ int outOff)
+ {
+ if (bufOff != 0)
+ {
+ if (!cipher.IsPartialBlockOkay)
+ {
+ throw new DataLengthException("data not block size aligned");
+ }
+
+ if (outOff + bufOff > output.Length)
+ {
+ throw new DataLengthException("output buffer too short for DoFinal()");
+ }
+
+ // NB: Can't copy directly, or we may write too much output
+ cipher.ProcessBlock(buf, 0, buf, 0);
+ Array.Copy(buf, 0, output, outOff, bufOff);
+ }
+
+ int resultLen = bufOff;
+
+ Reset();
+
+ return resultLen;
+ }
+
+ /**
+ * Reset the buffer and cipher. After resetting the object is in the same
+ * state as it was after the last init (if there was one).
+ */
+ public override void Reset()
+ {
+ Array.Clear(buf, 0, buf.Length);
+ bufOff = 0;
+
+ cipher.Reset();
+ }
+ }
+}
diff --git a/src/core/srcbc/crypto/encodings/Pkcs1Encoding.cs b/src/core/srcbc/crypto/encodings/Pkcs1Encoding.cs
index b813728..ec190f7 100644
--- a/src/core/srcbc/crypto/encodings/Pkcs1Encoding.cs
+++ b/src/core/srcbc/crypto/encodings/Pkcs1Encoding.cs
@@ -1,229 +1,232 @@
-using System;
-
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Utilities;
-
-namespace Org.BouncyCastle.Crypto.Encodings
-{
- /**
- * this does your basic Pkcs 1 v1.5 padding - whether or not you should be using this
- * depends on your application - see Pkcs1 Version 2 for details.
- */
- public class Pkcs1Encoding
- : IAsymmetricBlockCipher
- {
- /**
- * some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
- * work with one of these set the system property Org.BouncyCastle.Pkcs1.Strict to false.
- */
- public const string StrictLengthEnabledProperty = "Org.BouncyCastle.Pkcs1.Strict";
-
- private const int HeaderLength = 10;
-
- /**
- * The same effect can be achieved by setting the static property directly
- *
- * The static property is checked during construction of the encoding object, it is set to
- * true by default.
- *
- */
- public static bool StrictLengthEnabled
- {
- get { return strictLengthEnabled[0]; }
- set { strictLengthEnabled[0] = value; }
- }
-
- private static readonly bool[] strictLengthEnabled;
-
- static Pkcs1Encoding()
- {
- string strictProperty = Platform.GetEnvironmentVariable(StrictLengthEnabledProperty);
-
- strictLengthEnabled = new bool[]{ strictProperty == null || strictProperty.Equals("true")};
- }
-
-
- private SecureRandom random;
- private IAsymmetricBlockCipher engine;
- private bool forEncryption;
- private bool forPrivateKey;
- private bool useStrictLength;
-
- /**
- * Basic constructor.
- * @param cipher
- */
- public Pkcs1Encoding(
- IAsymmetricBlockCipher cipher)
- {
- this.engine = cipher;
- this.useStrictLength = StrictLengthEnabled;
- }
-
- public IAsymmetricBlockCipher GetUnderlyingCipher()
- {
- return engine;
- }
-
- public string AlgorithmName
- {
- get { return engine.AlgorithmName + "/PKCS1Padding"; }
- }
-
- public void Init(
- bool forEncryption,
- ICipherParameters parameters)
- {
- AsymmetricKeyParameter kParam;
- if (parameters is ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)parameters;
-
- this.random = rParam.Random;
- kParam = (AsymmetricKeyParameter)rParam.Parameters;
- }
- else
- {
- this.random = new SecureRandom();
- kParam = (AsymmetricKeyParameter)parameters;
- }
-
- engine.Init(forEncryption, parameters);
-
- this.forPrivateKey = kParam.IsPrivate;
- this.forEncryption = forEncryption;
- }
-
- public int GetInputBlockSize()
- {
- int baseBlockSize = engine.GetInputBlockSize();
-
- return forEncryption
- ? baseBlockSize - HeaderLength
- : baseBlockSize;
- }
-
- public int GetOutputBlockSize()
- {
- int baseBlockSize = engine.GetOutputBlockSize();
-
- return forEncryption
- ? baseBlockSize
- : baseBlockSize - HeaderLength;
- }
-
- public byte[] ProcessBlock(
- byte[] input,
- int inOff,
- int length)
- {
- return forEncryption
- ? EncodeBlock(input, inOff, length)
- : DecodeBlock(input, inOff, length);
- }
-
- private byte[] EncodeBlock(
- byte[] input,
- int inOff,
- int inLen)
- {
- byte[] block = new byte[engine.GetInputBlockSize()];
-
- if (forPrivateKey)
- {
- block[0] = 0x01; // type code 1
-
- for (int i = 1; i != block.Length - inLen - 1; i++)
- {
- block[i] = (byte)0xFF;
- }
- }
- else
- {
- random.NextBytes(block); // random fill
-
- block[0] = 0x02; // type code 2
-
- //
- // a zero byte marks the end of the padding, so all
- // the pad bytes must be non-zero.
- //
- for (int i = 1; i != block.Length - inLen - 1; i++)
- {
- while (block[i] == 0)
- {
- block[i] = (byte)random.NextInt();
- }
- }
- }
-
- block[block.Length - inLen - 1] = 0x00; // mark the end of the padding
- Array.Copy(input, inOff, block, block.Length - inLen, inLen);
-
- return engine.ProcessBlock(block, 0, block.Length);
- }
-
- /**
- * @exception InvalidCipherTextException if the decrypted block is not in Pkcs1 format.
- */
- private byte[] DecodeBlock(
- byte[] input,
- int inOff,
- int inLen)
- {
- byte[] block = engine.ProcessBlock(input, inOff, inLen);
-
- if (block.Length < GetOutputBlockSize())
- {
- throw new InvalidCipherTextException("block truncated");
- }
-
- byte type = block[0];
-
- if (type != 1 && type != 2)
- {
- throw new InvalidCipherTextException("unknown block type");
- }
-
- if (useStrictLength && block.Length != engine.GetOutputBlockSize())
- {
- throw new InvalidCipherTextException("block incorrect size");
- }
-
- //
- // find and extract the message block.
- //
- int start;
- for (start = 1; start != block.Length; start++)
- {
- byte pad = block[start];
-
- if (pad == 0)
- {
- break;
- }
-
- if (type == 1 && pad != (byte)0xff)
- {
- throw new InvalidCipherTextException("block padding incorrect");
- }
- }
-
- start++; // data should start at the next byte
-
- if (start >= block.Length || start < HeaderLength)
- {
- throw new InvalidCipherTextException("no data in block");
- }
-
- byte[] result = new byte[block.Length - start];
-
- Array.Copy(block, start, result, 0, result.Length);
-
- return result;
- }
- }
-
-}
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Encodings
+{
+ /**
+ * this does your basic Pkcs 1 v1.5 padding - whether or not you should be using this
+ * depends on your application - see Pkcs1 Version 2 for details.
+ */
+ public class Pkcs1Encoding
+ : IAsymmetricBlockCipher
+ {
+ /**
+ * some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
+ * work with one of these set the system property Org.BouncyCastle.Pkcs1.Strict to false.
+ */
+ public const string StrictLengthEnabledProperty = "Org.BouncyCastle.Pkcs1.Strict";
+
+ private const int HeaderLength = 10;
+
+ /**
+ * The same effect can be achieved by setting the static property directly
+ *
+ * The static property is checked during construction of the encoding object, it is set to
+ * true by default.
+ *
+ */
+ public static bool StrictLengthEnabled
+ {
+ get { return strictLengthEnabled[0]; }
+ set { strictLengthEnabled[0] = value; }
+ }
+
+ private static readonly bool[] strictLengthEnabled;
+
+ static Pkcs1Encoding()
+ {
+ string strictProperty = Platform.GetEnvironmentVariable(StrictLengthEnabledProperty);
+
+ strictLengthEnabled = new bool[]{ strictProperty == null || strictProperty.Equals("true")};
+ }
+
+
+ private SecureRandom random;
+ private IAsymmetricBlockCipher engine;
+ private bool forEncryption;
+ private bool forPrivateKey;
+ private bool useStrictLength;
+
+ /**
+ * Basic constructor.
+ * @param cipher
+ */
+ public Pkcs1Encoding(
+ IAsymmetricBlockCipher cipher)
+ {
+ this.engine = cipher;
+ this.useStrictLength = StrictLengthEnabled;
+ }
+
+ public IAsymmetricBlockCipher GetUnderlyingCipher()
+ {
+ return engine;
+ }
+
+ public string AlgorithmName
+ {
+ get { return engine.AlgorithmName + "/PKCS1Padding"; }
+ }
+
+ public void Init(
+ bool forEncryption,
+ ICipherParameters parameters)
+ {
+ AsymmetricKeyParameter kParam;
+ if (parameters is ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)parameters;
+
+ this.random = rParam.Random;
+ kParam = (AsymmetricKeyParameter)rParam.Parameters;
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ kParam = (AsymmetricKeyParameter)parameters;
+ }
+
+ engine.Init(forEncryption, parameters);
+
+ this.forPrivateKey = kParam.IsPrivate;
+ this.forEncryption = forEncryption;
+ }
+
+ public int GetInputBlockSize()
+ {
+ int baseBlockSize = engine.GetInputBlockSize();
+
+ return forEncryption
+ ? baseBlockSize - HeaderLength
+ : baseBlockSize;
+ }
+
+ public int GetOutputBlockSize()
+ {
+ int baseBlockSize = engine.GetOutputBlockSize();
+
+ return forEncryption
+ ? baseBlockSize
+ : baseBlockSize - HeaderLength;
+ }
+
+ public byte[] ProcessBlock(
+ byte[] input,
+ int inOff,
+ int length)
+ {
+ return forEncryption
+ ? EncodeBlock(input, inOff, length)
+ : DecodeBlock(input, inOff, length);
+ }
+
+ private byte[] EncodeBlock(
+ byte[] input,
+ int inOff,
+ int inLen)
+ {
+ if (inLen > GetInputBlockSize())
+ throw new ArgumentException("input data too large", "inLen");
+
+ byte[] block = new byte[engine.GetInputBlockSize()];
+
+ if (forPrivateKey)
+ {
+ block[0] = 0x01; // type code 1
+
+ for (int i = 1; i != block.Length - inLen - 1; i++)
+ {
+ block[i] = (byte)0xFF;
+ }
+ }
+ else
+ {
+ random.NextBytes(block); // random fill
+
+ block[0] = 0x02; // type code 2
+
+ //
+ // a zero byte marks the end of the padding, so all
+ // the pad bytes must be non-zero.
+ //
+ for (int i = 1; i != block.Length - inLen - 1; i++)
+ {
+ while (block[i] == 0)
+ {
+ block[i] = (byte)random.NextInt();
+ }
+ }
+ }
+
+ block[block.Length - inLen - 1] = 0x00; // mark the end of the padding
+ Array.Copy(input, inOff, block, block.Length - inLen, inLen);
+
+ return engine.ProcessBlock(block, 0, block.Length);
+ }
+
+ /**
+ * @exception InvalidCipherTextException if the decrypted block is not in Pkcs1 format.
+ */
+ private byte[] DecodeBlock(
+ byte[] input,
+ int inOff,
+ int inLen)
+ {
+ byte[] block = engine.ProcessBlock(input, inOff, inLen);
+
+ if (block.Length < GetOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block truncated");
+ }
+
+ byte type = block[0];
+
+ if (type != 1 && type != 2)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
+
+ if (useStrictLength && block.Length != engine.GetOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block incorrect size");
+ }
+
+ //
+ // find and extract the message block.
+ //
+ int start;
+ for (start = 1; start != block.Length; start++)
+ {
+ byte pad = block[start];
+
+ if (pad == 0)
+ {
+ break;
+ }
+
+ if (type == 1 && pad != (byte)0xff)
+ {
+ throw new InvalidCipherTextException("block padding incorrect");
+ }
+ }
+
+ start++; // data should start at the next byte
+
+ if (start >= block.Length || start < HeaderLength)
+ {
+ throw new InvalidCipherTextException("no data in block");
+ }
+
+ byte[] result = new byte[block.Length - start];
+
+ Array.Copy(block, start, result, 0, result.Length);
+
+ return result;
+ }
+ }
+
+}
diff --git a/src/core/srcbc/crypto/engines/CamelliaLightEngine.cs b/src/core/srcbc/crypto/engines/CamelliaLightEngine.cs
new file mode 100644
index 0000000..a301eb5
--- /dev/null
+++ b/src/core/srcbc/crypto/engines/CamelliaLightEngine.cs
@@ -0,0 +1,581 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+ /**
+ * Camellia - based on RFC 3713, smaller implementation, about half the size of CamelliaEngine.
+ */
+ public class CamelliaLightEngine
+ : IBlockCipher
+ {
+ private const int BLOCK_SIZE = 16;
+// private const int MASK8 = 0xff;
+ private bool initialised;
+ private bool _keyis128;
+
+ private uint[] subkey = new uint[24 * 4];
+ private uint[] kw = new uint[4 * 2]; // for whitening
+ private uint[] ke = new uint[6 * 2]; // for FL and FL^(-1)
+ private uint[] state = new uint[4]; // for encryption and decryption
+
+ private static readonly uint[] SIGMA = {
+ 0xa09e667f, 0x3bcc908b,
+ 0xb67ae858, 0x4caa73b2,
+ 0xc6ef372f, 0xe94f82be,
+ 0x54ff53a5, 0xf1d36f1c,
+ 0x10e527fa, 0xde682d1d,
+ 0xb05688c2, 0xb3e6c1fd
+ };
+
+ /*
+ *
+ * S-box data
+ *
+ */
+ private static readonly byte[] SBOX1 = {
+ (byte)112, (byte)130, (byte)44, (byte)236,
+ (byte)179, (byte)39, (byte)192, (byte)229,
+ (byte)228, (byte)133, (byte)87, (byte)53,
+ (byte)234, (byte)12, (byte)174, (byte)65,
+ (byte)35, (byte)239, (byte)107, (byte)147,
+ (byte)69, (byte)25, (byte)165, (byte)33,
+ (byte)237, (byte)14, (byte)79, (byte)78,
+ (byte)29, (byte)101, (byte)146, (byte)189,
+ (byte)134, (byte)184, (byte)175, (byte)143,
+ (byte)124, (byte)235, (byte)31, (byte)206,
+ (byte)62, (byte)48, (byte)220, (byte)95,
+ (byte)94, (byte)197, (byte)11, (byte)26,
+ (byte)166, (byte)225, (byte)57, (byte)202,
+ (byte)213, (byte)71, (byte)93, (byte)61,
+ (byte)217, (byte)1, (byte)90, (byte)214,
+ (byte)81, (byte)86, (byte)108, (byte)77,
+ (byte)139, (byte)13, (byte)154, (byte)102,
+ (byte)251, (byte)204, (byte)176, (byte)45,
+ (byte)116, (byte)18, (byte)43, (byte)32,
+ (byte)240, (byte)177, (byte)132, (byte)153,
+ (byte)223, (byte)76, (byte)203, (byte)194,
+ (byte)52, (byte)126, (byte)118, (byte)5,
+ (byte)109, (byte)183, (byte)169, (byte)49,
+ (byte)209, (byte)23, (byte)4, (byte)215,
+ (byte)20, (byte)88, (byte)58, (byte)97,
+ (byte)222, (byte)27, (byte)17, (byte)28,
+ (byte)50, (byte)15, (byte)156, (byte)22,
+ (byte)83, (byte)24, (byte)242, (byte)34,
+ (byte)254, (byte)68, (byte)207, (byte)178,
+ (byte)195, (byte)181, (byte)122, (byte)145,
+ (byte)36, (byte)8, (byte)232, (byte)168,
+ (byte)96, (byte)252, (byte)105, (byte)80,
+ (byte)170, (byte)208, (byte)160, (byte)125,
+ (byte)161, (byte)137, (byte)98, (byte)151,
+ (byte)84, (byte)91, (byte)30, (byte)149,
+ (byte)224, (byte)255, (byte)100, (byte)210,
+ (byte)16, (byte)196, (byte)0, (byte)72,
+ (byte)163, (byte)247, (byte)117, (byte)219,
+ (byte)138, (byte)3, (byte)230, (byte)218,
+ (byte)9, (byte)63, (byte)221, (byte)148,
+ (byte)135, (byte)92, (byte)131, (byte)2,
+ (byte)205, (byte)74, (byte)144, (byte)51,
+ (byte)115, (byte)103, (byte)246, (byte)243,
+ (byte)157, (byte)127, (byte)191, (byte)226,
+ (byte)82, (byte)155, (byte)216, (byte)38,
+ (byte)200, (byte)55, (byte)198, (byte)59,
+ (byte)129, (byte)150, (byte)111, (byte)75,
+ (byte)19, (byte)190, (byte)99, (byte)46,
+ (byte)233, (byte)121, (byte)167, (byte)140,
+ (byte)159, (byte)110, (byte)188, (byte)142,
+ (byte)41, (byte)245, (byte)249, (byte)182,
+ (byte)47, (byte)253, (byte)180, (byte)89,
+ (byte)120, (byte)152, (byte)6, (byte)106,
+ (byte)231, (byte)70, (byte)113, (byte)186,
+ (byte)212, (byte)37, (byte)171, (byte)66,
+ (byte)136, (byte)162, (byte)141, (byte)250,
+ (byte)114, (byte)7, (byte)185, (byte)85,
+ (byte)248, (byte)238, (byte)172, (byte)10,
+ (byte)54, (byte)73, (byte)42, (byte)104,
+ (byte)60, (byte)56, (byte)241, (byte)164,
+ (byte)64, (byte)40, (byte)211, (byte)123,
+ (byte)187, (byte)201, (byte)67, (byte)193,
+ (byte)21, (byte)227, (byte)173, (byte)244,
+ (byte)119, (byte)199, (byte)128, (byte)158
+ };
+
+ private static uint rightRotate(uint x, int s)
+ {
+ return ((x >> s) + (x << (32 - s)));
+ }
+
+ private static uint leftRotate(uint x, int s)
+ {
+ return (x << s) + (x >> (32 - s));
+ }
+
+ private static void roldq(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
+ {
+ ko[0 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >> (32 - rot));
+ ko[1 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >> (32 - rot));
+ ko[2 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >> (32 - rot));
+ ko[3 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >> (32 - rot));
+ ki[0 + ioff] = ko[0 + ooff];
+ ki[1 + ioff] = ko[1 + ooff];
+ ki[2 + ioff] = ko[2 + ooff];
+ ki[3 + ioff] = ko[3 + ooff];
+ }
+
+ private static void decroldq(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
+ {
+ ko[2 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >> (32 - rot));
+ ko[3 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >> (32 - rot));
+ ko[0 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >> (32 - rot));
+ ko[1 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >> (32 - rot));
+ ki[0 + ioff] = ko[2 + ooff];
+ ki[1 + ioff] = ko[3 + ooff];
+ ki[2 + ioff] = ko[0 + ooff];
+ ki[3 + ioff] = ko[1 + ooff];
+ }
+
+ private static void roldqo32(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
+ {
+ ko[0 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >> (64 - rot));
+ ko[1 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >> (64 - rot));
+ ko[2 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >> (64 - rot));
+ ko[3 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >> (64 - rot));
+ ki[0 + ioff] = ko[0 + ooff];
+ ki[1 + ioff] = ko[1 + ooff];
+ ki[2 + ioff] = ko[2 + ooff];
+ ki[3 + ioff] = ko[3 + ooff];
+ }
+
+ private static void decroldqo32(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
+ {
+ ko[2 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >> (64 - rot));
+ ko[3 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >> (64 - rot));
+ ko[0 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >> (64 - rot));
+ ko[1 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >> (64 - rot));
+ ki[0 + ioff] = ko[2 + ooff];
+ ki[1 + ioff] = ko[3 + ooff];
+ ki[2 + ioff] = ko[0 + ooff];
+ ki[3 + ioff] = ko[1 + ooff];
+ }
+
+ private static uint bytes2uint(byte[] src, int offset)
+ {
+ uint word = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ word = (word << 8) + (uint)src[i + offset];
+ }
+ return word;
+ }
+
+ private static void uint2bytes(uint word, byte[] dst, int offset)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ dst[(3 - i) + offset] = (byte)word;
+ word >>= 8;
+ }
+ }
+
+ private byte lRot8(byte v, int rot)
+ {
+ return (byte)(((uint)v << rot) | ((uint)v >> (8 - rot)));
+ }
+
+ private uint sbox2(int x)
+ {
+ return (uint)lRot8(SBOX1[x], 1);
+ }
+
+ private uint sbox3(int x)
+ {
+ return (uint)lRot8(SBOX1[x], 7);
+ }
+
+ private uint sbox4(int x)
+ {
+ return (uint)SBOX1[lRot8((byte)x, 1)];
+ }
+
+ private void camelliaF2(uint[] s, uint[] skey, int keyoff)
+ {
+ uint t1, t2, u, v;
+
+ t1 = s[0] ^ skey[0 + keyoff];
+ u = sbox4((byte)t1);
+ u |= (sbox3((byte)(t1 >> 8)) << 8);
+ u |= (sbox2((byte)(t1 >> 16)) << 16);
+ u |= ((uint)(SBOX1[(byte)(t1 >> 24)]) << 24);
+
+ t2 = s[1] ^ skey[1 + keyoff];
+ v = (uint)SBOX1[(byte)t2];
+ v |= (sbox4((byte)(t2 >> 8)) << 8);
+ v |= (sbox3((byte)(t2 >> 16)) << 16);
+ v |= (sbox2((byte)(t2 >> 24)) << 24);
+
+ v = leftRotate(v, 8);
+ u ^= v;
+ v = leftRotate(v, 8) ^ u;
+ u = rightRotate(u, 8) ^ v;
+ s[2] ^= leftRotate(v, 16) ^ u;
+ s[3] ^= leftRotate(u, 8);
+
+ t1 = s[2] ^ skey[2 + keyoff];
+ u = sbox4((byte)t1);
+ u |= sbox3((byte)(t1 >> 8)) << 8;
+ u |= sbox2((byte)(t1 >> 16)) << 16;
+ u |= ((uint)SBOX1[(byte)(t1 >> 24)]) << 24;
+
+ t2 = s[3] ^ skey[3 + keyoff];
+ v = (uint)SBOX1[(byte)t2];
+ v |= sbox4((byte)(t2 >> 8)) << 8;
+ v |= sbox3((byte)(t2 >> 16)) << 16;
+ v |= sbox2((byte)(t2 >> 24)) << 24;
+
+ v = leftRotate(v, 8);
+ u ^= v;
+ v = leftRotate(v, 8) ^ u;
+ u = rightRotate(u, 8) ^ v;
+ s[0] ^= leftRotate(v, 16) ^ u;
+ s[1] ^= leftRotate(u, 8);
+ }
+
+ private void camelliaFLs(uint[] s, uint[] fkey, int keyoff)
+ {
+ s[1] ^= leftRotate(s[0] & fkey[0 + keyoff], 1);
+ s[0] ^= fkey[1 + keyoff] | s[1];
+
+ s[2] ^= fkey[3 + keyoff] | s[3];
+ s[3] ^= leftRotate(fkey[2 + keyoff] & s[2], 1);
+ }
+
+ private void setKey(bool forEncryption, byte[] key)
+ {
+ uint[] k = new uint[8];
+ uint[] ka = new uint[4];
+ uint[] kb = new uint[4];
+ uint[] t = new uint[4];
+
+ switch (key.Length)
+ {
+ case 16:
+ _keyis128 = true;
+ k[0] = bytes2uint(key, 0);
+ k[1] = bytes2uint(key, 4);
+ k[2] = bytes2uint(key, 8);
+ k[3] = bytes2uint(key, 12);
+ k[4] = k[5] = k[6] = k[7] = 0;
+ break;
+ case 24:
+ k[0] = bytes2uint(key, 0);
+ k[1] = bytes2uint(key, 4);
+ k[2] = bytes2uint(key, 8);
+ k[3] = bytes2uint(key, 12);
+ k[4] = bytes2uint(key, 16);
+ k[5] = bytes2uint(key, 20);
+ k[6] = ~k[4];
+ k[7] = ~k[5];
+ _keyis128 = false;
+ break;
+ case 32:
+ k[0] = bytes2uint(key, 0);
+ k[1] = bytes2uint(key, 4);
+ k[2] = bytes2uint(key, 8);
+ k[3] = bytes2uint(key, 12);
+ k[4] = bytes2uint(key, 16);
+ k[5] = bytes2uint(key, 20);
+ k[6] = bytes2uint(key, 24);
+ k[7] = bytes2uint(key, 28);
+ _keyis128 = false;
+ break;
+ default:
+ throw new ArgumentException("key sizes are only 16/24/32 bytes.");
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ ka[i] = k[i] ^ k[i + 4];
+ }
+ /* compute KA */
+ camelliaF2(ka, SIGMA, 0);
+ for (int i = 0; i < 4; i++)
+ {
+ ka[i] ^= k[i];
+ }
+ camelliaF2(ka, SIGMA, 4);
+
+ if (_keyis128)
+ {
+ if (forEncryption)
+ {
+ /* KL dependant keys */
+ kw[0] = k[0];
+ kw[1] = k[1];
+ kw[2] = k[2];
+ kw[3] = k[3];
+ roldq(15, k, 0, subkey, 4);
+ roldq(30, k, 0, subkey, 12);
+ roldq(15, k, 0, t, 0);
+ subkey[18] = t[2];
+ subkey[19] = t[3];
+ roldq(17, k, 0, ke, 4);
+ roldq(17, k, 0, subkey, 24);
+ roldq(17, k, 0, subkey, 32);
+ /* KA dependant keys */
+ subkey[0] = ka[0];
+ subkey[1] = ka[1];
+ subkey[2] = ka[2];
+ subkey[3] = ka[3];
+ roldq(15, ka, 0, subkey, 8);
+ roldq(15, ka, 0, ke, 0);
+ roldq(15, ka, 0, t, 0);
+ subkey[16] = t[0];
+ subkey[17] = t[1];
+ roldq(15, ka, 0, subkey, 20);
+ roldqo32(34, ka, 0, subkey, 28);
+ roldq(17, ka, 0, kw, 4);
+
+ }
+ else
+ { // decryption
+ /* KL dependant keys */
+ kw[4] = k[0];
+ kw[5] = k[1];
+ kw[6] = k[2];
+ kw[7] = k[3];
+ decroldq(15, k, 0, subkey, 28);
+ decroldq(30, k, 0, subkey, 20);
+ decroldq(15, k, 0, t, 0);
+ subkey[16] = t[0];
+ subkey[17] = t[1];
+ decroldq(17, k, 0, ke, 0);
+ decroldq(17, k, 0, subkey, 8);
+ decroldq(17, k, 0, subkey, 0);
+ /* KA dependant keys */
+ subkey[34] = ka[0];
+ subkey[35] = ka[1];
+ subkey[32] = ka[2];
+ subkey[33] = ka[3];
+ decroldq(15, ka, 0, subkey, 24);
+ decroldq(15, ka, 0, ke, 4);
+ decroldq(15, ka, 0, t, 0);
+ subkey[18] = t[2];
+ subkey[19] = t[3];
+ decroldq(15, ka, 0, subkey, 12);
+ decroldqo32(34, ka, 0, subkey, 4);
+ roldq(17, ka, 0, kw, 0);
+ }
+ }
+ else
+ { // 192bit or 256bit
+ /* compute KB */
+ for (int i = 0; i < 4; i++)
+ {
+ kb[i] = ka[i] ^ k[i + 4];
+ }
+ camelliaF2(kb, SIGMA, 8);
+
+ if (forEncryption)
+ {
+ /* KL dependant keys */
+ kw[0] = k[0];
+ kw[1] = k[1];
+ kw[2] = k[2];
+ kw[3] = k[3];
+ roldqo32(45, k, 0, subkey, 16);
+ roldq(15, k, 0, ke, 4);
+ roldq(17, k, 0, subkey, 32);
+ roldqo32(34, k, 0, subkey, 44);
+ /* KR dependant keys */
+ roldq(15, k, 4, subkey, 4);
+ roldq(15, k, 4, ke, 0);
+ roldq(30, k, 4, subkey, 24);
+ roldqo32(34, k, 4, subkey, 36);
+ /* KA dependant keys */
+ roldq(15, ka, 0, subkey, 8);
+ roldq(30, ka, 0, subkey, 20);
+ /* 32bit rotation */
+ ke[8] = ka[1];
+ ke[9] = ka[2];
+ ke[10] = ka[3];
+ ke[11] = ka[0];
+ roldqo32(49, ka, 0, subkey, 40);
+
+ /* KB dependant keys */
+ subkey[0] = kb[0];
+ subkey[1] = kb[1];
+ subkey[2] = kb[2];
+ subkey[3] = kb[3];
+ roldq(30, kb, 0, subkey, 12);
+ roldq(30, kb, 0, subkey, 28);
+ roldqo32(51, kb, 0, kw, 4);
+
+ }
+ else
+ { // decryption
+ /* KL dependant keys */
+ kw[4] = k[0];
+ kw[5] = k[1];
+ kw[6] = k[2];
+ kw[7] = k[3];
+ decroldqo32(45, k, 0, subkey, 28);
+ decroldq(15, k, 0, ke, 4);
+ decroldq(17, k, 0, subkey, 12);
+ decroldqo32(34, k, 0, subkey, 0);
+ /* KR dependant keys */
+ decroldq(15, k, 4, subkey, 40);
+ decroldq(15, k, 4, ke, 8);
+ decroldq(30, k, 4, subkey, 20);
+ decroldqo32(34, k, 4, subkey, 8);
+ /* KA dependant keys */
+ decroldq(15, ka, 0, subkey, 36);
+ decroldq(30, ka, 0, subkey, 24);
+ /* 32bit rotation */
+ ke[2] = ka[1];
+ ke[3] = ka[2];
+ ke[0] = ka[3];
+ ke[1] = ka[0];
+ decroldqo32(49, ka, 0, subkey, 4);
+
+ /* KB dependant keys */
+ subkey[46] = kb[0];
+ subkey[47] = kb[1];
+ subkey[44] = kb[2];
+ subkey[45] = kb[3];
+ decroldq(30, kb, 0, subkey, 32);
+ decroldq(30, kb, 0, subkey, 16);
+ roldqo32(51, kb, 0, kw, 0);
+ }
+ }
+ }
+
+ private int processBlock128(byte[] input, int inOff, byte[] output, int outOff)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ state[i] = bytes2uint(input, inOff + (i * 4));
+ state[i] ^= kw[i];
+ }
+
+ camelliaF2(state, subkey, 0);
+ camelliaF2(state, subkey, 4);
+ camelliaF2(state, subkey, 8);
+ camelliaFLs(state, ke, 0);
+ camelliaF2(state, subkey, 12);
+ camelliaF2(state, subkey, 16);
+ camelliaF2(state, subkey, 20);
+ camelliaFLs(state, ke, 4);
+ camelliaF2(state, subkey, 24);
+ camelliaF2(state, subkey, 28);
+ camelliaF2(state, subkey, 32);
+
+ state[2] ^= kw[4];
+ state[3] ^= kw[5];
+ state[0] ^= kw[6];
+ state[1] ^= kw[7];
+
+ uint2bytes(state[2], output, outOff);
+ uint2bytes(state[3], output, outOff + 4);
+ uint2bytes(state[0], output, outOff + 8);
+ uint2bytes(state[1], output, outOff + 12);
+
+ return BLOCK_SIZE;
+ }
+
+ private int processBlock192or256(byte[] input, int inOff, byte[] output, int outOff)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ state[i] = bytes2uint(input, inOff + (i * 4));
+ state[i] ^= kw[i];
+ }
+
+ camelliaF2(state, subkey, 0);
+ camelliaF2(state, subkey, 4);
+ camelliaF2(state, subkey, 8);
+ camelliaFLs(state, ke, 0);
+ camelliaF2(state, subkey, 12);
+ camelliaF2(state, subkey, 16);
+ camelliaF2(state, subkey, 20);
+ camelliaFLs(state, ke, 4);
+ camelliaF2(state, subkey, 24);
+ camelliaF2(state, subkey, 28);
+ camelliaF2(state, subkey, 32);
+ camelliaFLs(state, ke, 8);
+ camelliaF2(state, subkey, 36);
+ camelliaF2(state, subkey, 40);
+ camelliaF2(state, subkey, 44);
+
+ state[2] ^= kw[4];
+ state[3] ^= kw[5];
+ state[0] ^= kw[6];
+ state[1] ^= kw[7];
+
+ uint2bytes(state[2], output, outOff);
+ uint2bytes(state[3], output, outOff + 4);
+ uint2bytes(state[0], output, outOff + 8);
+ uint2bytes(state[1], output, outOff + 12);
+ return BLOCK_SIZE;
+ }
+
+ public CamelliaLightEngine()
+ {
+ initialised = false;
+ }
+
+ public string AlgorithmName
+ {
+ get { return "Camellia"; }
+ }
+
+ public bool IsPartialBlockOkay
+ {
+ get { return false; }
+ }
+
+ public int GetBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public void Init(
+ bool forEncryption,
+ ICipherParameters parameters)
+ {
+ if (!(parameters is KeyParameter))
+ throw new ArgumentException("only simple KeyParameter expected.");
+
+ setKey(forEncryption, ((KeyParameter)parameters).GetKey());
+
+ initialised = true;
+ }
+
+ public int ProcessBlock(
+ byte[] input,
+ int inOff,
+ byte[] output,
+ int outOff)
+ {
+ if (!initialised)
+ throw new InvalidOperationException("Camellia engine not initialised");
+ if ((inOff + BLOCK_SIZE) > input.Length)
+ throw new DataLengthException("input buffer too short");
+ if ((outOff + BLOCK_SIZE) > output.Length)
+ throw new DataLengthException("output buffer too short");
+
+ if (_keyis128)
+ {
+ return processBlock128(input, inOff, output, outOff);
+ }
+ else
+ {
+ return processBlock192or256(input, inOff, output, outOff);
+ }
+ }
+
+ public void Reset()
+ {
+ }
+ }
+}
diff --git a/src/core/srcbc/crypto/io/CipherStream.cs b/src/core/srcbc/crypto/io/CipherStream.cs
index e69703c..b692085 100644
--- a/src/core/srcbc/crypto/io/CipherStream.cs
+++ b/src/core/srcbc/crypto/io/CipherStream.cs
@@ -1,224 +1,234 @@
-using System;
-using System.Diagnostics;
-using System.IO;
-using Org.BouncyCastle.Crypto;
-namespace Org.BouncyCastle.Crypto.IO
-{
- public class CipherStream : Stream
- {
- internal Stream stream;
- internal IBufferedCipher inCipher, outCipher;
- private byte[] mInBuf;
- private int mInPos;
- private bool inStreamEnded;
-
- public CipherStream(
- Stream stream,
- IBufferedCipher readCipher,
- IBufferedCipher writeCipher)
- {
- this.stream = stream;
-
- if (readCipher != null)
- {
- this.inCipher = readCipher;
- mInBuf = null;
- }
-
- if (writeCipher != null)
- {
- this.outCipher = writeCipher;
- }
- }
-
- public IBufferedCipher ReadCipher
- {
- get { return inCipher; }
- }
-
- public IBufferedCipher WriteCipher
- {
- get { return outCipher; }
- }
-
- public override int ReadByte()
- {
- if (inCipher == null)
- {
- return stream.ReadByte();
- }
-
- if (mInBuf == null || mInPos >= mInBuf.Length)
- {
- if (!FillInBuf())
- {
- return -1;
- }
- }
-
- return mInBuf[mInPos++];
- }
-
- public override int Read(byte[] buffer, int offset, int count)
- {
- if (inCipher == null)
- {
- return stream.Read(buffer, offset, count);
- }
-
-// int pos = offset;
-// int end = offset + count;
-// try
-// {
-// while (pos < end)
-// {
-// if (mInPos >= mInBufEnd && !FillInBuf()) break;
-//
-// int len = System.Math.Min(end - pos, mInBufEnd - mInPos);
-// Array.Copy(mInBuf, mInPos, buffer, pos, len);
-// mInPos += len;
-// pos += len;
-// }
-// }
-// catch (IOException)
-// {
-// if (pos == offset) throw;
-// }
-// return pos - offset;
-
- // TODO Optimise
- int i = 0;
- while (i < count)
- {
- int c = ReadByte();
-
- if (c < 0) break;
-
- buffer[offset + i++] = (byte) c;
- }
-
- return i;
- }
- private bool FillInBuf()
- {
- if (inStreamEnded)
- {
- return false;
- }
-
- mInPos = 0;
-
- do
- {
- mInBuf = readAndProcessBlock();
- }
- while (!inStreamEnded && mInBuf == null);
-
- return mInBuf != null;
- }
- private byte[] readAndProcessBlock()
- {
- int blockSize = inCipher.GetBlockSize();
- int readSize = (blockSize == 0) ? 256 : blockSize;
-
- byte[] block = new byte[readSize];
- int numRead = 0;
- do
- {
- int count = stream.Read(block, numRead, block.Length - numRead);
- if (count < 1)
- {
- inStreamEnded = true;
- break;
- }
- numRead += count;
- }
- while (numRead < block.Length);
-
- Debug.Assert(inStreamEnded || numRead == block.Length);
-
- byte[] bytes = inStreamEnded
- ? inCipher.DoFinal(block, 0, numRead)
- : inCipher.ProcessBytes(block);
-
- if (bytes != null && bytes.Length == 0)
- {
- bytes = null;
- }
-
- return bytes;
- }
- public override void Write(byte[] buffer, int offset, int count)
- {
- Debug.Assert(buffer != null);
- Debug.Assert(0 <= offset && offset <= buffer.Length);
- Debug.Assert(count >= 0);
-
- int end = offset + count;
-
- Debug.Assert(0 <= end && end <= buffer.Length);
-
- if (outCipher == null)
- {
- stream.Write(buffer, offset, count);
- return;
- }
-
- byte[] data = outCipher.ProcessBytes(buffer, offset, count);
- if (data != null)
- {
- stream.Write(data, 0, data.Length);
- }
- }
- public override void WriteByte(
- byte value)
- {
- if (outCipher == null)
- {
- stream.WriteByte(value);
- return;
- }
-
- byte[] data = outCipher.ProcessByte(value);
- if (data != null)
- {
- stream.Write(data, 0, data.Length);
- }
- }
- public override bool CanRead
- {
- get { return stream.CanRead && (inCipher != null); }
- }
- public override bool CanWrite
- {
- get { return stream.CanWrite && (outCipher != null); }
- }
- public override bool CanSeek
- {
- get { return false; }
- }
- public sealed override long Length { get { throw new NotSupportedException(); } }
- public sealed override long Position
- {
- get { throw new NotSupportedException(); }
- set { throw new NotSupportedException(); }
- }
- public override void Close()
- {
- if (outCipher != null)
- {
- byte[] data = outCipher.DoFinal();
- stream.Write(data, 0, data.Length);
- stream.Flush();
- }
- stream.Close();
- }
- public override void Flush()
- {
- // Note: outCipher.DoFinal is only called during Close()
- stream.Flush();
- }
- public sealed override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
- public sealed override void SetLength(long value) { throw new NotSupportedException(); }
- }
-}
+using System;
+using System.Diagnostics;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crypto.IO
+{
+ public class CipherStream
+ : Stream
+ {
+ internal Stream stream;
+ internal IBufferedCipher inCipher, outCipher;
+ private byte[] mInBuf;
+ private int mInPos;
+ private bool inStreamEnded;
+
+ public CipherStream(
+ Stream stream,
+ IBufferedCipher readCipher,
+ IBufferedCipher writeCipher)
+ {
+ this.stream = stream;
+
+ if (readCipher != null)
+ {
+ this.inCipher = readCipher;
+ mInBuf = null;
+ }
+
+ if (writeCipher != null)
+ {
+ this.outCipher = writeCipher;
+ }
+ }
+
+ public IBufferedCipher ReadCipher
+ {
+ get { return inCipher; }
+ }
+
+ public IBufferedCipher WriteCipher
+ {
+ get { return outCipher; }
+ }
+
+ public override int ReadByte()
+ {
+ if (inCipher == null)
+ return stream.ReadByte();
+
+ if (mInBuf == null || mInPos >= mInBuf.Length)
+ {
+ if (!FillInBuf())
+ return -1;
+ }
+
+ return mInBuf[mInPos++];
+ }
+
+ public override int Read(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ if (inCipher == null)
+ return stream.Read(buffer, offset, count);
+
+ int num = 0;
+ while (num < count)
+ {
+ if (mInBuf == null || mInPos >= mInBuf.Length)
+ {
+ if (!FillInBuf())
+ break;
+ }
+
+ int numToCopy = System.Math.Min(count - num, mInBuf.Length - mInPos);
+ Array.Copy(mInBuf, mInPos, buffer, offset + num, numToCopy);
+ mInPos += numToCopy;
+ num += numToCopy;
+ }
+
+ return num;
+ }
+
+ private bool FillInBuf()
+ {
+ if (inStreamEnded)
+ return false;
+
+ mInPos = 0;
+
+ do
+ {
+ mInBuf = ReadAndProcessBlock();
+ }
+ while (!inStreamEnded && mInBuf == null);
+
+ return mInBuf != null;
+ }
+
+ private byte[] ReadAndProcessBlock()
+ {
+ int blockSize = inCipher.GetBlockSize();
+ int readSize = (blockSize == 0) ? 256 : blockSize;
+
+ byte[] block = new byte[readSize];
+ int numRead = 0;
+ do
+ {
+ int count = stream.Read(block, numRead, block.Length - numRead);
+ if (count < 1)
+ {
+ inStreamEnded = true;
+ break;
+ }
+ numRead += count;
+ }
+ while (numRead < block.Length);
+
+ Debug.Assert(inStreamEnded || numRead == block.Length);
+
+ byte[] bytes = inStreamEnded
+ ? inCipher.DoFinal(block, 0, numRead)
+ : inCipher.ProcessBytes(block);
+
+ if (bytes != null && bytes.Length == 0)
+ {
+ bytes = null;
+ }
+
+ return bytes;
+ }
+
+ public override void Write(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ Debug.Assert(buffer != null);
+ Debug.Assert(0 <= offset && offset <= buffer.Length);
+ Debug.Assert(count >= 0);
+
+ int end = offset + count;
+
+ Debug.Assert(0 <= end && end <= buffer.Length);
+
+ if (outCipher == null)
+ {
+ stream.Write(buffer, offset, count);
+ return;
+ }
+
+ byte[] data = outCipher.ProcessBytes(buffer, offset, count);
+ if (data != null)
+ {
+ stream.Write(data, 0, data.Length);
+ }
+ }
+
+ public override void WriteByte(
+ byte b)
+ {
+ if (outCipher == null)
+ {
+ stream.WriteByte(b);
+ return;
+ }
+
+ byte[] data = outCipher.ProcessByte(b);
+ if (data != null)
+ {
+ stream.Write(data, 0, data.Length);
+ }
+ }
+
+ public override bool CanRead
+ {
+ get { return stream.CanRead && (inCipher != null); }
+ }
+
+ public override bool CanWrite
+ {
+ get { return stream.CanWrite && (outCipher != null); }
+ }
+
+ public override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public sealed override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public sealed override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public override void Close()
+ {
+ if (outCipher != null)
+ {
+ byte[] data = outCipher.DoFinal();
+ stream.Write(data, 0, data.Length);
+ stream.Flush();
+ }
+ stream.Close();
+ }
+
+ public override void Flush()
+ {
+ // Note: outCipher.DoFinal is only called during Close()
+ stream.Flush();
+ }
+
+ public sealed override long Seek(
+ long offset,
+ SeekOrigin origin)
+ {
+ throw new NotSupportedException();
+ }
+
+ public sealed override void SetLength(
+ long length)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/src/core/srcbc/crypto/paddings/Pkcs7Padding.cs b/src/core/srcbc/crypto/paddings/Pkcs7Padding.cs
index c72a108..f3166fd 100644
--- a/src/core/srcbc/crypto/paddings/Pkcs7Padding.cs
+++ b/src/core/srcbc/crypto/paddings/Pkcs7Padding.cs
@@ -1,77 +1,79 @@
-using System;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Security;
-
-
-namespace Org.BouncyCastle.Crypto.Paddings
-{
- /**
- * A padder that adds Pkcs7/Pkcs5 padding to a block.
- */
- public class Pkcs7Padding: IBlockCipherPadding
- {
- /**
- * Initialise the padder.
- *
- * @param random - a SecureRandom if available.
- */
- public void Init(SecureRandom random)
- {
- // nothing to do.
- }
-
- /**
- * Return the name of the algorithm the cipher implements.
- *
- * @return the name of the algorithm the cipher implements.
- */
- public string PaddingName
- {
- get { return "PKCS7"; }
- }
-
- /**
- * add the pad bytes to the passed in block, returning the
- * number of bytes added.
- */
- public int AddPadding(
- byte[] input,
- int inOff)
- {
- byte code = (byte)(input.Length - inOff);
-
- while (inOff < input.Length)
- {
- input[inOff] = code;
- inOff++;
- }
-
- return code;
- }
-
- /**
- * return the number of pad bytes present in the block.
- */
- public int PadCount(
- byte[] input)
- {
- int count = (int) input[input.Length - 1];
-
- if (count < 1 || count > input.Length)
- {
- throw new InvalidCipherTextException("pad block corrupted");
- }
-
- for (int i = 1; i <= count; i++)
- {
- if (input[input.Length - i] != count)
- {
- throw new InvalidCipherTextException("pad block corrupted");
- }
- }
-
- return count;
- }
- }
-
-}
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Paddings
+{
+ /**
+ * A padder that adds Pkcs7/Pkcs5 padding to a block.
+ */
+ public class Pkcs7Padding
+ : IBlockCipherPadding
+ {
+ /**
+ * Initialise the padder.
+ *
+ * @param random - a SecureRandom if available.
+ */
+ public void Init(
+ SecureRandom random)
+ {
+ // nothing to do.
+ }
+
+ /**
+ * Return the name of the algorithm the cipher implements.
+ *
+ * @return the name of the algorithm the cipher implements.
+ */
+ public string PaddingName
+ {
+ get { return "PKCS7"; }
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int AddPadding(
+ byte[] input,
+ int inOff)
+ {
+ byte code = (byte)(input.Length - inOff);
+
+ while (inOff < input.Length)
+ {
+ input[inOff] = code;
+ inOff++;
+ }
+
+ return code;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int PadCount(
+ byte[] input)
+ {
+ int count = (int) input[input.Length - 1];
+
+ if (count < 1 || count > input.Length)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ for (int i = 1; i <= count; i++)
+ {
+ if (input[input.Length - i] != count)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+ }
+
+ return count;
+ }
+ }
+
+}
diff --git a/src/core/srcbc/crypto/prng/DigestRandomGenerator.cs b/src/core/srcbc/crypto/prng/DigestRandomGenerator.cs
index 5f0cc75..cbd2ef0 100644
--- a/src/core/srcbc/crypto/prng/DigestRandomGenerator.cs
+++ b/src/core/srcbc/crypto/prng/DigestRandomGenerator.cs
@@ -1,107 +1,129 @@
-using System;
-
-using Org.BouncyCastle.Crypto.Digests;
-
-namespace Org.BouncyCastle.Crypto.Prng
-{
- /**
- * Random generation based on the digest with counter. Calling addSeedMaterial will
- * always increase the entropy of the hash.
- *
- * Internal access to the digest is syncrhonized so a single one of these can be shared.
- *
- */
- public class DigestRandomGenerator
- : IRandomGenerator
- {
- private long counter;
- private IDigest digest;
- private byte[] state;
-
- public DigestRandomGenerator(
- IDigest digest)
- {
- this.digest = digest;
- this.state = new byte[digest.GetDigestSize()];
- this.counter = 1;
- }
-
- public void AddSeedMaterial(
- byte[] inSeed)
- {
- lock (this)
- {
- DigestUpdate(inSeed);
- }
- }
-
- public void AddSeedMaterial(
- long rSeed)
- {
- lock (this)
- {
- for (int i = 0; i != 8; i++)
- {
- DigestUpdate((byte)rSeed);
-// rSeed >>>= 8;
- rSeed >>= 8;
- }
- }
- }
-
- public void NextBytes(
- byte[] bytes)
- {
- NextBytes(bytes, 0, bytes.Length);
- }
-
- public void NextBytes(
- byte[] bytes,
- int start,
- int len)
- {
- lock (this)
- {
- int stateOff = 0;
-
- DigestDoFinal(state);
-
- int end = start + len;
- for (int i = start; i < end; ++i)
- {
- if (stateOff == state.Length)
- {
- DigestUpdate(counter++);
- DigestUpdate(state);
- DigestDoFinal(state);
- stateOff = 0;
- }
- bytes[i] = state[stateOff++];
- }
-
- DigestUpdate(counter++);
- DigestUpdate(state);
- }
- }
-
- private void DigestUpdate(long seed)
- {
- for (int i = 0; i != 8; i++)
- {
- digest.Update((byte)seed);
-// seed >>>= 8;
- seed >>= 8;
- }
- }
-
- private void DigestUpdate(byte[] inSeed)
- {
- digest.BlockUpdate(inSeed, 0, inSeed.Length);
- }
-
- private void DigestDoFinal(byte[] result)
- {
- digest.DoFinal(result, 0);
- }
- }
-}
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+
+namespace Org.BouncyCastle.Crypto.Prng
+{
+ /**
+ * Random generation based on the digest with counter. Calling AddSeedMaterial will
+ * always increase the entropy of the hash.
+ *
+ * Internal access to the digest is synchronized so a single one of these can be shared.
+ *
+ */
+ public class DigestRandomGenerator
+ : IRandomGenerator
+ {
+ private const long CYCLE_COUNT = 10;
+
+ private long stateCounter;
+ private long seedCounter;
+ private IDigest digest;
+ private byte[] state;
+ private byte[] seed;
+
+ public DigestRandomGenerator(
+ IDigest digest)
+ {
+ this.digest = digest;
+
+ this.seed = new byte[digest.GetDigestSize()];
+ this.seedCounter = 1;
+
+ this.state = new byte[digest.GetDigestSize()];
+ this.stateCounter = 1;
+ }
+
+ public void AddSeedMaterial(
+ byte[] inSeed)
+ {
+ lock (this)
+ {
+ DigestUpdate(inSeed);
+ DigestUpdate(seed);
+ DigestDoFinal(seed);
+ }
+ }
+
+ public void AddSeedMaterial(
+ long rSeed)
+ {
+ lock (this)
+ {
+ DigestAddCounter(rSeed);
+ DigestUpdate(seed);
+ DigestDoFinal(seed);
+ }
+ }
+
+ public void NextBytes(
+ byte[] bytes)
+ {
+ NextBytes(bytes, 0, bytes.Length);
+ }
+
+ public void NextBytes(
+ byte[] bytes,
+ int start,
+ int len)
+ {
+ lock (this)
+ {
+ int stateOff = 0;
+
+ GenerateState();
+
+ int end = start + len;
+ for (int i = start; i < end; ++i)
+ {
+ if (stateOff == state.Length)
+ {
+ GenerateState();
+ stateOff = 0;
+ }
+ bytes[i] = state[stateOff++];
+ }
+ }
+ }
+
+ private void CycleSeed()
+ {
+ DigestUpdate(seed);
+ DigestAddCounter(seedCounter++);
+ DigestDoFinal(seed);
+ }
+
+ private void GenerateState()
+ {
+ DigestAddCounter(stateCounter++);
+ DigestUpdate(state);
+ DigestUpdate(seed);
+ DigestDoFinal(state);
+
+ if ((stateCounter % CYCLE_COUNT) == 0)
+ {
+ CycleSeed();
+ }
+ }
+
+ private void DigestAddCounter(long seedVal)
+ {
+ ulong seed = (ulong)seedVal;
+ for (int i = 0; i != 8; i++)
+ {
+ digest.Update((byte)seed);
+ seed >>= 8;
+ }
+ }
+
+ private void DigestUpdate(byte[] inSeed)
+ {
+ digest.BlockUpdate(inSeed, 0, inSeed.Length);
+ }
+
+ private void DigestDoFinal(byte[] result)
+ {
+ digest.DoFinal(result, 0);
+ }
+ }
+}
diff --git a/src/core/srcbc/crypto/signers/ECDsaSigner.cs b/src/core/srcbc/crypto/signers/ECDsaSigner.cs
index 1d10143..6c1e3f7 100644
--- a/src/core/srcbc/crypto/signers/ECDsaSigner.cs
+++ b/src/core/srcbc/crypto/signers/ECDsaSigner.cs
@@ -1,150 +1,156 @@
-using System;
-using Org.BouncyCastle.Math;
-using Org.BouncyCastle.Math.EC;
-using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Crypto.Parameters;
-
-namespace Org.BouncyCastle.Crypto.Signers
-{
- /**
- * EC-DSA as described in X9.62
- */
- public class ECDsaSigner
- : IDsa
- {
- private ECKeyParameters key;
- private SecureRandom random;
-
- public string AlgorithmName
- {
- get { return "ECDSA"; }
- }
-
- public void Init(
- bool forSigning,
- ICipherParameters parameters)
- {
- if (forSigning)
- {
- if (parameters is ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom) parameters;
-
- this.random = rParam.Random;
- parameters = rParam.Parameters;
- }
- else
- {
- this.random = new SecureRandom();
- }
-
- if (!(parameters is ECPrivateKeyParameters))
- throw new InvalidKeyException("EC private key required for signing");
-
- this.key = (ECPrivateKeyParameters) parameters;
- }
- else
- {
- if (!(parameters is ECPublicKeyParameters))
- throw new InvalidKeyException("EC public key required for verification");
-
- this.key = (ECPublicKeyParameters) parameters;
- }
- }
-
- // 5.3 pg 28
- /**
- * Generate a signature for the given message using the key we were
- * initialised with. For conventional DSA the message should be a SHA-1
- * hash of the message of interest.
- *
- * @param message the message that will be verified later.
- */
- public BigInteger[] GenerateSignature(
- byte[] message)
- {
- BigInteger n = key.Parameters.N;
- BigInteger e = calculateE(n, message);
-
- BigInteger r = null;
- BigInteger s = null;
-
- // 5.3.2
- do // Generate s
- {
- BigInteger k = null;
-
- do // Generate r
- {
- do
- {
- k = new BigInteger(n.BitLength, random);
- }
- while (k.SignValue == 0);
-
- ECPoint p = key.Parameters.G.Multiply(k);
-
- // 5.3.3
- BigInteger x = p.X.ToBigInteger();
-
- r = x.Mod(n);
- }
- while (r.SignValue == 0);
-
- BigInteger d = ((ECPrivateKeyParameters)key).D;
-
- s = k.ModInverse(n).Multiply(e.Add(d.Multiply(r))).Mod(n);
- }
- while (s.SignValue == 0);
-
- return new BigInteger[]{ r, s };
- }
-
- // 5.4 pg 29
- /**
- * return true if the value r and s represent a DSA signature for
- * the passed in message (for standard DSA the message should be
- * a SHA-1 hash of the real message to be verified).
- */
- public bool VerifySignature(
- byte[] message,
- BigInteger r,
- BigInteger s)
- {
- BigInteger n = key.Parameters.N;
-
- // r and s should both in the range [1,n-1]
- if (r.SignValue < 1 || s.SignValue < 1
- || r.CompareTo(n) >= 0 || s.CompareTo(n) >= 0)
- {
- return false;
- }
-
- BigInteger e = calculateE(n, message);
- BigInteger c = s.ModInverse(n);
-
- BigInteger u1 = e.Multiply(c).Mod(n);
- BigInteger u2 = r.Multiply(c).Mod(n);
-
- ECPoint G = key.Parameters.G;
- ECPoint Q = ((ECPublicKeyParameters) key).Q;
-
- ECPoint point = ECAlgorithms.SumOfTwoMultiplies(G, u1, Q, u2);
-
- BigInteger v = point.X.ToBigInteger().Mod(n);
-
- return v.Equals(r);
- }
-
- private BigInteger calculateE(
- BigInteger n,
- byte[] message)
- {
- int length = System.Math.Min(message.Length, n.BitLength / 8);
-
- return new BigInteger(1, message, 0, length);
- }
- }
-}
+using System;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+ /**
+ * EC-DSA as described in X9.62
+ */
+ public class ECDsaSigner
+ : IDsa
+ {
+ private ECKeyParameters key;
+ private SecureRandom random;
+
+ public string AlgorithmName
+ {
+ get { return "ECDSA"; }
+ }
+
+ public void Init(
+ bool forSigning,
+ ICipherParameters parameters)
+ {
+ if (forSigning)
+ {
+ if (parameters is ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom) parameters;
+
+ this.random = rParam.Random;
+ parameters = rParam.Parameters;
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ }
+
+ if (!(parameters is ECPrivateKeyParameters))
+ throw new InvalidKeyException("EC private key required for signing");
+
+ this.key = (ECPrivateKeyParameters) parameters;
+ }
+ else
+ {
+ if (!(parameters is ECPublicKeyParameters))
+ throw new InvalidKeyException("EC public key required for verification");
+
+ this.key = (ECPublicKeyParameters) parameters;
+ }
+ }
+
+ // 5.3 pg 28
+ /**
+ * Generate a signature for the given message using the key we were
+ * initialised with. For conventional DSA the message should be a SHA-1
+ * hash of the message of interest.
+ *
+ * @param message the message that will be verified later.
+ */
+ public BigInteger[] GenerateSignature(
+ byte[] message)
+ {
+ BigInteger n = key.Parameters.N;
+ BigInteger e = calculateE(n, message);
+
+ BigInteger r = null;
+ BigInteger s = null;
+
+ // 5.3.2
+ do // Generate s
+ {
+ BigInteger k = null;
+
+ do // Generate r
+ {
+ do
+ {
+ k = new BigInteger(n.BitLength, random);
+ }
+ while (k.SignValue == 0);
+
+ ECPoint p = key.Parameters.G.Multiply(k);
+
+ // 5.3.3
+ BigInteger x = p.X.ToBigInteger();
+
+ r = x.Mod(n);
+ }
+ while (r.SignValue == 0);
+
+ BigInteger d = ((ECPrivateKeyParameters)key).D;
+
+ s = k.ModInverse(n).Multiply(e.Add(d.Multiply(r))).Mod(n);
+ }
+ while (s.SignValue == 0);
+
+ return new BigInteger[]{ r, s };
+ }
+
+ // 5.4 pg 29
+ /**
+ * return true if the value r and s represent a DSA signature for
+ * the passed in message (for standard DSA the message should be
+ * a SHA-1 hash of the real message to be verified).
+ */
+ public bool VerifySignature(
+ byte[] message,
+ BigInteger r,
+ BigInteger s)
+ {
+ BigInteger n = key.Parameters.N;
+
+ // r and s should both in the range [1,n-1]
+ if (r.SignValue < 1 || s.SignValue < 1
+ || r.CompareTo(n) >= 0 || s.CompareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ BigInteger e = calculateE(n, message);
+ BigInteger c = s.ModInverse(n);
+
+ BigInteger u1 = e.Multiply(c).Mod(n);
+ BigInteger u2 = r.Multiply(c).Mod(n);
+
+ ECPoint G = key.Parameters.G;
+ ECPoint Q = ((ECPublicKeyParameters) key).Q;
+
+ ECPoint point = ECAlgorithms.SumOfTwoMultiplies(G, u1, Q, u2);
+
+ BigInteger v = point.X.ToBigInteger().Mod(n);
+
+ return v.Equals(r);
+ }
+
+ private BigInteger calculateE(
+ BigInteger n,
+ byte[] message)
+ {
+ int messageBitLength = message.Length * 8;
+ BigInteger trunc = new BigInteger(1, message);
+
+ if (n.BitLength < messageBitLength)
+ {
+ trunc = trunc.ShiftRight(messageBitLength - n.BitLength);
+ }
+
+ return trunc;
+ }
+ }
+}
diff --git a/src/core/srcbc/crypto/tls/TlsBlockCipherCipherSuite.cs b/src/core/srcbc/crypto/tls/TlsBlockCipherCipherSuite.cs
index 004f6ac..edaf20f 100644
--- a/src/core/srcbc/crypto/tls/TlsBlockCipherCipherSuite.cs
+++ b/src/core/srcbc/crypto/tls/TlsBlockCipherCipherSuite.cs
@@ -1,196 +1,196 @@
-using System;
-using System.Text;
-
-using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Crypto.Parameters;
-
-namespace Org.BouncyCastle.Crypto.Tls
-{
- /// A generic TLS 1.0 block cipher suite. This can be used for AES or 3DES for example.
- public class TlsBlockCipherCipherSuite
- : TlsCipherSuite
- {
- private IBlockCipher encryptCipher;
-
- private IBlockCipher decryptCipher;
-
- private IDigest writeDigest;
-
- private IDigest readDigest;
-
- private int cipherKeySize;
-
- private short keyExchange;
-
- private TlsMac writeMac;
-
- private TlsMac readMac;
-
- internal TlsBlockCipherCipherSuite(
- IBlockCipher encrypt,
- IBlockCipher decrypt,
- IDigest writeDigest,
- IDigest readDigest,
- int cipherKeySize,
- short keyExchange)
- {
- this.encryptCipher = encrypt;
- this.decryptCipher = decrypt;
- this.writeDigest = writeDigest;
- this.readDigest = readDigest;
- this.cipherKeySize = cipherKeySize;
- this.keyExchange = keyExchange;
- }
-
- internal override void Init(byte[] ms, byte[] cr, byte[] sr)
- {
- int prfSize = (2 * cipherKeySize) + (2 * writeDigest.GetDigestSize())
- + (2 * encryptCipher.GetBlockSize());
- byte[] key_block = new byte[prfSize];
- byte[] random = new byte[cr.Length + sr.Length];
- Array.Copy(cr, 0, random, sr.Length, cr.Length);
- Array.Copy(sr, 0, random, 0, sr.Length);
- TlsUtilities.PRF(ms, TlsUtilities.ToByteArray("key expansion"), random, key_block);
-
- int offset = 0;
-
- // Init MACs
- writeMac = new TlsMac(writeDigest, key_block, offset, writeDigest
- .GetDigestSize());
- offset += writeDigest.GetDigestSize();
- readMac = new TlsMac(readDigest, key_block, offset, readDigest
- .GetDigestSize());
- offset += readDigest.GetDigestSize();
-
- // Init Ciphers
- this.initCipher(true, encryptCipher, key_block, cipherKeySize, offset,
- offset + (cipherKeySize * 2));
- offset += cipherKeySize;
- this.initCipher(false, decryptCipher, key_block, cipherKeySize, offset,
- offset + cipherKeySize + decryptCipher.GetBlockSize());
- }
-
- private void initCipher(bool forEncryption, IBlockCipher cipher,
- byte[] key_block, int key_size, int key_offset, int iv_offset)
- {
- KeyParameter key_parameter = new KeyParameter(key_block, key_offset,
- key_size);
- ParametersWithIV parameters_with_iv = new ParametersWithIV(
- key_parameter, key_block, iv_offset, cipher.GetBlockSize());
- cipher.Init(forEncryption, parameters_with_iv);
- }
-
- internal override byte[] EncodePlaintext(
- short type,
- byte[] plaintext,
- int offset,
- int len)
- {
- int blocksize = encryptCipher.GetBlockSize();
- int paddingsize = blocksize
- - ((len + writeMac.Size + 1) % blocksize);
- int totalsize = len + writeMac.Size + paddingsize + 1;
- byte[] outbuf = new byte[totalsize];
- Array.Copy(plaintext, offset, outbuf, 0, len);
- byte[] mac = writeMac.CalculateMac(type, plaintext, offset, len);
- Array.Copy(mac, 0, outbuf, len, mac.Length);
- int paddoffset = len + mac.Length;
- for (int i = 0; i <= paddingsize; i++)
- {
- outbuf[i + paddoffset] = (byte)paddingsize;
- }
- for (int i = 0; i < totalsize; i += blocksize)
- {
- encryptCipher.ProcessBlock(outbuf, i, outbuf, i);
- }
- return outbuf;
- }
-
- internal override byte[] DecodeCiphertext(
- short type,
- byte[] ciphertext,
- int offset,
- int len,
- TlsProtocolHandler handler)
- {
- int blocksize = decryptCipher.GetBlockSize();
- bool decrypterror = false;
-
- /*
- * Decrypt all the ciphertext using the blockcipher
- */
- for (int i = 0; i < len; i += blocksize)
- {
- decryptCipher.ProcessBlock(ciphertext, i + offset, ciphertext, i
- + offset);
- }
-
- /*
- * Check if padding is correct
- */
- int paddingsize = ciphertext[offset + len - 1];
- if (offset + len - 1 - paddingsize < 0)
- {
- /*
- * This would lead to an negativ array index, so this padding
- * must be incorrect!
- */
- decrypterror = true;
- paddingsize = 0;
- }
- else
- {
- /*
- * Now, check all the padding-bytes.
- */
- for (int i = 0; i <= paddingsize; i++)
- {
- if (ciphertext[offset + len - 1 - i] != paddingsize)
- {
- /* Wrong padding */
- decrypterror = true;
- }
- }
- }
-
- /*
- * We now don't care if padding verification has failed or not,
- * we will calculate the mac to give an attacker no kind of timing
- * profile he can use to find out if mac verification failed or
- * padding verification failed.
- */
- int plaintextlength = len - readMac.Size - paddingsize - 1;
- byte[] calculatedMac = readMac.CalculateMac(type, ciphertext, offset,
- plaintextlength);
-
- /*
- * Check all bytes in the mac.
- */
- for (int i = 0; i < calculatedMac.Length; i++)
- {
- if (ciphertext[offset + plaintextlength + i] != calculatedMac[i])
- {
- decrypterror = true;
- }
- }
-
- /*
- * Now, it is save to fail.
- */
- if (decrypterror)
- {
- handler.FailWithError(TlsProtocolHandler.AL_fatal,
- TlsProtocolHandler.AP_bad_record_mac);
- }
- byte[] plaintext = new byte[plaintextlength];
- Array.Copy(ciphertext, offset, plaintext, 0, plaintextlength);
- return plaintext;
-
- }
-
- internal override short KeyExchangeAlgorithm
- {
- get { return this.keyExchange; }
- }
- }
-}
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ /// A generic TLS 1.0 block cipher suite. This can be used for AES or 3DES for example.
+ public class TlsBlockCipherCipherSuite
+ : TlsCipherSuite
+ {
+ private IBlockCipher encryptCipher;
+
+ private IBlockCipher decryptCipher;
+
+ private IDigest writeDigest;
+
+ private IDigest readDigest;
+
+ private int cipherKeySize;
+
+ private short keyExchange;
+
+ private TlsMac writeMac;
+
+ private TlsMac readMac;
+
+ internal TlsBlockCipherCipherSuite(
+ IBlockCipher encrypt,
+ IBlockCipher decrypt,
+ IDigest writeDigest,
+ IDigest readDigest,
+ int cipherKeySize,
+ short keyExchange)
+ {
+ this.encryptCipher = encrypt;
+ this.decryptCipher = decrypt;
+ this.writeDigest = writeDigest;
+ this.readDigest = readDigest;
+ this.cipherKeySize = cipherKeySize;
+ this.keyExchange = keyExchange;
+ }
+
+ internal override void Init(byte[] ms, byte[] cr, byte[] sr)
+ {
+ int prfSize = (2 * cipherKeySize) + (2 * writeDigest.GetDigestSize())
+ + (2 * encryptCipher.GetBlockSize());
+ byte[] key_block = new byte[prfSize];
+ byte[] random = new byte[cr.Length + sr.Length];
+ Array.Copy(cr, 0, random, sr.Length, cr.Length);
+ Array.Copy(sr, 0, random, 0, sr.Length);
+ TlsUtilities.PRF(ms, TlsUtilities.ToByteArray("key expansion"), random, key_block);
+
+ int offset = 0;
+
+ // Init MACs
+ writeMac = new TlsMac(writeDigest, key_block, offset, writeDigest
+ .GetDigestSize());
+ offset += writeDigest.GetDigestSize();
+ readMac = new TlsMac(readDigest, key_block, offset, readDigest
+ .GetDigestSize());
+ offset += readDigest.GetDigestSize();
+
+ // Init Ciphers
+ this.initCipher(true, encryptCipher, key_block, cipherKeySize, offset,
+ offset + (cipherKeySize * 2));
+ offset += cipherKeySize;
+ this.initCipher(false, decryptCipher, key_block, cipherKeySize, offset,
+ offset + cipherKeySize + decryptCipher.GetBlockSize());
+ }
+
+ private void initCipher(bool forEncryption, IBlockCipher cipher,
+ byte[] key_block, int key_size, int key_offset, int iv_offset)
+ {
+ KeyParameter key_parameter = new KeyParameter(key_block, key_offset,
+ key_size);
+ ParametersWithIV parameters_with_iv = new ParametersWithIV(
+ key_parameter, key_block, iv_offset, cipher.GetBlockSize());
+ cipher.Init(forEncryption, parameters_with_iv);
+ }
+
+ internal override byte[] EncodePlaintext(
+ short type,
+ byte[] plaintext,
+ int offset,
+ int len)
+ {
+ int blocksize = encryptCipher.GetBlockSize();
+ int paddingsize = blocksize
+ - ((len + writeMac.Size + 1) % blocksize);
+ int totalsize = len + writeMac.Size + paddingsize + 1;
+ byte[] outbuf = new byte[totalsize];
+ Array.Copy(plaintext, offset, outbuf, 0, len);
+ byte[] mac = writeMac.CalculateMac(type, plaintext, offset, len);
+ Array.Copy(mac, 0, outbuf, len, mac.Length);
+ int paddoffset = len + mac.Length;
+ for (int i = 0; i <= paddingsize; i++)
+ {
+ outbuf[i + paddoffset] = (byte)paddingsize;
+ }
+ for (int i = 0; i < totalsize; i += blocksize)
+ {
+ encryptCipher.ProcessBlock(outbuf, i, outbuf, i);
+ }
+ return outbuf;
+ }
+
+ internal override byte[] DecodeCiphertext(
+ short type,
+ byte[] ciphertext,
+ int offset,
+ int len,
+ TlsProtocolHandler handler)
+ {
+ int blocksize = decryptCipher.GetBlockSize();
+ bool decrypterror = false;
+
+ /*
+ * Decrypt all the ciphertext using the blockcipher
+ */
+ for (int i = 0; i < len; i += blocksize)
+ {
+ decryptCipher.ProcessBlock(ciphertext, i + offset, ciphertext, i
+ + offset);
+ }
+
+ /*
+ * Check if padding is correct
+ */
+ int paddingsize = ciphertext[offset + len - 1];
+ if (offset + len - 1 - paddingsize < 0)
+ {
+ /*
+ * This would lead to a negative array index, so this padding
+ * must be incorrect!
+ */
+ decrypterror = true;
+ paddingsize = 0;
+ }
+ else
+ {
+ /*
+ * Now, check all the padding-bytes.
+ */
+ for (int i = 0; i <= paddingsize; i++)
+ {
+ if (ciphertext[offset + len - 1 - i] != paddingsize)
+ {
+ /* Wrong padding */
+ decrypterror = true;
+ }
+ }
+ }
+
+ /*
+ * We now don't care if padding verification has failed or not,
+ * we will calculate the mac to give an attacker no kind of timing
+ * profile he can use to find out if mac verification failed or
+ * padding verification failed.
+ */
+ int plaintextlength = len - readMac.Size - paddingsize - 1;
+ byte[] calculatedMac = readMac.CalculateMac(type, ciphertext, offset,
+ plaintextlength);
+
+ /*
+ * Check all bytes in the mac.
+ */
+ for (int i = 0; i < calculatedMac.Length; i++)
+ {
+ if (ciphertext[offset + plaintextlength + i] != calculatedMac[i])
+ {
+ decrypterror = true;
+ }
+ }
+
+ /*
+ * Now, it is safe to fail.
+ */
+ if (decrypterror)
+ {
+ handler.FailWithError(TlsProtocolHandler.AL_fatal,
+ TlsProtocolHandler.AP_bad_record_mac);
+ }
+ byte[] plaintext = new byte[plaintextlength];
+ Array.Copy(ciphertext, offset, plaintext, 0, plaintextlength);
+ return plaintext;
+
+ }
+
+ internal override short KeyExchangeAlgorithm
+ {
+ get { return this.keyExchange; }
+ }
+ }
+}
diff --git a/src/core/srcbc/crypto/tls/TlsProtocolHandler.cs b/src/core/srcbc/crypto/tls/TlsProtocolHandler.cs
index eb860cd..d714752 100644
--- a/src/core/srcbc/crypto/tls/TlsProtocolHandler.cs
+++ b/src/core/srcbc/crypto/tls/TlsProtocolHandler.cs
@@ -1,1152 +1,1152 @@
-using System;
-using System.IO;
-using System.Text;
-
-using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Crypto.Encodings;
-using Org.BouncyCastle.Crypto.Engines;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Crypto.Prng;
-using Org.BouncyCastle.Math;
-using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Utilities.Date;
-
-namespace Org.BouncyCastle.Crypto.Tls
-{
- /// An implementation of all high level protocols in TLS 1.0.
- public class TlsProtocolHandler
- {
- private const short RL_CHANGE_CIPHER_SPEC = 20;
- private const short RL_ALERT = 21;
- private const short RL_HANDSHAKE = 22;
- private const short RL_APPLICATION_DATA = 23;
-
- /*
- hello_request(0), client_hello(1), server_hello(2),
- certificate(11), server_key_exchange (12),
- certificate_request(13), server_hello_done(14),
- certificate_verify(15), client_key_exchange(16),
- finished(20), (255)
- */
-
- private const short HP_HELLO_REQUEST = 0;
- private const short HP_CLIENT_HELLO = 1;
- private const short HP_SERVER_HELLO = 2;
- private const short HP_CERTIFICATE = 11;
- private const short HP_SERVER_KEY_EXCHANGE = 12;
- private const short HP_CERTIFICATE_REQUEST = 13;
- private const short HP_SERVER_HELLO_DONE = 14;
- private const short HP_CERTIFICATE_VERIFY = 15;
- private const short HP_CLIENT_KEY_EXCHANGE = 16;
- private const short HP_FINISHED = 20;
-
- /*
- * Our Connection states
- */
-
- private const short CS_CLIENT_HELLO_SEND = 1;
- private const short CS_SERVER_HELLO_RECEIVED = 2;
- private const short CS_SERVER_CERTIFICATE_RECEIVED = 3;
- private const short CS_SERVER_KEY_EXCHANGE_RECEIVED = 4;
- private const short CS_CERTIFICATE_REQUEST_RECEIVED = 5;
- private const short CS_SERVER_HELLO_DONE_RECEIVED = 6;
- private const short CS_CLIENT_KEY_EXCHANGE_SEND = 7;
- private const short CS_CLIENT_CHANGE_CIPHER_SPEC_SEND = 8;
- private const short CS_CLIENT_FINISHED_SEND = 9;
- private const short CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED = 10;
- private const short CS_DONE = 11;
-
- internal const short AP_close_notify = 0;
- internal const short AP_unexpected_message = 10;
- internal const short AP_bad_record_mac = 20;
- internal const short AP_decryption_failed = 21;
- internal const short AP_record_overflow = 22;
- internal const short AP_decompression_failure = 30;
- internal const short AP_handshake_failure = 40;
- internal const short AP_bad_certificate = 42;
- internal const short AP_unsupported_certificate = 43;
- internal const short AP_certificate_revoked = 44;
- internal const short AP_certificate_expired = 45;
- internal const short AP_certificate_unknown = 46;
- internal const short AP_illegal_parameter = 47;
- internal const short AP_unknown_ca = 48;
- internal const short AP_access_denied = 49;
- internal const short AP_decode_error = 50;
- internal const short AP_decrypt_error = 51;
- internal const short AP_export_restriction = 60;
- internal const short AP_protocol_version = 70;
- internal const short AP_insufficient_security = 71;
- internal const short AP_internal_error = 80;
- internal const short AP_user_canceled = 90;
- internal const short AP_no_renegotiation = 100;
-
- internal const short AL_warning = 1;
- internal const short AL_fatal = 2;
-
- private static readonly byte[] emptybuf = new byte[0];
-
- private static readonly string TLS_ERROR_MESSAGE = "Internal TLS error, this could be an attack";
-
- /*
- * Queues for data from some protocols.
- */
-
- private ByteQueue applicationDataQueue = new ByteQueue();
- private ByteQueue changeCipherSpecQueue = new ByteQueue();
- private ByteQueue alertQueue = new ByteQueue();
- private ByteQueue handshakeQueue = new ByteQueue();
-
- /*
- * The Record Stream we use
- */
- private RecordStream rs;
-
- private SecureRandom random;
-
- /*
- * The public rsa-key of the server.
- */
- private RsaKeyParameters serverRsaKey = null;
-
- private TlsInputStream tlsInputStream = null;
- private TlsOuputStream tlsOutputStream = null;
-
- private bool closed = false;
- private bool failedWithError = false;
- private bool appDataReady = false;
-
- private byte[] clientRandom;
- private byte[] serverRandom;
- private byte[] ms;
-
- private TlsCipherSuite choosenCipherSuite = null;
-
- private BigInteger Yc;
- private byte[] pms;
-
- private ICertificateVerifyer verifyer = null;
-
- /*
- * Both streams can be the same object
- */
- public TlsProtocolHandler(
- Stream inStr,
- Stream outStr)
- {
- /*
- * We use a threaded seed generator to generate a good random
- * seed. If the user has a better random seed, he should use
- * the constructor with a SecureRandom.
- *
- * Hopefully, 20 bytes in fast mode are good enough.
- */
- byte[] seed = new ThreadedSeedGenerator().GenerateSeed(20, true);
-
- this.random = new SecureRandom(seed);
- this.rs = new RecordStream(this, inStr, outStr);
- }
-
- public TlsProtocolHandler(
- Stream inStr,
- Stream outStr,
- SecureRandom sr)
- {
- this.random = sr;
- this.rs = new RecordStream(this, inStr, outStr);
- }
-
- private short connection_state;
-
- internal void ProcessData(
- short protocol,
- byte[] buf,
- int offset,
- int len)
- {
- /*
- * Have a look at the protocol type, and add it to the correct queue.
- */
- switch (protocol)
- {
- case RL_CHANGE_CIPHER_SPEC:
- changeCipherSpecQueue.AddData(buf, offset, len);
- processChangeCipherSpec();
- break;
- case RL_ALERT:
- alertQueue.AddData(buf, offset, len);
- processAlert();
- break;
- case RL_HANDSHAKE:
- handshakeQueue.AddData(buf, offset, len);
- processHandshake();
- break;
- case RL_APPLICATION_DATA:
- if (!appDataReady)
- {
- this.FailWithError(AL_fatal, AP_unexpected_message);
- }
- applicationDataQueue.AddData(buf, offset, len);
- processApplicationData();
- break;
- default:
- /*
- * Uh, we don't know this protocol.
- *
- * RFC2246 defines on page 13, that we should ignore this.
- */
- break;
- }
- }
-
- private void processHandshake()
- {
- bool read;
- do
- {
- read = false;
-
- /*
- * We need the first 4 bytes, they contain type and length of
- * the message.
- */
- if (handshakeQueue.Available >= 4)
- {
- byte[] beginning = new byte[4];
- handshakeQueue.Read(beginning, 0, 4, 0);
- MemoryStream bis = new MemoryStream(beginning, false);
- short type = TlsUtilities.ReadUint8(bis);
- int len = TlsUtilities.ReadUint24(bis);
-
- /*
- * Check if we have enough bytes in the buffer to read
- * the full message.
- */
- if (handshakeQueue.Available >= (len + 4))
- {
- /*
- * Read the message.
- */
- byte[] buf = new byte[len];
- handshakeQueue.Read(buf, 0, len, 4);
- handshakeQueue.RemoveData(len + 4);
-
- /*
- * If it is not a finished message, update our hashes
- * we prepare for the finish message.
- */
- if (type != HP_FINISHED)
- {
- rs.hash1.BlockUpdate(beginning, 0, 4);
- rs.hash2.BlockUpdate(beginning, 0, 4);
- rs.hash1.BlockUpdate(buf, 0, len);
- rs.hash2.BlockUpdate(buf, 0, len);
- }
-
- /*
- * Now, parse the message.
- */
- MemoryStream inStr = new MemoryStream(buf, false);
-
- /*
- * Check the type.
- */
- switch (type)
- {
- case HP_CERTIFICATE:
- switch (connection_state)
- {
- case CS_SERVER_HELLO_RECEIVED:
- /*
- * Parse the certificates.
- */
- Certificate cert = Certificate.Parse(inStr);
- AssertEmpty(inStr);
-
- /*
- * Verify them.
- */
- if (!this.verifyer.IsValid(cert.GetCerts()))
- {
- this.FailWithError(AL_fatal, AP_user_canceled);
- }
-
- /*
- * We only support RSA certificates. Lets hope
- * this is one.
- */
- RsaPublicKeyStructure rsaKey = null;
- try
- {
- rsaKey = RsaPublicKeyStructure.GetInstance(
- cert.certs[0].TbsCertificate.SubjectPublicKeyInfo.GetPublicKey());
- }
- catch (Exception)
- {
- /*
- * Sorry, we have to fail ;-(
- */
- this.FailWithError(AL_fatal, AP_unsupported_certificate);
- }
-
- /*
- * Parse the servers public RSA key.
- */
- this.serverRsaKey = new RsaKeyParameters(
- false,
- rsaKey.Modulus,
- rsaKey.PublicExponent);
-
- connection_state = CS_SERVER_CERTIFICATE_RECEIVED;
- read = true;
- break;
- default:
- this.FailWithError(AL_fatal, AP_unexpected_message);
- break;
- }
- break;
- case HP_FINISHED:
- switch (connection_state)
- {
- case CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED:
- /*
- * Read the checksum from the finished message,
- * it has always 12 bytes.
- */
- byte[] receivedChecksum = new byte[12];
- TlsUtilities.ReadFully(receivedChecksum, inStr);
- AssertEmpty(inStr);
-
- /*
- * Calculate our own checksum.
- */
- byte[] checksum = new byte[12];
- byte[] md5andsha1 = new byte[16 + 20];
- rs.hash2.DoFinal(md5andsha1, 0);
- TlsUtilities.PRF(this.ms, TlsUtilities.ToByteArray("server finished"), md5andsha1, checksum);
-
- /*
- * Compare both checksums.
- */
- for (int i = 0; i < receivedChecksum.Length; i++)
- {
- if (receivedChecksum[i] != checksum[i])
- {
- /*
- * Wrong checksum in the finished message.
- */
- this.FailWithError(AL_fatal, AP_handshake_failure);
- }
- }
-
- connection_state = CS_DONE;
-
- /*
- * We are now ready to receive application data.
- */
- this.appDataReady = true;
- read = true;
- break;
- default:
- this.FailWithError(AL_fatal, AP_unexpected_message);
- break;
- }
- break;
- case HP_SERVER_HELLO:
- switch (connection_state)
- {
- case CS_CLIENT_HELLO_SEND:
- /*
- * Read the server hello message
- */
- TlsUtilities.CheckVersion(inStr, this);
-
- /*
- * Read the server random
- */
- this.serverRandom = new byte[32];
- TlsUtilities.ReadFully(this.serverRandom, inStr);
-
- /*
- * Currently, we don't support session ids
- */
- short sessionIdLength = TlsUtilities.ReadUint8(inStr);
- byte[] sessionId = new byte[sessionIdLength];
- TlsUtilities.ReadFully(sessionId, inStr);
-
- /*
- * Find out which ciphersuite the server has
- * chosen. If we don't support this ciphersuite,
- * the TlsCipherSuiteManager will throw an
- * exception.
- */
- this.choosenCipherSuite = TlsCipherSuiteManager.GetCipherSuite(
- TlsUtilities.ReadUint16(inStr), this);
-
- /*
- * We support only the null compression which
- * means no compression.
- */
- short compressionMethod = TlsUtilities.ReadUint8(inStr);
- if (compressionMethod != 0)
- {
- this.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_illegal_parameter);
- }
- AssertEmpty(inStr);
-
- connection_state = CS_SERVER_HELLO_RECEIVED;
- read = true;
- break;
- default:
- this.FailWithError(AL_fatal, AP_unexpected_message);
- break;
- }
- break;
- case HP_SERVER_HELLO_DONE:
- switch (connection_state)
- {
- case CS_SERVER_CERTIFICATE_RECEIVED:
- case CS_SERVER_KEY_EXCHANGE_RECEIVED:
- case CS_CERTIFICATE_REQUEST_RECEIVED:
-
- // NB: Original code used case label fall-through
- if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED)
- {
- /*
- * There was no server key exchange message, check
- * that we are doing RSA key exchange.
- */
- if (this.choosenCipherSuite.KeyExchangeAlgorithm != TlsCipherSuite.KE_RSA)
- {
- this.FailWithError(AL_fatal, AP_unexpected_message);
- }
- }
-
- AssertEmpty(inStr);
- bool isCertReq = (connection_state == CS_CERTIFICATE_REQUEST_RECEIVED);
- connection_state = CS_SERVER_HELLO_DONE_RECEIVED;
-
- if (isCertReq)
- {
- sendClientCertificate();
- }
-
- /*
- * Send the client key exchange message, depending
- * on the key exchange we are using in our
- * ciphersuite.
- */
- short ke = this.choosenCipherSuite.KeyExchangeAlgorithm;
-
- switch (ke)
- {
- case TlsCipherSuite.KE_RSA:
- /*
- * We are doing RSA key exchange. We will
- * choose a pre master secret and send it
- * rsa encrypted to the server.
- *
- * Prepare pre master secret.
- */
- pms = new byte[48];
- pms[0] = 3;
- pms[1] = 1;
- random.NextBytes(pms, 2, 46);
-
- /*
- * Encode the pms and send it to the server.
- *
- * Prepare an Pkcs1Encoding with good random
- * padding.
- */
- RsaBlindedEngine rsa = new RsaBlindedEngine();
- Pkcs1Encoding encoding = new Pkcs1Encoding(rsa);
- encoding.Init(true, new ParametersWithRandom(this.serverRsaKey, this.random));
- byte[] encrypted = null;
- try
- {
- encrypted = encoding.ProcessBlock(pms, 0, pms.Length);
- }
- catch (InvalidCipherTextException)
- {
- /*
- * This should never happen, only during decryption.
- */
- this.FailWithError(AL_fatal, AP_internal_error);
- }
-
- /*
- * Send the encrypted pms.
- */
- MemoryStream bos = new MemoryStream();
- TlsUtilities.WriteUint8(HP_CLIENT_KEY_EXCHANGE, bos);
- TlsUtilities.WriteUint24(encrypted.Length + 2, bos);
- TlsUtilities.WriteUint16(encrypted.Length, bos);
- bos.Write(encrypted, 0, encrypted.Length);
- byte[] message = bos.ToArray();
-
- rs.WriteMessage((short)RL_HANDSHAKE, message, 0, message.Length);
- break;
- case TlsCipherSuite.KE_DHE_RSA:
- /*
- * Send the Client Key Exchange message for
- * DHE key exchange.
- */
- byte[] YcByte = this.Yc.ToByteArray();
- MemoryStream DHbos = new MemoryStream();
- TlsUtilities.WriteUint8(HP_CLIENT_KEY_EXCHANGE, DHbos);
- TlsUtilities.WriteUint24(YcByte.Length + 2, DHbos);
- TlsUtilities.WriteUint16(YcByte.Length, DHbos);
- DHbos.Write(YcByte, 0, YcByte.Length);
- byte[] DHmessage = DHbos.ToArray();
-
- rs.WriteMessage((short)RL_HANDSHAKE, DHmessage, 0, DHmessage.Length);
-
- break;
- default:
- /*
- * Problem during handshake, we don't know
- * how to handle this key exchange method.
- */
- this.FailWithError(AL_fatal, AP_unexpected_message);
- break;
-
- }
-
- connection_state = CS_CLIENT_KEY_EXCHANGE_SEND;
-
- /*
- * Now, we send change cipher state
- */
- byte[] cmessage = new byte[1];
- cmessage[0] = 1;
- rs.WriteMessage((short)RL_CHANGE_CIPHER_SPEC, cmessage, 0, cmessage.Length);
-
- connection_state = CS_CLIENT_CHANGE_CIPHER_SPEC_SEND;
-
- /*
- * Calculate the ms
- */
- this.ms = new byte[48];
- byte[] randBytes = new byte[clientRandom.Length + serverRandom.Length];
- Array.Copy(clientRandom, 0, randBytes, 0, clientRandom.Length);
- Array.Copy(serverRandom, 0, randBytes, clientRandom.Length, serverRandom.Length);
- TlsUtilities.PRF(pms, TlsUtilities.ToByteArray("master secret"), randBytes, this.ms);
-
- /*
- * Initialize our cipher suite
- */
- rs.writeSuite = this.choosenCipherSuite;
- rs.writeSuite.Init(this.ms, clientRandom, serverRandom);
-
- /*
- * Send our finished message.
- */
- byte[] checksum = new byte[12];
- byte[] md5andsha1 = new byte[16 + 20];
- rs.hash1.DoFinal(md5andsha1, 0);
- TlsUtilities.PRF(this.ms, TlsUtilities.ToByteArray("client finished"), md5andsha1, checksum);
-
- MemoryStream bos2 = new MemoryStream();
- TlsUtilities.WriteUint8(HP_FINISHED, bos2);
- TlsUtilities.WriteUint24(12, bos2);
- bos2.Write(checksum, 0, checksum.Length);
- byte[] message2 = bos2.ToArray();
-
- rs.WriteMessage((short)RL_HANDSHAKE, message2, 0, message2.Length);
-
- this.connection_state = CS_CLIENT_FINISHED_SEND;
- read = true;
- break;
- default:
- this.FailWithError(AL_fatal, AP_handshake_failure);
- break;
- }
- break;
- case HP_SERVER_KEY_EXCHANGE:
- switch (connection_state)
- {
- case CS_SERVER_CERTIFICATE_RECEIVED:
- /*
- * Check that we are doing DHE key exchange
- */
- if (this.choosenCipherSuite.KeyExchangeAlgorithm != TlsCipherSuite.KE_DHE_RSA)
- {
- this.FailWithError(AL_fatal, AP_unexpected_message);
- }
-
- /*
- * Parse the Structure
- */
- int pLength = TlsUtilities.ReadUint16(inStr);
- byte[] pByte = new byte[pLength];
- TlsUtilities.ReadFully(pByte, inStr);
-
- int gLength = TlsUtilities.ReadUint16(inStr);
- byte[] gByte = new byte[gLength];
- TlsUtilities.ReadFully(gByte, inStr);
-
- int YsLength = TlsUtilities.ReadUint16(inStr);
- byte[] YsByte = new byte[YsLength];
- TlsUtilities.ReadFully(YsByte, inStr);
-
- int sigLength = TlsUtilities.ReadUint16(inStr);
- byte[] sigByte = new byte[sigLength];
- TlsUtilities.ReadFully(sigByte, inStr);
-
- AssertEmpty(inStr);
-
- /*
- * Verify the Signature.
- *
- * First, calculate the hash.
- */
- CombinedHash sigDigest = new CombinedHash();
- MemoryStream signedData = new MemoryStream();
- TlsUtilities.WriteUint16(pLength, signedData);
- signedData.Write(pByte, 0, pByte.Length);
- TlsUtilities.WriteUint16(gLength, signedData);
- signedData.Write(gByte, 0, gByte.Length);
- TlsUtilities.WriteUint16(YsLength, signedData);
- signedData.Write(YsByte, 0, YsByte.Length);
- byte[] signed = signedData.ToArray();
-
- sigDigest.BlockUpdate(this.clientRandom, 0, this.clientRandom.Length);
- sigDigest.BlockUpdate(this.serverRandom, 0, this.serverRandom.Length);
- sigDigest.BlockUpdate(signed, 0, signed.Length);
- byte[] hash = new byte[sigDigest.GetDigestSize()];
- sigDigest.DoFinal(hash, 0);
-
- /*
- * Now, do the RSA operation
- */
- RsaBlindedEngine rsa = new RsaBlindedEngine();
- Pkcs1Encoding encoding = new Pkcs1Encoding(rsa);
- encoding.Init(false, this.serverRsaKey);
-
- /*
- * The data which was signed
- */
- byte[] sigHash = null;
-
- try
- {
- sigHash = encoding.ProcessBlock(sigByte, 0, sigByte.Length);
- }
- catch (InvalidCipherTextException)
- {
- this.FailWithError(AL_fatal, AP_bad_certificate);
- }
-
- /*
- * Check if the data which was signed is equal to
- * the hash we calculated.
- */
- if (sigHash.Length != hash.Length)
- {
- this.FailWithError(AL_fatal, AP_bad_certificate);
- }
-
- for (int i = 0; i < sigHash.Length; i++)
- {
- if (sigHash[i] != hash[i])
- {
- this.FailWithError(AL_fatal, AP_bad_certificate);
- }
- }
-
- /*
- * OK, Signature was correct.
- *
- * Do the DH calculation.
- */
- BigInteger p = new BigInteger(1, pByte);
- BigInteger g = new BigInteger(1, gByte);
- BigInteger Ys = new BigInteger(1, YsByte);
- BigInteger x = new BigInteger(p.BitLength - 1, this.random);
- Yc = g.ModPow(x, p);
- this.pms = Ys.ModPow(x, p).ToByteArrayUnsigned();
-
- this.connection_state = CS_SERVER_KEY_EXCHANGE_RECEIVED;
- read = true;
- break;
- default:
- this.FailWithError(AL_fatal, AP_unexpected_message);
- break;
- }
- break;
- case HP_CERTIFICATE_REQUEST:
- switch (connection_state)
- {
- case CS_SERVER_CERTIFICATE_RECEIVED:
- case CS_SERVER_KEY_EXCHANGE_RECEIVED:
-
- // NB: Original code used case label fall-through
- if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED)
- {
- /*
- * There was no server key exchange message, check
- * that we are doing RSA key exchange.
- */
- if (this.choosenCipherSuite.KeyExchangeAlgorithm != TlsCipherSuite.KE_RSA)
- {
- this.FailWithError(AL_fatal, AP_unexpected_message);
- }
- }
-
- int typesLength = TlsUtilities.ReadUint8(inStr);
- byte[] types = new byte[typesLength];
- TlsUtilities.ReadFully(types, inStr);
-
- int authsLength = TlsUtilities.ReadUint16(inStr);
- byte[] auths = new byte[authsLength];
- TlsUtilities.ReadFully(auths, inStr);
-
- AssertEmpty(inStr);
-
- this.connection_state = CS_CERTIFICATE_REQUEST_RECEIVED;
- read = true;
- break;
- default:
- this.FailWithError(AL_fatal, AP_unexpected_message);
- break;
- }
- break;
- case HP_HELLO_REQUEST:
- case HP_CLIENT_KEY_EXCHANGE:
- case HP_CERTIFICATE_VERIFY:
- case HP_CLIENT_HELLO:
- default:
- // We do not support this!
- this.FailWithError(AL_fatal, AP_unexpected_message);
- break;
-
- }
-
- }
- }
- }
- while (read);
-
- }
-
- private void processApplicationData()
- {
- /*
- * There is nothing we need to do here.
- *
- * This function could be used for callbacks when application
- * data arrives in the future.
- */
- }
-
- private void processAlert()
- {
- while (alertQueue.Available >= 2)
- {
- /*
- * An alert is always 2 bytes. Read the alert.
- */
- byte[] tmp = new byte[2];
- alertQueue.Read(tmp, 0, 2, 0);
- alertQueue.RemoveData(2);
- short level = tmp[0];
- short description = tmp[1];
- if (level == AL_fatal)
- {
- /*
- * This is a fatal error.
- */
- this.failedWithError = true;
- this.closed = true;
- /*
- * Now try to Close the stream, ignore errors.
- */
- try
- {
- rs.Close();
- }
- catch (Exception)
- {
- }
- throw new IOException(TLS_ERROR_MESSAGE);
- }
- else
- {
- /*
- * This is just a warning.
- */
- if (description == AP_close_notify)
- {
- /*
- * Close notify
- */
- this.FailWithError(AL_warning, AP_close_notify);
- }
- /*
- * If it is just a warning, we continue.
- */
- }
- }
-
- }
-
- /**
- * This method is called, when a change cipher spec message is received.
- *
- * @throws IOException If the message has an invalid content or the
- * handshake is not in the correct state.
- */
- private void processChangeCipherSpec()
- {
- while (changeCipherSpecQueue.Available > 0)
- {
- /*
- * A change cipher spec message is only one byte with the value 1.
- */
- byte[] b = new byte[1];
- changeCipherSpecQueue.Read(b, 0, 1, 0);
- changeCipherSpecQueue.RemoveData(1);
- if (b[0] != 1)
- {
- /*
- * This should never happen.
- */
- this.FailWithError(AL_fatal, AP_unexpected_message);
-
- }
- else
- {
- /*
- * Check if we are in the correct connection state.
- */
- if (this.connection_state == CS_CLIENT_FINISHED_SEND)
- {
- rs.readSuite = rs.writeSuite;
- this.connection_state = CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED;
- }
- else
- {
- /*
- * We are not in the correct connection state.
- */
- this.FailWithError(AL_fatal, AP_handshake_failure);
- }
-
- }
- }
- }
-
- private void sendClientCertificate()
- {
- /*
- * just write back the "no client certificate" message
- * see also gnutls, auth_cert.c:643 (0B 00 00 03 00 00 00)
- */
- MemoryStream bos = new MemoryStream();
- TlsUtilities.WriteUint8(HP_CERTIFICATE, bos);
- TlsUtilities.WriteUint24(3, bos);
- TlsUtilities.WriteUint24(0, bos);
- byte[] message = bos.ToArray();
-
- rs.WriteMessage((short)RL_HANDSHAKE, message, 0, message.Length);
- }
-
- /// Connects to the remote system.
- /// Will be used when a certificate is received to verify
- /// that this certificate is accepted by the client.
- /// If handshake was not successful
- public virtual void Connect(
- ICertificateVerifyer verifyer)
- {
- this.verifyer = verifyer;
-
- /*
- * Send Client hello
- *
- * First, generate some random data.
- */
- this.clientRandom = new byte[32];
-
- /*
- * TLS 1.0 requires a unix-timestamp in the first 4 bytes
- */
- int t = (int)(DateTimeUtilities.CurrentUnixMs() / 1000L);
- this.clientRandom[0] = (byte)(t >> 24);
- this.clientRandom[1] = (byte)(t >> 16);
- this.clientRandom[2] = (byte)(t >> 8);
- this.clientRandom[3] = (byte)t;
-
- random.NextBytes(this.clientRandom, 4, 28);
-
-
- MemoryStream outStr = new MemoryStream();
- TlsUtilities.WriteVersion(outStr);
- outStr.Write(this.clientRandom, 0, this.clientRandom.Length);
-
- /*
- * Length of Session id
- */
- TlsUtilities.WriteUint8((short)0, outStr);
-
- /*
- * Cipher suites
- */
- TlsCipherSuiteManager.WriteCipherSuites(outStr);
-
- /*
- * Compression methods, just the null method.
- */
- byte[] compressionMethods = new byte[]{0x00};
- TlsUtilities.WriteUint8((short)compressionMethods.Length, outStr);
- outStr.Write(compressionMethods,0, compressionMethods.Length);
-
-
- MemoryStream bos = new MemoryStream();
- TlsUtilities.WriteUint8(HP_CLIENT_HELLO, bos);
- TlsUtilities.WriteUint24((int) outStr.Length, bos);
- byte[] outBytes = outStr.ToArray();
- bos.Write(outBytes, 0, outBytes.Length);
- byte[] message = bos.ToArray();
- rs.WriteMessage(RL_HANDSHAKE, message, 0, message.Length);
- connection_state = CS_CLIENT_HELLO_SEND;
-
- /*
- * We will now read data, until we have completed the handshake.
- */
- while (connection_state != CS_DONE)
- {
- rs.ReadData();
- }
-
- this.tlsInputStream = new TlsInputStream(this);
- this.tlsOutputStream = new TlsOuputStream(this);
- }
-
- /**
- * Read data from the network. The method will return immed, if there is
- * still some data left in the buffer, or block untill some application
- * data has been read from the network.
- *
- * @param buf The buffer where the data will be copied to.
- * @param offset The position where the data will be placed in the buffer.
- * @param len The maximum number of bytes to read.
- * @return The number of bytes read.
- * @throws IOException If something goes wrong during reading data.
- */
- internal int ReadApplicationData(byte[] buf, int offset, int len)
- {
- while (applicationDataQueue.Available == 0)
- {
- /*
- * We need to read some data.
- */
- if (this.failedWithError)
- {
- /*
- * Something went terribly wrong, we should throw an IOException
- */
- throw new IOException(TLS_ERROR_MESSAGE);
- }
- if (this.closed)
- {
- /*
- * Connection has been closed, there is no more data to read.
- */
- return 0;
- }
-
- try
- {
- rs.ReadData();
- }
- catch (IOException e)
- {
- if (!this.closed)
- {
- this.FailWithError(AL_fatal, AP_internal_error);
- }
- throw e;
- }
- catch (Exception e)
- {
- if (!this.closed)
- {
- this.FailWithError(AL_fatal, AP_internal_error);
- }
- throw e;
- }
- }
- len = System.Math.Min(len, applicationDataQueue.Available);
- applicationDataQueue.Read(buf, offset, len, 0);
- applicationDataQueue.RemoveData(len);
- return len;
- }
-
- /**
- * Send some application data to the remote system.
- *
- * The method will handle fragmentation internally.
- *
- * @param buf The buffer with the data.
- * @param offset The position in the buffer where the data is placed.
- * @param len The length of the data.
- * @throws IOException If something goes wrong during sending.
- */
- internal void WriteData(byte[] buf, int offset, int len)
- {
- if (this.failedWithError)
- {
- throw new IOException(TLS_ERROR_MESSAGE);
- }
- if (this.closed)
- {
- throw new IOException("Sorry, connection has been closed, you cannot write more data");
- }
-
- /*
- * Protect against known IV attack!
- *
- * DO NOT REMOVE THIS LINE, EXCEPT YOU KNOW EXACTLY WHAT
- * YOU ARE DOING HERE.
- */
- rs.WriteMessage(RL_APPLICATION_DATA, emptybuf, 0, 0);
-
- do
- {
- /*
- * We are only allowed to write fragments up to 2^14 bytes.
- */
- int toWrite = System.Math.Min(len, 1 << 14);
-
- try
- {
- rs.WriteMessage(RL_APPLICATION_DATA, buf, offset, toWrite);
- }
- catch (IOException e)
- {
- if (!closed)
- {
- this.FailWithError(AL_fatal, AP_internal_error);
- }
- throw e;
- }
- catch (Exception e)
- {
- if (!closed)
- {
- this.FailWithError(AL_fatal, AP_internal_error);
- }
- throw e;
- }
-
-
- offset += toWrite;
- len -= toWrite;
- }
- while (len > 0);
-
- }
-
- [Obsolete("Use 'OutputStream' property instead")]
- public TlsOuputStream TlsOuputStream
- {
- get { return this.tlsOutputStream; }
- }
-
- /// A Stream which can be used to send data.
- public virtual Stream OutputStream
- {
- get { return this.tlsOutputStream; }
- }
-
- [Obsolete("Use 'InputStream' property instead")]
- public TlsInputStream TlsInputStream
- {
- get { return this.tlsInputStream; }
- }
-
- /// A Stream which can be used to read data.
- public virtual Stream InputStream
- {
- get { return this.tlsInputStream; }
- }
-
- /**
- * Terminate this connection whith an alert.
- *
- * Can be used for normal closure too.
- *
- * @param alertLevel The level of the alert, an be AL_fatal or AL_warning.
- * @param alertDescription The exact alert message.
- * @throws IOException If alert was fatal.
- */
- internal void FailWithError(
- short alertLevel,
- short alertDescription)
- {
- /*
- * Check if the connection is still open.
- */
- if (!closed)
- {
- /*
- * Prepare the message
- */
- byte[] error = new byte[2];
- error[0] = (byte)alertLevel;
- error[1] = (byte)alertDescription;
- this.closed = true;
-
- if (alertLevel == AL_fatal)
- {
- /*
- * This is a fatal message.
- */
- this.failedWithError = true;
- }
- rs.WriteMessage(RL_ALERT, error, 0, 2);
- rs.Close();
- if (alertLevel == AL_fatal)
- {
- throw new IOException(TLS_ERROR_MESSAGE);
- }
-
- }
- else
- {
- throw new IOException(TLS_ERROR_MESSAGE);
- }
- }
-
- /// Closes this connection
- /// If something goes wrong during closing.
- public virtual void Close()
- {
- if (!closed)
- {
- this.FailWithError((short)1, (short)0);
- }
- }
-
- /**
- * Make sure the Stream is now empty. Fail otherwise.
- *
- * @param is The Stream to check.
- * @throws IOException If is is not empty.
- */
- internal void AssertEmpty(
- MemoryStream inStr)
- {
-// if (inStr.available() > 0)
- if (inStr.Position < inStr.Length)
- {
- this.FailWithError(AL_fatal, AP_decode_error);
- }
- }
-
- internal void Flush()
- {
- rs.Flush();
- }
- }
-}
+using System;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Prng;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ /// An implementation of all high level protocols in TLS 1.0.
+ public class TlsProtocolHandler
+ {
+ private const short RL_CHANGE_CIPHER_SPEC = 20;
+ private const short RL_ALERT = 21;
+ private const short RL_HANDSHAKE = 22;
+ private const short RL_APPLICATION_DATA = 23;
+
+ /*
+ hello_request(0), client_hello(1), server_hello(2),
+ certificate(11), server_key_exchange (12),
+ certificate_request(13), server_hello_done(14),
+ certificate_verify(15), client_key_exchange(16),
+ finished(20), (255)
+ */
+
+ private const short HP_HELLO_REQUEST = 0;
+ private const short HP_CLIENT_HELLO = 1;
+ private const short HP_SERVER_HELLO = 2;
+ private const short HP_CERTIFICATE = 11;
+ private const short HP_SERVER_KEY_EXCHANGE = 12;
+ private const short HP_CERTIFICATE_REQUEST = 13;
+ private const short HP_SERVER_HELLO_DONE = 14;
+ private const short HP_CERTIFICATE_VERIFY = 15;
+ private const short HP_CLIENT_KEY_EXCHANGE = 16;
+ private const short HP_FINISHED = 20;
+
+ /*
+ * Our Connection states
+ */
+
+ private const short CS_CLIENT_HELLO_SEND = 1;
+ private const short CS_SERVER_HELLO_RECEIVED = 2;
+ private const short CS_SERVER_CERTIFICATE_RECEIVED = 3;
+ private const short CS_SERVER_KEY_EXCHANGE_RECEIVED = 4;
+ private const short CS_CERTIFICATE_REQUEST_RECEIVED = 5;
+ private const short CS_SERVER_HELLO_DONE_RECEIVED = 6;
+ private const short CS_CLIENT_KEY_EXCHANGE_SEND = 7;
+ private const short CS_CLIENT_CHANGE_CIPHER_SPEC_SEND = 8;
+ private const short CS_CLIENT_FINISHED_SEND = 9;
+ private const short CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED = 10;
+ private const short CS_DONE = 11;
+
+ internal const short AP_close_notify = 0;
+ internal const short AP_unexpected_message = 10;
+ internal const short AP_bad_record_mac = 20;
+ internal const short AP_decryption_failed = 21;
+ internal const short AP_record_overflow = 22;
+ internal const short AP_decompression_failure = 30;
+ internal const short AP_handshake_failure = 40;
+ internal const short AP_bad_certificate = 42;
+ internal const short AP_unsupported_certificate = 43;
+ internal const short AP_certificate_revoked = 44;
+ internal const short AP_certificate_expired = 45;
+ internal const short AP_certificate_unknown = 46;
+ internal const short AP_illegal_parameter = 47;
+ internal const short AP_unknown_ca = 48;
+ internal const short AP_access_denied = 49;
+ internal const short AP_decode_error = 50;
+ internal const short AP_decrypt_error = 51;
+ internal const short AP_export_restriction = 60;
+ internal const short AP_protocol_version = 70;
+ internal const short AP_insufficient_security = 71;
+ internal const short AP_internal_error = 80;
+ internal const short AP_user_canceled = 90;
+ internal const short AP_no_renegotiation = 100;
+
+ internal const short AL_warning = 1;
+ internal const short AL_fatal = 2;
+
+ private static readonly byte[] emptybuf = new byte[0];
+
+ private static readonly string TLS_ERROR_MESSAGE = "Internal TLS error, this could be an attack";
+
+ /*
+ * Queues for data from some protocols.
+ */
+
+ private ByteQueue applicationDataQueue = new ByteQueue();
+ private ByteQueue changeCipherSpecQueue = new ByteQueue();
+ private ByteQueue alertQueue = new ByteQueue();
+ private ByteQueue handshakeQueue = new ByteQueue();
+
+ /*
+ * The Record Stream we use
+ */
+ private RecordStream rs;
+
+ private SecureRandom random;
+
+ /*
+ * The public rsa-key of the server.
+ */
+ private RsaKeyParameters serverRsaKey = null;
+
+ private TlsInputStream tlsInputStream = null;
+ private TlsOuputStream tlsOutputStream = null;
+
+ private bool closed = false;
+ private bool failedWithError = false;
+ private bool appDataReady = false;
+
+ private byte[] clientRandom;
+ private byte[] serverRandom;
+ private byte[] ms;
+
+ private TlsCipherSuite chosenCipherSuite = null;
+
+ private BigInteger Yc;
+ private byte[] pms;
+
+ private ICertificateVerifyer verifyer = null;
+
+ /*
+ * Both streams can be the same object
+ */
+ public TlsProtocolHandler(
+ Stream inStr,
+ Stream outStr)
+ {
+ /*
+ * We use a threaded seed generator to generate a good random
+ * seed. If the user has a better random seed, he should use
+ * the constructor with a SecureRandom.
+ *
+ * Hopefully, 20 bytes in fast mode are good enough.
+ */
+ byte[] seed = new ThreadedSeedGenerator().GenerateSeed(20, true);
+
+ this.random = new SecureRandom(seed);
+ this.rs = new RecordStream(this, inStr, outStr);
+ }
+
+ public TlsProtocolHandler(
+ Stream inStr,
+ Stream outStr,
+ SecureRandom sr)
+ {
+ this.random = sr;
+ this.rs = new RecordStream(this, inStr, outStr);
+ }
+
+ private short connection_state;
+
+ internal void ProcessData(
+ short protocol,
+ byte[] buf,
+ int offset,
+ int len)
+ {
+ /*
+ * Have a look at the protocol type, and add it to the correct queue.
+ */
+ switch (protocol)
+ {
+ case RL_CHANGE_CIPHER_SPEC:
+ changeCipherSpecQueue.AddData(buf, offset, len);
+ processChangeCipherSpec();
+ break;
+ case RL_ALERT:
+ alertQueue.AddData(buf, offset, len);
+ processAlert();
+ break;
+ case RL_HANDSHAKE:
+ handshakeQueue.AddData(buf, offset, len);
+ processHandshake();
+ break;
+ case RL_APPLICATION_DATA:
+ if (!appDataReady)
+ {
+ this.FailWithError(AL_fatal, AP_unexpected_message);
+ }
+ applicationDataQueue.AddData(buf, offset, len);
+ processApplicationData();
+ break;
+ default:
+ /*
+ * Uh, we don't know this protocol.
+ *
+ * RFC2246 defines on page 13, that we should ignore this.
+ */
+ break;
+ }
+ }
+
+ private void processHandshake()
+ {
+ bool read;
+ do
+ {
+ read = false;
+
+ /*
+ * We need the first 4 bytes, they contain type and length of
+ * the message.
+ */
+ if (handshakeQueue.Available >= 4)
+ {
+ byte[] beginning = new byte[4];
+ handshakeQueue.Read(beginning, 0, 4, 0);
+ MemoryStream bis = new MemoryStream(beginning, false);
+ short type = TlsUtilities.ReadUint8(bis);
+ int len = TlsUtilities.ReadUint24(bis);
+
+ /*
+ * Check if we have enough bytes in the buffer to read
+ * the full message.
+ */
+ if (handshakeQueue.Available >= (len + 4))
+ {
+ /*
+ * Read the message.
+ */
+ byte[] buf = new byte[len];
+ handshakeQueue.Read(buf, 0, len, 4);
+ handshakeQueue.RemoveData(len + 4);
+
+ /*
+ * If it is not a finished message, update our hashes
+ * we prepare for the finish message.
+ */
+ if (type != HP_FINISHED)
+ {
+ rs.hash1.BlockUpdate(beginning, 0, 4);
+ rs.hash2.BlockUpdate(beginning, 0, 4);
+ rs.hash1.BlockUpdate(buf, 0, len);
+ rs.hash2.BlockUpdate(buf, 0, len);
+ }
+
+ /*
+ * Now, parse the message.
+ */
+ MemoryStream inStr = new MemoryStream(buf, false);
+
+ /*
+ * Check the type.
+ */
+ switch (type)
+ {
+ case HP_CERTIFICATE:
+ switch (connection_state)
+ {
+ case CS_SERVER_HELLO_RECEIVED:
+ /*
+ * Parse the certificates.
+ */
+ Certificate cert = Certificate.Parse(inStr);
+ AssertEmpty(inStr);
+
+ /*
+ * Verify them.
+ */
+ if (!this.verifyer.IsValid(cert.GetCerts()))
+ {
+ this.FailWithError(AL_fatal, AP_user_canceled);
+ }
+
+ /*
+ * We only support RSA certificates. Lets hope
+ * this is one.
+ */
+ RsaPublicKeyStructure rsaKey = null;
+ try
+ {
+ rsaKey = RsaPublicKeyStructure.GetInstance(
+ cert.certs[0].TbsCertificate.SubjectPublicKeyInfo.GetPublicKey());
+ }
+ catch (Exception)
+ {
+ /*
+ * Sorry, we have to fail ;-(
+ */
+ this.FailWithError(AL_fatal, AP_unsupported_certificate);
+ }
+
+ /*
+ * Parse the servers public RSA key.
+ */
+ this.serverRsaKey = new RsaKeyParameters(
+ false,
+ rsaKey.Modulus,
+ rsaKey.PublicExponent);
+
+ connection_state = CS_SERVER_CERTIFICATE_RECEIVED;
+ read = true;
+ break;
+ default:
+ this.FailWithError(AL_fatal, AP_unexpected_message);
+ break;
+ }
+ break;
+ case HP_FINISHED:
+ switch (connection_state)
+ {
+ case CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED:
+ /*
+ * Read the checksum from the finished message,
+ * it has always 12 bytes.
+ */
+ byte[] receivedChecksum = new byte[12];
+ TlsUtilities.ReadFully(receivedChecksum, inStr);
+ AssertEmpty(inStr);
+
+ /*
+ * Calculate our own checksum.
+ */
+ byte[] checksum = new byte[12];
+ byte[] md5andsha1 = new byte[16 + 20];
+ rs.hash2.DoFinal(md5andsha1, 0);
+ TlsUtilities.PRF(this.ms, TlsUtilities.ToByteArray("server finished"), md5andsha1, checksum);
+
+ /*
+ * Compare both checksums.
+ */
+ for (int i = 0; i < receivedChecksum.Length; i++)
+ {
+ if (receivedChecksum[i] != checksum[i])
+ {
+ /*
+ * Wrong checksum in the finished message.
+ */
+ this.FailWithError(AL_fatal, AP_handshake_failure);
+ }
+ }
+
+ connection_state = CS_DONE;
+
+ /*
+ * We are now ready to receive application data.
+ */
+ this.appDataReady = true;
+ read = true;
+ break;
+ default:
+ this.FailWithError(AL_fatal, AP_unexpected_message);
+ break;
+ }
+ break;
+ case HP_SERVER_HELLO:
+ switch (connection_state)
+ {
+ case CS_CLIENT_HELLO_SEND:
+ /*
+ * Read the server hello message
+ */
+ TlsUtilities.CheckVersion(inStr, this);
+
+ /*
+ * Read the server random
+ */
+ this.serverRandom = new byte[32];
+ TlsUtilities.ReadFully(this.serverRandom, inStr);
+
+ /*
+ * Currently, we don't support session ids
+ */
+ short sessionIdLength = TlsUtilities.ReadUint8(inStr);
+ byte[] sessionId = new byte[sessionIdLength];
+ TlsUtilities.ReadFully(sessionId, inStr);
+
+ /*
+ * Find out which ciphersuite the server has
+ * chosen. If we don't support this ciphersuite,
+ * the TlsCipherSuiteManager will throw an
+ * exception.
+ */
+ this.chosenCipherSuite = TlsCipherSuiteManager.GetCipherSuite(
+ TlsUtilities.ReadUint16(inStr), this);
+
+ /*
+ * We support only the null compression which
+ * means no compression.
+ */
+ short compressionMethod = TlsUtilities.ReadUint8(inStr);
+ if (compressionMethod != 0)
+ {
+ this.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_illegal_parameter);
+ }
+ AssertEmpty(inStr);
+
+ connection_state = CS_SERVER_HELLO_RECEIVED;
+ read = true;
+ break;
+ default:
+ this.FailWithError(AL_fatal, AP_unexpected_message);
+ break;
+ }
+ break;
+ case HP_SERVER_HELLO_DONE:
+ switch (connection_state)
+ {
+ case CS_SERVER_CERTIFICATE_RECEIVED:
+ case CS_SERVER_KEY_EXCHANGE_RECEIVED:
+ case CS_CERTIFICATE_REQUEST_RECEIVED:
+
+ // NB: Original code used case label fall-through
+ if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED)
+ {
+ /*
+ * There was no server key exchange message, check
+ * that we are doing RSA key exchange.
+ */
+ if (this.chosenCipherSuite.KeyExchangeAlgorithm != TlsCipherSuite.KE_RSA)
+ {
+ this.FailWithError(AL_fatal, AP_unexpected_message);
+ }
+ }
+
+ AssertEmpty(inStr);
+ bool isCertReq = (connection_state == CS_CERTIFICATE_REQUEST_RECEIVED);
+ connection_state = CS_SERVER_HELLO_DONE_RECEIVED;
+
+ if (isCertReq)
+ {
+ sendClientCertificate();
+ }
+
+ /*
+ * Send the client key exchange message, depending
+ * on the key exchange we are using in our
+ * ciphersuite.
+ */
+ short ke = this.chosenCipherSuite.KeyExchangeAlgorithm;
+
+ switch (ke)
+ {
+ case TlsCipherSuite.KE_RSA:
+ /*
+ * We are doing RSA key exchange. We will
+ * choose a pre master secret and send it
+ * rsa encrypted to the server.
+ *
+ * Prepare pre master secret.
+ */
+ pms = new byte[48];
+ pms[0] = 3;
+ pms[1] = 1;
+ random.NextBytes(pms, 2, 46);
+
+ /*
+ * Encode the pms and send it to the server.
+ *
+ * Prepare an Pkcs1Encoding with good random
+ * padding.
+ */
+ RsaBlindedEngine rsa = new RsaBlindedEngine();
+ Pkcs1Encoding encoding = new Pkcs1Encoding(rsa);
+ encoding.Init(true, new ParametersWithRandom(this.serverRsaKey, this.random));
+ byte[] encrypted = null;
+ try
+ {
+ encrypted = encoding.ProcessBlock(pms, 0, pms.Length);
+ }
+ catch (InvalidCipherTextException)
+ {
+ /*
+ * This should never happen, only during decryption.
+ */
+ this.FailWithError(AL_fatal, AP_internal_error);
+ }
+
+ /*
+ * Send the encrypted pms.
+ */
+ MemoryStream bos = new MemoryStream();
+ TlsUtilities.WriteUint8(HP_CLIENT_KEY_EXCHANGE, bos);
+ TlsUtilities.WriteUint24(encrypted.Length + 2, bos);
+ TlsUtilities.WriteUint16(encrypted.Length, bos);
+ bos.Write(encrypted, 0, encrypted.Length);
+ byte[] message = bos.ToArray();
+
+ rs.WriteMessage((short)RL_HANDSHAKE, message, 0, message.Length);
+ break;
+ case TlsCipherSuite.KE_DHE_RSA:
+ /*
+ * Send the Client Key Exchange message for
+ * DHE key exchange.
+ */
+ byte[] YcByte = this.Yc.ToByteArray();
+ MemoryStream DHbos = new MemoryStream();
+ TlsUtilities.WriteUint8(HP_CLIENT_KEY_EXCHANGE, DHbos);
+ TlsUtilities.WriteUint24(YcByte.Length + 2, DHbos);
+ TlsUtilities.WriteUint16(YcByte.Length, DHbos);
+ DHbos.Write(YcByte, 0, YcByte.Length);
+ byte[] DHmessage = DHbos.ToArray();
+
+ rs.WriteMessage((short)RL_HANDSHAKE, DHmessage, 0, DHmessage.Length);
+
+ break;
+ default:
+ /*
+ * Problem during handshake, we don't know
+ * how to handle this key exchange method.
+ */
+ this.FailWithError(AL_fatal, AP_unexpected_message);
+ break;
+
+ }
+
+ connection_state = CS_CLIENT_KEY_EXCHANGE_SEND;
+
+ /*
+ * Now, we send change cipher state
+ */
+ byte[] cmessage = new byte[1];
+ cmessage[0] = 1;
+ rs.WriteMessage((short)RL_CHANGE_CIPHER_SPEC, cmessage, 0, cmessage.Length);
+
+ connection_state = CS_CLIENT_CHANGE_CIPHER_SPEC_SEND;
+
+ /*
+ * Calculate the ms
+ */
+ this.ms = new byte[48];
+ byte[] randBytes = new byte[clientRandom.Length + serverRandom.Length];
+ Array.Copy(clientRandom, 0, randBytes, 0, clientRandom.Length);
+ Array.Copy(serverRandom, 0, randBytes, clientRandom.Length, serverRandom.Length);
+ TlsUtilities.PRF(pms, TlsUtilities.ToByteArray("master secret"), randBytes, this.ms);
+
+ /*
+ * Initialize our cipher suite
+ */
+ rs.writeSuite = this.chosenCipherSuite;
+ rs.writeSuite.Init(this.ms, clientRandom, serverRandom);
+
+ /*
+ * Send our finished message.
+ */
+ byte[] checksum = new byte[12];
+ byte[] md5andsha1 = new byte[16 + 20];
+ rs.hash1.DoFinal(md5andsha1, 0);
+ TlsUtilities.PRF(this.ms, TlsUtilities.ToByteArray("client finished"), md5andsha1, checksum);
+
+ MemoryStream bos2 = new MemoryStream();
+ TlsUtilities.WriteUint8(HP_FINISHED, bos2);
+ TlsUtilities.WriteUint24(12, bos2);
+ bos2.Write(checksum, 0, checksum.Length);
+ byte[] message2 = bos2.ToArray();
+
+ rs.WriteMessage((short)RL_HANDSHAKE, message2, 0, message2.Length);
+
+ this.connection_state = CS_CLIENT_FINISHED_SEND;
+ read = true;
+ break;
+ default:
+ this.FailWithError(AL_fatal, AP_handshake_failure);
+ break;
+ }
+ break;
+ case HP_SERVER_KEY_EXCHANGE:
+ switch (connection_state)
+ {
+ case CS_SERVER_CERTIFICATE_RECEIVED:
+ /*
+ * Check that we are doing DHE key exchange
+ */
+ if (this.chosenCipherSuite.KeyExchangeAlgorithm != TlsCipherSuite.KE_DHE_RSA)
+ {
+ this.FailWithError(AL_fatal, AP_unexpected_message);
+ }
+
+ /*
+ * Parse the Structure
+ */
+ int pLength = TlsUtilities.ReadUint16(inStr);
+ byte[] pByte = new byte[pLength];
+ TlsUtilities.ReadFully(pByte, inStr);
+
+ int gLength = TlsUtilities.ReadUint16(inStr);
+ byte[] gByte = new byte[gLength];
+ TlsUtilities.ReadFully(gByte, inStr);
+
+ int YsLength = TlsUtilities.ReadUint16(inStr);
+ byte[] YsByte = new byte[YsLength];
+ TlsUtilities.ReadFully(YsByte, inStr);
+
+ int sigLength = TlsUtilities.ReadUint16(inStr);
+ byte[] sigByte = new byte[sigLength];
+ TlsUtilities.ReadFully(sigByte, inStr);
+
+ AssertEmpty(inStr);
+
+ /*
+ * Verify the Signature.
+ *
+ * First, calculate the hash.
+ */
+ CombinedHash sigDigest = new CombinedHash();
+ MemoryStream signedData = new MemoryStream();
+ TlsUtilities.WriteUint16(pLength, signedData);
+ signedData.Write(pByte, 0, pByte.Length);
+ TlsUtilities.WriteUint16(gLength, signedData);
+ signedData.Write(gByte, 0, gByte.Length);
+ TlsUtilities.WriteUint16(YsLength, signedData);
+ signedData.Write(YsByte, 0, YsByte.Length);
+ byte[] signed = signedData.ToArray();
+
+ sigDigest.BlockUpdate(this.clientRandom, 0, this.clientRandom.Length);
+ sigDigest.BlockUpdate(this.serverRandom, 0, this.serverRandom.Length);
+ sigDigest.BlockUpdate(signed, 0, signed.Length);
+ byte[] hash = new byte[sigDigest.GetDigestSize()];
+ sigDigest.DoFinal(hash, 0);
+
+ /*
+ * Now, do the RSA operation
+ */
+ RsaBlindedEngine rsa = new RsaBlindedEngine();
+ Pkcs1Encoding encoding = new Pkcs1Encoding(rsa);
+ encoding.Init(false, this.serverRsaKey);
+
+ /*
+ * The data which was signed
+ */
+ byte[] sigHash = null;
+
+ try
+ {
+ sigHash = encoding.ProcessBlock(sigByte, 0, sigByte.Length);
+ }
+ catch (InvalidCipherTextException)
+ {
+ this.FailWithError(AL_fatal, AP_bad_certificate);
+ }
+
+ /*
+ * Check if the data which was signed is equal to
+ * the hash we calculated.
+ */
+ if (sigHash.Length != hash.Length)
+ {
+ this.FailWithError(AL_fatal, AP_bad_certificate);
+ }
+
+ for (int i = 0; i < sigHash.Length; i++)
+ {
+ if (sigHash[i] != hash[i])
+ {
+ this.FailWithError(AL_fatal, AP_bad_certificate);
+ }
+ }
+
+ /*
+ * OK, Signature was correct.
+ *
+ * Do the DH calculation.
+ */
+ BigInteger p = new BigInteger(1, pByte);
+ BigInteger g = new BigInteger(1, gByte);
+ BigInteger Ys = new BigInteger(1, YsByte);
+ BigInteger x = new BigInteger(p.BitLength - 1, this.random);
+ Yc = g.ModPow(x, p);
+ this.pms = Ys.ModPow(x, p).ToByteArrayUnsigned();
+
+ this.connection_state = CS_SERVER_KEY_EXCHANGE_RECEIVED;
+ read = true;
+ break;
+ default:
+ this.FailWithError(AL_fatal, AP_unexpected_message);
+ break;
+ }
+ break;
+ case HP_CERTIFICATE_REQUEST:
+ switch (connection_state)
+ {
+ case CS_SERVER_CERTIFICATE_RECEIVED:
+ case CS_SERVER_KEY_EXCHANGE_RECEIVED:
+
+ // NB: Original code used case label fall-through
+ if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED)
+ {
+ /*
+ * There was no server key exchange message, check
+ * that we are doing RSA key exchange.
+ */
+ if (this.chosenCipherSuite.KeyExchangeAlgorithm != TlsCipherSuite.KE_RSA)
+ {
+ this.FailWithError(AL_fatal, AP_unexpected_message);
+ }
+ }
+
+ int typesLength = TlsUtilities.ReadUint8(inStr);
+ byte[] types = new byte[typesLength];
+ TlsUtilities.ReadFully(types, inStr);
+
+ int authsLength = TlsUtilities.ReadUint16(inStr);
+ byte[] auths = new byte[authsLength];
+ TlsUtilities.ReadFully(auths, inStr);
+
+ AssertEmpty(inStr);
+
+ this.connection_state = CS_CERTIFICATE_REQUEST_RECEIVED;
+ read = true;
+ break;
+ default:
+ this.FailWithError(AL_fatal, AP_unexpected_message);
+ break;
+ }
+ break;
+ case HP_HELLO_REQUEST:
+ case HP_CLIENT_KEY_EXCHANGE:
+ case HP_CERTIFICATE_VERIFY:
+ case HP_CLIENT_HELLO:
+ default:
+ // We do not support this!
+ this.FailWithError(AL_fatal, AP_unexpected_message);
+ break;
+
+ }
+
+ }
+ }
+ }
+ while (read);
+
+ }
+
+ private void processApplicationData()
+ {
+ /*
+ * There is nothing we need to do here.
+ *
+ * This function could be used for callbacks when application
+ * data arrives in the future.
+ */
+ }
+
+ private void processAlert()
+ {
+ while (alertQueue.Available >= 2)
+ {
+ /*
+ * An alert is always 2 bytes. Read the alert.
+ */
+ byte[] tmp = new byte[2];
+ alertQueue.Read(tmp, 0, 2, 0);
+ alertQueue.RemoveData(2);
+ short level = tmp[0];
+ short description = tmp[1];
+ if (level == AL_fatal)
+ {
+ /*
+ * This is a fatal error.
+ */
+ this.failedWithError = true;
+ this.closed = true;
+ /*
+ * Now try to Close the stream, ignore errors.
+ */
+ try
+ {
+ rs.Close();
+ }
+ catch (Exception)
+ {
+ }
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+ else
+ {
+ /*
+ * This is just a warning.
+ */
+ if (description == AP_close_notify)
+ {
+ /*
+ * Close notify
+ */
+ this.FailWithError(AL_warning, AP_close_notify);
+ }
+ /*
+ * If it is just a warning, we continue.
+ */
+ }
+ }
+
+ }
+
+ /**
+ * This method is called, when a change cipher spec message is received.
+ *
+ * @throws IOException If the message has an invalid content or the
+ * handshake is not in the correct state.
+ */
+ private void processChangeCipherSpec()
+ {
+ while (changeCipherSpecQueue.Available > 0)
+ {
+ /*
+ * A change cipher spec message is only one byte with the value 1.
+ */
+ byte[] b = new byte[1];
+ changeCipherSpecQueue.Read(b, 0, 1, 0);
+ changeCipherSpecQueue.RemoveData(1);
+ if (b[0] != 1)
+ {
+ /*
+ * This should never happen.
+ */
+ this.FailWithError(AL_fatal, AP_unexpected_message);
+
+ }
+ else
+ {
+ /*
+ * Check if we are in the correct connection state.
+ */
+ if (this.connection_state == CS_CLIENT_FINISHED_SEND)
+ {
+ rs.readSuite = rs.writeSuite;
+ this.connection_state = CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED;
+ }
+ else
+ {
+ /*
+ * We are not in the correct connection state.
+ */
+ this.FailWithError(AL_fatal, AP_handshake_failure);
+ }
+
+ }
+ }
+ }
+
+ private void sendClientCertificate()
+ {
+ /*
+ * just write back the "no client certificate" message
+ * see also gnutls, auth_cert.c:643 (0B 00 00 03 00 00 00)
+ */
+ MemoryStream bos = new MemoryStream();
+ TlsUtilities.WriteUint8(HP_CERTIFICATE, bos);
+ TlsUtilities.WriteUint24(3, bos);
+ TlsUtilities.WriteUint24(0, bos);
+ byte[] message = bos.ToArray();
+
+ rs.WriteMessage((short)RL_HANDSHAKE, message, 0, message.Length);
+ }
+
+ /// Connects to the remote system.
+ /// Will be used when a certificate is received to verify
+ /// that this certificate is accepted by the client.
+ /// If handshake was not successful
+ public virtual void Connect(
+ ICertificateVerifyer verifyer)
+ {
+ this.verifyer = verifyer;
+
+ /*
+ * Send Client hello
+ *
+ * First, generate some random data.
+ */
+ this.clientRandom = new byte[32];
+
+ /*
+ * TLS 1.0 requires a unix-timestamp in the first 4 bytes
+ */
+ int t = (int)(DateTimeUtilities.CurrentUnixMs() / 1000L);
+ this.clientRandom[0] = (byte)(t >> 24);
+ this.clientRandom[1] = (byte)(t >> 16);
+ this.clientRandom[2] = (byte)(t >> 8);
+ this.clientRandom[3] = (byte)t;
+
+ random.NextBytes(this.clientRandom, 4, 28);
+
+
+ MemoryStream outStr = new MemoryStream();
+ TlsUtilities.WriteVersion(outStr);
+ outStr.Write(this.clientRandom, 0, this.clientRandom.Length);
+
+ /*
+ * Length of Session id
+ */
+ TlsUtilities.WriteUint8((short)0, outStr);
+
+ /*
+ * Cipher suites
+ */
+ TlsCipherSuiteManager.WriteCipherSuites(outStr);
+
+ /*
+ * Compression methods, just the null method.
+ */
+ byte[] compressionMethods = new byte[]{0x00};
+ TlsUtilities.WriteUint8((short)compressionMethods.Length, outStr);
+ outStr.Write(compressionMethods,0, compressionMethods.Length);
+
+
+ MemoryStream bos = new MemoryStream();
+ TlsUtilities.WriteUint8(HP_CLIENT_HELLO, bos);
+ TlsUtilities.WriteUint24((int) outStr.Length, bos);
+ byte[] outBytes = outStr.ToArray();
+ bos.Write(outBytes, 0, outBytes.Length);
+ byte[] message = bos.ToArray();
+ rs.WriteMessage(RL_HANDSHAKE, message, 0, message.Length);
+ connection_state = CS_CLIENT_HELLO_SEND;
+
+ /*
+ * We will now read data, until we have completed the handshake.
+ */
+ while (connection_state != CS_DONE)
+ {
+ rs.ReadData();
+ }
+
+ this.tlsInputStream = new TlsInputStream(this);
+ this.tlsOutputStream = new TlsOuputStream(this);
+ }
+
+ /**
+ * Read data from the network. The method will return immed, if there is
+ * still some data left in the buffer, or block untill some application
+ * data has been read from the network.
+ *
+ * @param buf The buffer where the data will be copied to.
+ * @param offset The position where the data will be placed in the buffer.
+ * @param len The maximum number of bytes to read.
+ * @return The number of bytes read.
+ * @throws IOException If something goes wrong during reading data.
+ */
+ internal int ReadApplicationData(byte[] buf, int offset, int len)
+ {
+ while (applicationDataQueue.Available == 0)
+ {
+ /*
+ * We need to read some data.
+ */
+ if (this.failedWithError)
+ {
+ /*
+ * Something went terribly wrong, we should throw an IOException
+ */
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+ if (this.closed)
+ {
+ /*
+ * Connection has been closed, there is no more data to read.
+ */
+ return 0;
+ }
+
+ try
+ {
+ rs.ReadData();
+ }
+ catch (IOException e)
+ {
+ if (!this.closed)
+ {
+ this.FailWithError(AL_fatal, AP_internal_error);
+ }
+ throw e;
+ }
+ catch (Exception e)
+ {
+ if (!this.closed)
+ {
+ this.FailWithError(AL_fatal, AP_internal_error);
+ }
+ throw e;
+ }
+ }
+ len = System.Math.Min(len, applicationDataQueue.Available);
+ applicationDataQueue.Read(buf, offset, len, 0);
+ applicationDataQueue.RemoveData(len);
+ return len;
+ }
+
+ /**
+ * Send some application data to the remote system.
+ *
+ * The method will handle fragmentation internally.
+ *
+ * @param buf The buffer with the data.
+ * @param offset The position in the buffer where the data is placed.
+ * @param len The length of the data.
+ * @throws IOException If something goes wrong during sending.
+ */
+ internal void WriteData(byte[] buf, int offset, int len)
+ {
+ if (this.failedWithError)
+ {
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+ if (this.closed)
+ {
+ throw new IOException("Sorry, connection has been closed, you cannot write more data");
+ }
+
+ /*
+ * Protect against known IV attack!
+ *
+ * DO NOT REMOVE THIS LINE, EXCEPT YOU KNOW EXACTLY WHAT
+ * YOU ARE DOING HERE.
+ */
+ rs.WriteMessage(RL_APPLICATION_DATA, emptybuf, 0, 0);
+
+ do
+ {
+ /*
+ * We are only allowed to write fragments up to 2^14 bytes.
+ */
+ int toWrite = System.Math.Min(len, 1 << 14);
+
+ try
+ {
+ rs.WriteMessage(RL_APPLICATION_DATA, buf, offset, toWrite);
+ }
+ catch (IOException e)
+ {
+ if (!closed)
+ {
+ this.FailWithError(AL_fatal, AP_internal_error);
+ }
+ throw e;
+ }
+ catch (Exception e)
+ {
+ if (!closed)
+ {
+ this.FailWithError(AL_fatal, AP_internal_error);
+ }
+ throw e;
+ }
+
+
+ offset += toWrite;
+ len -= toWrite;
+ }
+ while (len > 0);
+
+ }
+
+ [Obsolete("Use 'OutputStream' property instead")]
+ public TlsOuputStream TlsOuputStream
+ {
+ get { return this.tlsOutputStream; }
+ }
+
+ /// A Stream which can be used to send data.
+ public virtual Stream OutputStream
+ {
+ get { return this.tlsOutputStream; }
+ }
+
+ [Obsolete("Use 'InputStream' property instead")]
+ public TlsInputStream TlsInputStream
+ {
+ get { return this.tlsInputStream; }
+ }
+
+ /// A Stream which can be used to read data.
+ public virtual Stream InputStream
+ {
+ get { return this.tlsInputStream; }
+ }
+
+ /**
+ * Terminate this connection whith an alert.
+ *
+ * Can be used for normal closure too.
+ *
+ * @param alertLevel The level of the alert, an be AL_fatal or AL_warning.
+ * @param alertDescription The exact alert message.
+ * @throws IOException If alert was fatal.
+ */
+ internal void FailWithError(
+ short alertLevel,
+ short alertDescription)
+ {
+ /*
+ * Check if the connection is still open.
+ */
+ if (!closed)
+ {
+ /*
+ * Prepare the message
+ */
+ byte[] error = new byte[2];
+ error[0] = (byte)alertLevel;
+ error[1] = (byte)alertDescription;
+ this.closed = true;
+
+ if (alertLevel == AL_fatal)
+ {
+ /*
+ * This is a fatal message.
+ */
+ this.failedWithError = true;
+ }
+ rs.WriteMessage(RL_ALERT, error, 0, 2);
+ rs.Close();
+ if (alertLevel == AL_fatal)
+ {
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+
+ }
+ else
+ {
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+ }
+
+ /// Closes this connection
+ /// If something goes wrong during closing.
+ public virtual void Close()
+ {
+ if (!closed)
+ {
+ this.FailWithError((short)1, (short)0);
+ }
+ }
+
+ /**
+ * Make sure the Stream is now empty. Fail otherwise.
+ *
+ * @param is The Stream to check.
+ * @throws IOException If is is not empty.
+ */
+ internal void AssertEmpty(
+ MemoryStream inStr)
+ {
+// if (inStr.available() > 0)
+ if (inStr.Position < inStr.Length)
+ {
+ this.FailWithError(AL_fatal, AP_decode_error);
+ }
+ }
+
+ internal void Flush()
+ {
+ rs.Flush();
+ }
+ }
+}
diff --git a/src/core/srcbc/openpgp/PgpKeyRingGenerator.cs b/src/core/srcbc/openpgp/PgpKeyRingGenerator.cs
index a423762..1f8deea 100644
--- a/src/core/srcbc/openpgp/PgpKeyRingGenerator.cs
+++ b/src/core/srcbc/openpgp/PgpKeyRingGenerator.cs
@@ -1,166 +1,166 @@
-using System;
-using System.Collections;
-
-using Org.BouncyCastle.Security;
-
-namespace Org.BouncyCastle.Bcpg.OpenPgp
-{
- ///
- /// Generator for a PGP master and subkey ring.
- /// This class will generate both the secret and public key rings
- ///
- public class PgpKeyRingGenerator
- {
- private ArrayList keys = new ArrayList();
- private string id;
- private SymmetricKeyAlgorithmTag encAlgorithm;
- private int certificationLevel;
- private char[] passPhrase;
- private bool useSha1;
- private PgpKeyPair masterKey;
- private PgpSignatureSubpacketVector hashedPacketVector;
- private PgpSignatureSubpacketVector unhashedPacketVector;
- private SecureRandom rand;
-
- ///
- /// Create a new key ring generator using old style checksumming. It is recommended to use
- /// SHA1 checksumming where possible.
- ///
- /// The certification level for keys on this ring.
- /// The master key pair.
- /// The id to be associated with the ring.
- /// The algorithm to be used to protect secret keys.
- /// The passPhrase to be used to protect secret keys.
- /// Packets to be included in the certification hash.
- /// Packets to be attached unhashed to the certification.
- /// input secured random.
- public PgpKeyRingGenerator(
- int certificationLevel,
- PgpKeyPair masterKey,
- string id,
- SymmetricKeyAlgorithmTag encAlgorithm,
- char[] passPhrase,
- PgpSignatureSubpacketVector hashedPackets,
- PgpSignatureSubpacketVector unhashedPackets,
- SecureRandom rand)
- : this(certificationLevel, masterKey, id, encAlgorithm, passPhrase, false, hashedPackets, unhashedPackets, rand)
- {
- }
-
- ///
- /// Create a new key ring generator.
- ///
- /// The certification level for keys on this ring.
- /// The master key pair.
- /// The id to be associated with the ring.
- /// The algorithm to be used to protect secret keys.
- /// The passPhrase to be used to protect secret keys.
- /// Checksum the secret keys with SHA1 rather than the older 16 bit checksum.
- /// Packets to be included in the certification hash.
- /// Packets to be attached unhashed to the certification.
- /// input secured random.
- public PgpKeyRingGenerator(
- int certificationLevel,
- PgpKeyPair masterKey,
- string id,
- SymmetricKeyAlgorithmTag encAlgorithm,
- char[] passPhrase,
- bool useSha1,
- PgpSignatureSubpacketVector hashedPackets,
- PgpSignatureSubpacketVector unhashedPackets,
- SecureRandom rand)
- {
- this.certificationLevel = certificationLevel;
- this.masterKey = masterKey;
- this.id = id;
- this.encAlgorithm = encAlgorithm;
- this.passPhrase = passPhrase;
- this.useSha1 = useSha1;
- this.hashedPacketVector = hashedPackets;
- this.unhashedPacketVector = unhashedPackets;
- this.rand = rand;
-
- keys.Add(new PgpSecretKey(certificationLevel, masterKey, id, encAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand));
- }
-
- /// Add a subkey to the key ring to be generated with default certification.
- public void AddSubKey(
- PgpKeyPair keyPair)
- {
- AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector);
- }
-
- ///
- /// Add a subkey with specific hashed and unhashed packets associated with it and
- /// default certification.
- ///
- /// Public/private key pair.
- /// Hashed packet values to be included in certification.
- /// Unhashed packets values to be included in certification.
- ///
- public void AddSubKey(
- PgpKeyPair keyPair,
- PgpSignatureSubpacketVector hashedPackets,
- PgpSignatureSubpacketVector unhashedPackets)
- {
- try
- {
- PgpSignatureGenerator sGen = new PgpSignatureGenerator(
- masterKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
-
- //
- // Generate the certification
- //
- sGen.InitSign(PgpSignature.SubkeyBinding, masterKey.PrivateKey);
-
- sGen.SetHashedSubpackets(hashedPackets);
- sGen.SetUnhashedSubpackets(unhashedPackets);
-
- ArrayList subSigs = new ArrayList();
-
- subSigs.Add(sGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey));
-
- keys.Add(new PgpSecretKey(keyPair, null, subSigs, encAlgorithm, passPhrase, useSha1, rand));
- }
- catch (PgpException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new PgpException("exception adding subkey: ", e);
- }
- }
-
- /// Return the secret key ring.
- public PgpSecretKeyRing GenerateSecretKeyRing()
- {
- return new PgpSecretKeyRing(keys);
- }
-
- /// Return the public key ring that corresponds to the secret key ring.
- public PgpPublicKeyRing GeneratePublicKeyRing()
- {
- ArrayList pubKeys = new ArrayList();
-
- IEnumerator enumerator = keys.GetEnumerator();
- enumerator.MoveNext();
-
- PgpSecretKey pgpSecretKey = (PgpSecretKey) enumerator.Current;
- pubKeys.Add(pgpSecretKey.PublicKey);
-
- while (enumerator.MoveNext())
- {
- pgpSecretKey = (PgpSecretKey) enumerator.Current;
-
- PgpPublicKey k = new PgpPublicKey(pgpSecretKey.PublicKey);
- k.publicPk = new PublicSubkeyPacket(
- k.Algorithm, k.CreationTime, k.publicPk.Key);
-
- pubKeys.Add(k);
- }
-
- return new PgpPublicKeyRing(pubKeys);
- }
- }
-}
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+ ///
+ /// Generator for a PGP master and subkey ring.
+ /// This class will generate both the secret and public key rings
+ ///
+ public class PgpKeyRingGenerator
+ {
+ private ArrayList keys = new ArrayList();
+ private string id;
+ private SymmetricKeyAlgorithmTag encAlgorithm;
+ private int certificationLevel;
+ private char[] passPhrase;
+ private bool useSha1;
+ private PgpKeyPair masterKey;
+ private PgpSignatureSubpacketVector hashedPacketVector;
+ private PgpSignatureSubpacketVector unhashedPacketVector;
+ private SecureRandom rand;
+
+ ///
+ /// Create a new key ring generator using old style checksumming. It is recommended to use
+ /// SHA1 checksumming where possible.
+ ///
+ /// The certification level for keys on this ring.
+ /// The master key pair.
+ /// The id to be associated with the ring.
+ /// The algorithm to be used to protect secret keys.
+ /// The passPhrase to be used to protect secret keys.
+ /// Packets to be included in the certification hash.
+ /// Packets to be attached unhashed to the certification.
+ /// input secured random.
+ public PgpKeyRingGenerator(
+ int certificationLevel,
+ PgpKeyPair masterKey,
+ string id,
+ SymmetricKeyAlgorithmTag encAlgorithm,
+ char[] passPhrase,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ SecureRandom rand)
+ : this(certificationLevel, masterKey, id, encAlgorithm, passPhrase, false, hashedPackets, unhashedPackets, rand)
+ {
+ }
+
+ ///
+ /// Create a new key ring generator.
+ ///
+ /// The certification level for keys on this ring.
+ /// The master key pair.
+ /// The id to be associated with the ring.
+ /// The algorithm to be used to protect secret keys.
+ /// The passPhrase to be used to protect secret keys.
+ /// Checksum the secret keys with SHA1 rather than the older 16 bit checksum.
+ /// Packets to be included in the certification hash.
+ /// Packets to be attached unhashed to the certification.
+ /// input secured random.
+ public PgpKeyRingGenerator(
+ int certificationLevel,
+ PgpKeyPair masterKey,
+ string id,
+ SymmetricKeyAlgorithmTag encAlgorithm,
+ char[] passPhrase,
+ bool useSha1,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ SecureRandom rand)
+ {
+ this.certificationLevel = certificationLevel;
+ this.masterKey = masterKey;
+ this.id = id;
+ this.encAlgorithm = encAlgorithm;
+ this.passPhrase = passPhrase;
+ this.useSha1 = useSha1;
+ this.hashedPacketVector = hashedPackets;
+ this.unhashedPacketVector = unhashedPackets;
+ this.rand = rand;
+
+ keys.Add(new PgpSecretKey(certificationLevel, masterKey, id, encAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand));
+ }
+
+ /// Add a subkey to the key ring to be generated with default certification.
+ public void AddSubKey(
+ PgpKeyPair keyPair)
+ {
+ AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector);
+ }
+
+ ///
+ /// Add a subkey with specific hashed and unhashed packets associated with it and
+ /// default certification.
+ ///
+ /// Public/private key pair.
+ /// Hashed packet values to be included in certification.
+ /// Unhashed packets values to be included in certification.
+ ///
+ public void AddSubKey(
+ PgpKeyPair keyPair,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets)
+ {
+ try
+ {
+ PgpSignatureGenerator sGen = new PgpSignatureGenerator(
+ masterKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
+
+ //
+ // Generate the certification
+ //
+ sGen.InitSign(PgpSignature.SubkeyBinding, masterKey.PrivateKey);
+
+ sGen.SetHashedSubpackets(hashedPackets);
+ sGen.SetUnhashedSubpackets(unhashedPackets);
+
+ ArrayList subSigs = new ArrayList();
+
+ subSigs.Add(sGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey));
+
+ keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, subSigs), encAlgorithm, passPhrase, useSha1, rand));
+ }
+ catch (PgpException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("exception adding subkey: ", e);
+ }
+ }
+
+ /// Return the secret key ring.
+ public PgpSecretKeyRing GenerateSecretKeyRing()
+ {
+ return new PgpSecretKeyRing(keys);
+ }
+
+ /// Return the public key ring that corresponds to the secret key ring.
+ public PgpPublicKeyRing GeneratePublicKeyRing()
+ {
+ ArrayList pubKeys = new ArrayList();
+
+ IEnumerator enumerator = keys.GetEnumerator();
+ enumerator.MoveNext();
+
+ PgpSecretKey pgpSecretKey = (PgpSecretKey) enumerator.Current;
+ pubKeys.Add(pgpSecretKey.PublicKey);
+
+ while (enumerator.MoveNext())
+ {
+ pgpSecretKey = (PgpSecretKey) enumerator.Current;
+
+ PgpPublicKey k = new PgpPublicKey(pgpSecretKey.PublicKey);
+ k.publicPk = new PublicSubkeyPacket(
+ k.Algorithm, k.CreationTime, k.publicPk.Key);
+
+ pubKeys.Add(k);
+ }
+
+ return new PgpPublicKeyRing(pubKeys);
+ }
+ }
+}
diff --git a/src/core/srcbc/openpgp/PgpOnePassSignature.cs b/src/core/srcbc/openpgp/PgpOnePassSignature.cs
index c8c4128..68fc599 100644
--- a/src/core/srcbc/openpgp/PgpOnePassSignature.cs
+++ b/src/core/srcbc/openpgp/PgpOnePassSignature.cs
@@ -1,179 +1,179 @@
-using System;
-using System.IO;
-
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Security;
-
-namespace Org.BouncyCastle.Bcpg.OpenPgp
-{
- /// A one pass signature object.
- public class PgpOnePassSignature
- {
- private OnePassSignaturePacket sigPack;
- private int signatureType;
- private ISigner sig;
- private byte lastb;
-
- internal PgpOnePassSignature(
- BcpgInputStream bcpgInput)
- : this((OnePassSignaturePacket) bcpgInput.ReadPacket())
- {
- }
-
- internal PgpOnePassSignature(
- OnePassSignaturePacket sigPack)
- {
- this.sigPack = sigPack;
- this.signatureType = sigPack.SignatureType;
-
- try
- {
- this.sig = SignerUtilities.GetSigner(
- PgpUtilities.GetSignatureName(sigPack.KeyAlgorithm, sigPack.HashAlgorithm));
- }
- catch (Exception e)
- {
- throw new PgpException("can't set up signature object.", e);
- }
- }
-
- /// Initialise the signature object for verification.
- public void InitVerify(
- PgpPublicKey pubKey)
- {
- lastb = 0;
-
- try
- {
- sig.Init(false, pubKey.GetKey());
- }
- catch (InvalidKeyException e)
- {
- throw new PgpException("invalid key.", e);
- }
- }
-
- public void Update(
- byte b)
- {
- if (signatureType == PgpSignature.CanonicalTextDocument)
- {
- doCanonicalUpdateByte(b);
- }
- else
- {
- sig.Update(b);
- }
- }
-
- private void doCanonicalUpdateByte(
- byte b)
- {
- if (b == '\r')
- {
- doUpdateCRLF();
- }
- else if (b == '\n')
- {
- if (lastb != '\r')
- {
- doUpdateCRLF();
- }
- }
- else
- {
- sig.Update(b);
- }
-
- lastb = b;
- }
-
- private void doUpdateCRLF()
- {
- sig.Update((byte)'\r');
- sig.Update((byte)'\n');
- }
-
- public void Update(
- byte[] bytes)
- {
- if (signatureType == PgpSignature.CanonicalTextDocument)
- {
- for (int i = 0; i != bytes.Length; i++)
- {
- doCanonicalUpdateByte(bytes[i]);
- }
- }
- else
- {
- sig.BlockUpdate(bytes, 0, bytes.Length);
- }
- }
-
- public void Update(
- byte[] bytes,
- int off,
- int length)
- {
- if (signatureType == PgpSignature.CanonicalTextDocument)
- {
- int finish = off + length;
-
- for (int i = off; i != finish; i++)
- {
- doCanonicalUpdateByte(bytes[i]);
- }
- }
- else
- {
- sig.BlockUpdate(bytes, off, length);
- }
- }
-
- /// Verify the calculated signature against the passed in PgpSignature.
- public bool Verify(
- PgpSignature pgpSig)
- {
- byte[] trailer = pgpSig.GetSignatureTrailer();
-
- sig.BlockUpdate(trailer, 0, trailer.Length);
-
- return sig.VerifySignature(pgpSig.GetSignature());
- }
-
- public long KeyId
- {
- get { return sigPack.KeyId; }
- }
-
- public int SignatureType
- {
- get { return sigPack.SignatureType; }
- }
-
- public HashAlgorithmTag HashAlgorithm
- {
- get { return sigPack.HashAlgorithm; }
- }
-
- public PublicKeyAlgorithmTag KeyAlgorithm
- {
- get { return sigPack.KeyAlgorithm; }
- }
-
- public byte[] GetEncoded()
- {
- MemoryStream bOut = new MemoryStream();
-
- Encode(bOut);
-
- return bOut.ToArray();
- }
-
- public void Encode(
- Stream outStr)
- {
- BcpgOutputStream.Wrap(outStr).WritePacket(sigPack);
- }
- }
-}
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+ /// A one pass signature object.
+ public class PgpOnePassSignature
+ {
+ private OnePassSignaturePacket sigPack;
+ private int signatureType;
+ private ISigner sig;
+ private byte lastb;
+
+ internal PgpOnePassSignature(
+ BcpgInputStream bcpgInput)
+ : this((OnePassSignaturePacket) bcpgInput.ReadPacket())
+ {
+ }
+
+ internal PgpOnePassSignature(
+ OnePassSignaturePacket sigPack)
+ {
+ this.sigPack = sigPack;
+ this.signatureType = sigPack.SignatureType;
+ }
+
+ /// Initialise the signature object for verification.
+ public void InitVerify(
+ PgpPublicKey pubKey)
+ {
+ lastb = 0;
+
+ try
+ {
+ sig = SignerUtilities.GetSigner(
+ PgpUtilities.GetSignatureName(sigPack.KeyAlgorithm, sigPack.HashAlgorithm));
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("can't set up signature object.", e);
+ }
+
+ try
+ {
+ sig.Init(false, pubKey.GetKey());
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new PgpException("invalid key.", e);
+ }
+ }
+
+ public void Update(
+ byte b)
+ {
+ if (signatureType == PgpSignature.CanonicalTextDocument)
+ {
+ doCanonicalUpdateByte(b);
+ }
+ else
+ {
+ sig.Update(b);
+ }
+ }
+
+ private void doCanonicalUpdateByte(
+ byte b)
+ {
+ if (b == '\r')
+ {
+ doUpdateCRLF();
+ }
+ else if (b == '\n')
+ {
+ if (lastb != '\r')
+ {
+ doUpdateCRLF();
+ }
+ }
+ else
+ {
+ sig.Update(b);
+ }
+
+ lastb = b;
+ }
+
+ private void doUpdateCRLF()
+ {
+ sig.Update((byte)'\r');
+ sig.Update((byte)'\n');
+ }
+
+ public void Update(
+ byte[] bytes)
+ {
+ if (signatureType == PgpSignature.CanonicalTextDocument)
+ {
+ for (int i = 0; i != bytes.Length; i++)
+ {
+ doCanonicalUpdateByte(bytes[i]);
+ }
+ }
+ else
+ {
+ sig.BlockUpdate(bytes, 0, bytes.Length);
+ }
+ }
+
+ public void Update(
+ byte[] bytes,
+ int off,
+ int length)
+ {
+ if (signatureType == PgpSignature.CanonicalTextDocument)
+ {
+ int finish = off + length;
+
+ for (int i = off; i != finish; i++)
+ {
+ doCanonicalUpdateByte(bytes[i]);
+ }
+ }
+ else
+ {
+ sig.BlockUpdate(bytes, off, length);
+ }
+ }
+
+ /// Verify the calculated signature against the passed in PgpSignature.
+ public bool Verify(
+ PgpSignature pgpSig)
+ {
+ byte[] trailer = pgpSig.GetSignatureTrailer();
+
+ sig.BlockUpdate(trailer, 0, trailer.Length);
+
+ return sig.VerifySignature(pgpSig.GetSignature());
+ }
+
+ public long KeyId
+ {
+ get { return sigPack.KeyId; }
+ }
+
+ public int SignatureType
+ {
+ get { return sigPack.SignatureType; }
+ }
+
+ public HashAlgorithmTag HashAlgorithm
+ {
+ get { return sigPack.HashAlgorithm; }
+ }
+
+ public PublicKeyAlgorithmTag KeyAlgorithm
+ {
+ get { return sigPack.KeyAlgorithm; }
+ }
+
+ public byte[] GetEncoded()
+ {
+ MemoryStream bOut = new MemoryStream();
+
+ Encode(bOut);
+
+ return bOut.ToArray();
+ }
+
+ public void Encode(
+ Stream outStr)
+ {
+ BcpgOutputStream.Wrap(outStr).WritePacket(sigPack);
+ }
+ }
+}
diff --git a/src/core/srcbc/openpgp/PgpPublicKey.cs b/src/core/srcbc/openpgp/PgpPublicKey.cs
index 96220e6..503ec4d 100644
--- a/src/core/srcbc/openpgp/PgpPublicKey.cs
+++ b/src/core/srcbc/openpgp/PgpPublicKey.cs
@@ -1,842 +1,890 @@
-using System;
-using System.Collections;
-using System.IO;
-
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.IO;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Utilities.Collections;
-
-namespace Org.BouncyCastle.Bcpg.OpenPgp
-{
- /// General class to handle a PGP public key object.
- public class PgpPublicKey
- {
- private static readonly int[] MasterKeyCertificationTypes = new int[]
- {
- PgpSignature.PositiveCertification,
- PgpSignature.CasualCertification,
- PgpSignature.NoCertification,
- PgpSignature.DefaultCertification
- };
-
- private long keyId;
- private byte[] fingerprint;
- private int keyStrength;
-
- internal PublicKeyPacket publicPk;
- private TrustPacket trustPk;
- private ArrayList keySigs = new ArrayList();
- private ArrayList ids = new ArrayList();
- private ArrayList idTrusts = new ArrayList();
- private ArrayList idSigs = new ArrayList();
- private ArrayList subSigs;
-
- private void Init()
- {
- IBcpgKey key = publicPk.Key;
-
- if (publicPk.Version <= 3)
- {
- RsaPublicBcpgKey rK = (RsaPublicBcpgKey) key;
-
- this.keyId = rK.Modulus.LongValue;
-
- try
- {
- IDigest digest = DigestUtilities.GetDigest("MD5");
-
- byte[] bytes = rK.Modulus.ToByteArrayUnsigned();
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- bytes = rK.PublicExponent.ToByteArrayUnsigned();
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- this.fingerprint = DigestUtilities.DoFinal(digest);
- }
- //catch (NoSuchAlgorithmException)
- catch (Exception)
- {
- throw new IOException("can't find MD5");
- }
-
- this.keyStrength = rK.Modulus.BitLength;
- }
- else
- {
- byte[] kBytes = publicPk.GetEncodedContents();
-
- try
- {
- IDigest digest = DigestUtilities.GetDigest("SHA1");
-
- digest.Update(0x99);
- digest.Update((byte)(kBytes.Length >> 8));
- digest.Update((byte)kBytes.Length);
- digest.BlockUpdate(kBytes, 0, kBytes.Length);
- this.fingerprint = DigestUtilities.DoFinal(digest);
- }
- //catch (NoSuchAlgorithmException)
- catch (Exception)
- {
- throw new IOException("can't find SHA1");
- }
-
- this.keyId = (long)(((ulong)fingerprint[fingerprint.Length - 8] << 56)
- | ((ulong)fingerprint[fingerprint.Length - 7] << 48)
- | ((ulong)fingerprint[fingerprint.Length - 6] << 40)
- | ((ulong)fingerprint[fingerprint.Length - 5] << 32)
- | ((ulong)fingerprint[fingerprint.Length - 4] << 24)
- | ((ulong)fingerprint[fingerprint.Length - 3] << 16)
- | ((ulong)fingerprint[fingerprint.Length - 2] << 8)
- | (ulong)fingerprint[fingerprint.Length - 1]);
-
- if (key is RsaPublicBcpgKey)
- {
- this.keyStrength = ((RsaPublicBcpgKey)key).Modulus.BitLength;
- }
- else if (key is DsaPublicBcpgKey)
- {
- this.keyStrength = ((DsaPublicBcpgKey)key).P.BitLength;
- }
- else if (key is ElGamalPublicBcpgKey)
- {
- this.keyStrength = ((ElGamalPublicBcpgKey)key).P.BitLength;
- }
- }
- }
-
- ///
- /// Create a PgpPublicKey from the passed in lightweight one.
- ///
- ///
- /// Note: the time passed in affects the value of the key's keyId, so you probably only want
- /// to do this once for a lightweight key, or make sure you keep track of the time you used.
- ///
- /// Asymmetric algorithm type representing the public key.
- /// Actual public key to associate.
- /// Date of creation.
- /// If pubKey is not public.
- /// On key creation problem.
- public PgpPublicKey(
- PublicKeyAlgorithmTag algorithm,
- AsymmetricKeyParameter pubKey,
- DateTime time)
- {
- if (pubKey.IsPrivate)
- throw new ArgumentException("Expected a public key", "pubKey");
-
- IBcpgKey bcpgKey;
- if (pubKey is RsaKeyParameters)
- {
- RsaKeyParameters rK = (RsaKeyParameters) pubKey;
-
- bcpgKey = new RsaPublicBcpgKey(rK.Modulus, rK.Exponent);
- }
- else if (pubKey is DsaPublicKeyParameters)
- {
- DsaPublicKeyParameters dK = (DsaPublicKeyParameters) pubKey;
- DsaParameters dP = dK.Parameters;
-
- bcpgKey = new DsaPublicBcpgKey(dP.P, dP.Q, dP.G, dK.Y);
- }
- else if (pubKey is ElGamalPublicKeyParameters)
- {
- ElGamalPublicKeyParameters eK = (ElGamalPublicKeyParameters) pubKey;
- ElGamalParameters eS = eK.Parameters;
-
- bcpgKey = new ElGamalPublicBcpgKey(eS.P, eS.G, eK.Y);
- }
- else
- {
- throw new PgpException("unknown key class");
- }
-
- this.publicPk = new PublicKeyPacket(algorithm, time, bcpgKey);
- this.ids = new ArrayList();
- this.idSigs = new ArrayList();
-
- try
- {
- Init();
- }
- catch (IOException e)
- {
- throw new PgpException("exception calculating keyId", e);
- }
- }
-
- /// Constructor for a sub-key.
- internal PgpPublicKey(
- PublicKeyPacket publicPk,
- TrustPacket trustPk,
- ArrayList sigs)
- {
- this.publicPk = publicPk;
- this.trustPk = trustPk;
- this.subSigs = sigs;
-
- Init();
- }
-
- internal PgpPublicKey(
- PgpPublicKey key,
- TrustPacket trust,
- ArrayList subSigs)
- {
- this.publicPk = key.publicPk;
- this.trustPk = trust;
- this.subSigs = subSigs;
-
- this.fingerprint = key.fingerprint;
- this.keyId = key.keyId;
- this.keyStrength = key.keyStrength;
- }
-
- /// Copy constructor.
- /// The public key to copy.
- internal PgpPublicKey(
- PgpPublicKey pubKey)
- {
- this.publicPk = pubKey.publicPk;
-
- this.keySigs = new ArrayList(pubKey.keySigs);
- this.ids = new ArrayList(pubKey.ids);
- this.idTrusts = new ArrayList(pubKey.idTrusts);
- this.idSigs = new ArrayList(pubKey.idSigs.Count);
- for (int i = 0; i != pubKey.idSigs.Count; i++)
- {
- this.idSigs.Add(new ArrayList((ArrayList)pubKey.idSigs[i]));
- }
-
- if (pubKey.subSigs != null)
- {
- this.subSigs = new ArrayList(pubKey.subSigs.Count);
- for (int i = 0; i != pubKey.subSigs.Count; i++)
- {
- this.subSigs.Add(pubKey.subSigs[i]);
- }
- }
-
- this.fingerprint = pubKey.fingerprint;
- this.keyId = pubKey.keyId;
- this.keyStrength = pubKey.keyStrength;
- }
-
- internal PgpPublicKey(
- PublicKeyPacket publicPk,
- TrustPacket trustPk,
- ArrayList keySigs,
- ArrayList ids,
- ArrayList idTrusts,
- ArrayList idSigs)
- {
- this.publicPk = publicPk;
- this.trustPk = trustPk;
- this.keySigs = keySigs;
- this.ids = ids;
- this.idTrusts = idTrusts;
- this.idSigs = idSigs;
-
- Init();
- }
-
- internal PgpPublicKey(
- PublicKeyPacket publicPk,
- ArrayList ids,
- ArrayList idSigs)
- {
- this.publicPk = publicPk;
- this.ids = ids;
- this.idSigs = idSigs;
- Init();
- }
-
- /// The version of this key.
- public int Version
- {
- get { return publicPk.Version; }
- }
-
- /// The creation time of this key.
- public DateTime CreationTime
- {
- get { return publicPk.GetTime(); }
- }
-
- /// The number of valid days from creation time - zero means no expiry.
- public int ValidDays
- {
- get
- {
- if (publicPk.Version > 3)
- {
- return (int)(GetValidSeconds() / (24 * 60 * 60));
- }
-
- return publicPk.ValidDays;
- }
- }
-
- /// Return the trust data associated with the public key, if present.
- /// A byte array with trust data, null otherwise.
- public byte[] GetTrustData()
- {
- if (trustPk == null)
- {
- return null;
- }
-
- return trustPk.GetLevelAndTrustAmount();
- }
-
- /// The number of valid seconds from creation time - zero means no expiry.
- public long GetValidSeconds()
- {
- if (publicPk.Version > 3)
- {
- if (IsMasterKey)
- {
- for (int i = 0; i != MasterKeyCertificationTypes.Length; i++)
- {
- long seconds = GetExpirationTimeFromSig(true, MasterKeyCertificationTypes[i]);
-
- if (seconds >= 0)
- {
- return seconds;
- }
- }
- }
- else
- {
- long seconds = GetExpirationTimeFromSig(false, PgpSignature.SubkeyBinding);
-
- if (seconds >= 0)
- {
- return seconds;
- }
- }
-
- return 0;
- }
-
- return (long) publicPk.ValidDays * 24 * 60 * 60;
- }
-
- private long GetExpirationTimeFromSig(
- bool selfSigned,
- int signatureType)
- {
- foreach (PgpSignature sig in GetSignaturesOfType(signatureType))
- {
- if (!selfSigned || sig.KeyId == KeyId)
- {
- PgpSignatureSubpacketVector hashed = sig.GetHashedSubPackets();
-
- if (hashed != null)
- {
- return hashed.GetKeyExpirationTime();
- }
-
- return 0;
- }
- }
-
- return -1;
- }
-
- /// The keyId associated with the public key.
- public long KeyId
- {
- get { return keyId; }
- }
-
- /// The fingerprint of the key
- public byte[] GetFingerprint()
- {
- return (byte[]) fingerprint.Clone();
- }
-
- ///
- /// Check if this key has an algorithm type that makes it suitable to use for encryption.
- ///
- ///
- /// Note: with version 4 keys KeyFlags subpackets should also be considered when present for
- /// determining the preferred use of the key.
- ///
- ///
- /// true if this key algorithm is suitable for encryption.
- ///
- public bool IsEncryptionKey
- {
- get
- {
- switch (publicPk.Algorithm)
- {
- case PublicKeyAlgorithmTag.ElGamalEncrypt:
- case PublicKeyAlgorithmTag.ElGamalGeneral:
- case PublicKeyAlgorithmTag.RsaEncrypt:
- case PublicKeyAlgorithmTag.RsaGeneral:
- return true;
- default:
- return false;
- }
- }
- }
-
- /// True, if this is a master key.
- public bool IsMasterKey
- {
- get { return subSigs == null; }
- }
-
- /// The algorithm code associated with the public key.
- public PublicKeyAlgorithmTag Algorithm
- {
- get { return publicPk.Algorithm; }
- }
-
- /// The strength of the key in bits.
- public int BitStrength
- {
- get { return keyStrength; }
- }
-
- /// The public key contained in the object.
- /// A lightweight public key.
- /// If the key algorithm is not recognised.
- public AsymmetricKeyParameter GetKey()
- {
- try
- {
- switch (publicPk.Algorithm)
- {
- case PublicKeyAlgorithmTag.RsaEncrypt:
- case PublicKeyAlgorithmTag.RsaGeneral:
- case PublicKeyAlgorithmTag.RsaSign:
- RsaPublicBcpgKey rsaK = (RsaPublicBcpgKey) publicPk.Key;
- return new RsaKeyParameters(false, rsaK.Modulus, rsaK.PublicExponent);
- case PublicKeyAlgorithmTag.Dsa:
- DsaPublicBcpgKey dsaK = (DsaPublicBcpgKey) publicPk.Key;
- return new DsaPublicKeyParameters(dsaK.Y, new DsaParameters(dsaK.P, dsaK.Q, dsaK.G));
- case PublicKeyAlgorithmTag.ElGamalEncrypt:
- case PublicKeyAlgorithmTag.ElGamalGeneral:
- ElGamalPublicBcpgKey elK = (ElGamalPublicBcpgKey) publicPk.Key;
- return new ElGamalPublicKeyParameters(elK.Y, new ElGamalParameters(elK.P, elK.G));
- default:
- throw new PgpException("unknown public key algorithm encountered");
- }
- }
- catch (PgpException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new PgpException("exception constructing public key", e);
- }
- }
-
- /// Allows enumeration of any user IDs associated with the key.
- /// An IEnumerable of string objects.
- public IEnumerable GetUserIds()
- {
- ArrayList temp = new ArrayList();
-
- foreach (object o in ids)
- {
- if (o is string)
- {
- temp.Add(o);
- }
- }
-
- return new EnumerableProxy(temp);
- }
-
- /// Allows enumeration of any user attribute vectors associated with the key.
- /// An IEnumerable of PgpUserAttributeSubpacketVector objects.
- public IEnumerable GetUserAttributes()
- {
- ArrayList temp = new ArrayList();
-
- foreach (object o in ids)
- {
- if (o is PgpUserAttributeSubpacketVector)
- {
- temp.Add(o);
- }
- }
-
- return new EnumerableProxy(temp);
- }
-
- /// Allows enumeration of any signatures associated with the passed in id.
- /// The ID to be matched.
- /// An IEnumerable of PgpSignature objects.
- public IEnumerable GetSignaturesForId(
- string id)
- {
- if (id == null)
- throw new ArgumentNullException("id");
-
- for (int i = 0; i != ids.Count; i++)
- {
- if (id.Equals(ids[i]))
- {
- return new EnumerableProxy((ArrayList) idSigs[i]);
- }
- }
-
- return null;
- }
-
- /// Allows enumeration of signatures associated with the passed in user attributes.
- /// The vector of user attributes to be matched.
- /// An IEnumerable of PgpSignature objects.
- public IEnumerable GetSignaturesForUserAttribute(
- PgpUserAttributeSubpacketVector userAttributes)
- {
- for (int i = 0; i != ids.Count; i++)
- {
- if (userAttributes.Equals(ids[i]))
- {
- return new EnumerableProxy((ArrayList) idSigs[i]);
- }
- }
-
- return null;
- }
-
- /// Allows enumeration of signatures of the passed in type that are on this key.
- /// The type of the signature to be returned.
- /// An IEnumerable of PgpSignature objects.
- public IEnumerable GetSignaturesOfType(
- int signatureType)
- {
- ArrayList temp = new ArrayList();
-
- foreach (PgpSignature sig in GetSignatures())
- {
- if (sig.SignatureType == signatureType)
- {
- temp.Add(sig);
- }
- }
-
- return new EnumerableProxy(temp);
- }
-
- /// Allows enumeration of all signatures/certifications associated with this key.
- /// An IEnumerable with all signatures/certifications.
- public IEnumerable GetSignatures()
- {
- ArrayList sigs;
- if (subSigs != null)
- {
- sigs = subSigs;
- }
- else
- {
- sigs = new ArrayList(keySigs);
-
- foreach (ICollection extraSigs in idSigs)
- {
- sigs.AddRange(extraSigs);
- }
- }
-
- return new EnumerableProxy(sigs);
- }
-
- public byte[] GetEncoded()
- {
- MemoryStream bOut = new MemoryStream();
- Encode(bOut);
- return bOut.ToArray();
- }
-
- public void Encode(
- Stream outStr)
- {
- BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr);
-
- bcpgOut.WritePacket(publicPk);
- if (trustPk != null)
- {
- bcpgOut.WritePacket(trustPk);
- }
-
- if (subSigs == null) // not a sub-key
- {
- foreach (PgpSignature keySig in keySigs)
- {
- keySig.Encode(bcpgOut);
- }
-
- for (int i = 0; i != ids.Count; i++)
- {
- if (ids[i] is string)
- {
- string id = (string) ids[i];
-
- bcpgOut.WritePacket(new UserIdPacket(id));
- }
- else
- {
- PgpUserAttributeSubpacketVector v = (PgpUserAttributeSubpacketVector)ids[i];
- bcpgOut.WritePacket(new UserAttributePacket(v.ToSubpacketArray()));
- }
-
- if (idTrusts[i] != null)
- {
- bcpgOut.WritePacket((ContainedPacket)idTrusts[i]);
- }
-
- foreach (PgpSignature sig in (ArrayList) idSigs[i])
- {
- sig.Encode(bcpgOut);
- }
- }
- }
- else
- {
- foreach (PgpSignature subSig in subSigs)
- {
- subSig.Encode(bcpgOut);
- }
- }
- }
-
- /// Check whether this (sub)key has a revocation signature on it.
- /// True, if this (sub)key has been revoked.
- public bool IsRevoked()
- {
- int ns = 0;
- bool revoked = false;
- if (IsMasterKey) // Master key
- {
- while (!revoked && (ns < keySigs.Count))
- {
- if (((PgpSignature)keySigs[ns++]).SignatureType == PgpSignature.KeyRevocation)
- {
- revoked = true;
- }
- }
- }
- else // Sub-key
- {
- while (!revoked && (ns < subSigs.Count))
- {
- if (((PgpSignature)subSigs[ns++]).SignatureType == PgpSignature.SubkeyRevocation)
- {
- revoked = true;
- }
- }
- }
- return revoked;
- }
-
- /// Add a certification for an id to the given public key.
- /// The key the certification is to be added to.
- /// The ID the certification is associated with.
- /// The new certification.
- /// The re-certified key.
- public static PgpPublicKey AddCertification(
- PgpPublicKey key,
- string id,
- PgpSignature certification)
- {
- PgpPublicKey returnKey = new PgpPublicKey(key);
- ArrayList sigList = null;
-
- for (int i = 0; i != returnKey.ids.Count; i++)
- {
- if (id.Equals(returnKey.ids[i]))
- {
- sigList = (ArrayList) returnKey.idSigs[i];
- }
- }
-
- if (sigList != null)
- {
- sigList.Add(certification);
- }
- else
- {
- sigList = new ArrayList();
-
- sigList.Add(certification);
- returnKey.ids.Add(id);
- returnKey.idTrusts.Add(null);
- returnKey.idSigs.Add(sigList);
- }
-
- return returnKey;
- }
-
- /// Add a certification for the given UserAttributeSubpackets to the given public key.
- /// The key the certification is to be added to.
- /// The attributes the certification is associated with.
- /// The new certification.
- /// The re-certified key.
- public static PgpPublicKey AddCertification(
- PgpPublicKey key,
- PgpUserAttributeSubpacketVector userAttributes,
- PgpSignature certification)
- {
- PgpPublicKey returnKey = new PgpPublicKey(key);
- IList sigList = null;
-
- for (int i = 0; i != returnKey.ids.Count; i++)
- {
- if (userAttributes.Equals(returnKey.ids[i]))
- {
- sigList = (IList) returnKey.idSigs[i];
- }
- }
-
- if (sigList != null)
- {
- sigList.Add(certification);
- }
- else
- {
- sigList = new ArrayList();
- sigList.Add(certification);
- returnKey.ids.Add(userAttributes);
- returnKey.idTrusts.Add(null);
- returnKey.idSigs.Add(sigList);
- }
-
- return returnKey;
- }
-
- ///
- /// Remove any certifications associated with a user attribute subpacket on a key.
- ///
- /// The key the certifications are to be removed from.
- /// The attributes to be removed.
- ///
- /// The re-certified key, or null if the user attribute subpacket was not found on the key.
- ///
- public static PgpPublicKey RemoveCertification(
- PgpPublicKey key,
- PgpUserAttributeSubpacketVector userAttributes)
- {
- PgpPublicKey returnKey = new PgpPublicKey(key);
- bool found = false;
-
- for (int i = 0; i < returnKey.ids.Count; i++)
- {
- if (userAttributes.Equals(returnKey.ids[i]))
- {
- found = true;
- returnKey.ids.RemoveAt(i);
- returnKey.idTrusts.RemoveAt(i);
- returnKey.idSigs.RemoveAt(i);
- }
- }
-
- if (!found)
- {
- return null;
- }
-
- return returnKey;
- }
-
- /// Remove any certifications associated with a given ID on a key.
- /// The key the certifications are to be removed from.
- /// The ID that is to be removed.
- /// The re-certified key, or null if the ID was not found on the key.
- public static PgpPublicKey RemoveCertification(
- PgpPublicKey key,
- string id)
- {
- PgpPublicKey returnKey = new PgpPublicKey(key);
- bool found = false;
-
- for (int i = 0; i < returnKey.ids.Count; i++)
- {
- if (id.Equals(returnKey.ids[i]))
- {
- found = true;
- returnKey.ids.RemoveAt(i);
- returnKey.idTrusts.RemoveAt(i);
- returnKey.idSigs.RemoveAt(i);
- }
- }
-
- return found ? returnKey : null;
- }
-
- /// Remove any certifications associated with a given ID on a key.
- /// The key the certifications are to be removed from.
- /// The ID that the certfication is to be removed from.
- /// The certfication to be removed.
- /// The re-certified key, or null if the certification was not found.
- public static PgpPublicKey RemoveCertification(
- PgpPublicKey key,
- string id,
- PgpSignature certification)
- {
- PgpPublicKey returnKey = new PgpPublicKey(key);
- bool found = false;
-
- for (int i = 0; i < returnKey.ids.Count; i++)
- {
- if (id.Equals(returnKey.ids[i]))
- {
- ArrayList certs = (ArrayList) returnKey.idSigs[i];
- found = certs.Contains(certification);
-
- if (found)
- {
- certs.Remove(certification);
- }
- }
- }
-
- return found ? returnKey : null;
- }
-
- /// Add a revocation or some other key certification to a key.
- /// The key the revocation is to be added to.
- /// The key signature to be added.
- /// The new changed public key object.
- public static PgpPublicKey AddCertification(
- PgpPublicKey key,
- PgpSignature certification)
- {
- if (key.IsMasterKey)
- {
- if (certification.SignatureType == PgpSignature.SubkeyRevocation)
- {
- throw new ArgumentException("signature type incorrect for master key revocation.");
- }
- }
- else
- {
- if (certification.SignatureType == PgpSignature.KeyRevocation)
- {
- throw new ArgumentException("signature type incorrect for sub-key revocation.");
- }
- }
-
- PgpPublicKey returnKey = new PgpPublicKey(key);
-
- if (returnKey.subSigs != null)
- {
- returnKey.subSigs.Add(certification);
- }
- else
- {
- returnKey.keySigs.Add(certification);
- }
-
- return returnKey;
- }
- }
-}
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+ /// General class to handle a PGP public key object.
+ public class PgpPublicKey
+ {
+ private static readonly int[] MasterKeyCertificationTypes = new int[]
+ {
+ PgpSignature.PositiveCertification,
+ PgpSignature.CasualCertification,
+ PgpSignature.NoCertification,
+ PgpSignature.DefaultCertification
+ };
+
+ private long keyId;
+ private byte[] fingerprint;
+ private int keyStrength;
+
+ internal PublicKeyPacket publicPk;
+ internal TrustPacket trustPk;
+ internal ArrayList keySigs = new ArrayList();
+ internal ArrayList ids = new ArrayList();
+ internal ArrayList idTrusts = new ArrayList();
+ internal ArrayList idSigs = new ArrayList();
+ internal ArrayList subSigs;
+
+ private void Init()
+ {
+ IBcpgKey key = publicPk.Key;
+
+ if (publicPk.Version <= 3)
+ {
+ RsaPublicBcpgKey rK = (RsaPublicBcpgKey) key;
+
+ this.keyId = rK.Modulus.LongValue;
+
+ try
+ {
+ IDigest digest = DigestUtilities.GetDigest("MD5");
+
+ byte[] bytes = rK.Modulus.ToByteArrayUnsigned();
+ digest.BlockUpdate(bytes, 0, bytes.Length);
+
+ bytes = rK.PublicExponent.ToByteArrayUnsigned();
+ digest.BlockUpdate(bytes, 0, bytes.Length);
+
+ this.fingerprint = DigestUtilities.DoFinal(digest);
+ }
+ //catch (NoSuchAlgorithmException)
+ catch (Exception)
+ {
+ throw new IOException("can't find MD5");
+ }
+
+ this.keyStrength = rK.Modulus.BitLength;
+ }
+ else
+ {
+ byte[] kBytes = publicPk.GetEncodedContents();
+
+ try
+ {
+ IDigest digest = DigestUtilities.GetDigest("SHA1");
+
+ digest.Update(0x99);
+ digest.Update((byte)(kBytes.Length >> 8));
+ digest.Update((byte)kBytes.Length);
+ digest.BlockUpdate(kBytes, 0, kBytes.Length);
+ this.fingerprint = DigestUtilities.DoFinal(digest);
+ }
+ //catch (NoSuchAlgorithmException)
+ catch (Exception)
+ {
+ throw new IOException("can't find SHA1");
+ }
+
+ this.keyId = (long)(((ulong)fingerprint[fingerprint.Length - 8] << 56)
+ | ((ulong)fingerprint[fingerprint.Length - 7] << 48)
+ | ((ulong)fingerprint[fingerprint.Length - 6] << 40)
+ | ((ulong)fingerprint[fingerprint.Length - 5] << 32)
+ | ((ulong)fingerprint[fingerprint.Length - 4] << 24)
+ | ((ulong)fingerprint[fingerprint.Length - 3] << 16)
+ | ((ulong)fingerprint[fingerprint.Length - 2] << 8)
+ | (ulong)fingerprint[fingerprint.Length - 1]);
+
+ if (key is RsaPublicBcpgKey)
+ {
+ this.keyStrength = ((RsaPublicBcpgKey)key).Modulus.BitLength;
+ }
+ else if (key is DsaPublicBcpgKey)
+ {
+ this.keyStrength = ((DsaPublicBcpgKey)key).P.BitLength;
+ }
+ else if (key is ElGamalPublicBcpgKey)
+ {
+ this.keyStrength = ((ElGamalPublicBcpgKey)key).P.BitLength;
+ }
+ }
+ }
+
+ ///
+ /// Create a PgpPublicKey from the passed in lightweight one.
+ ///
+ ///
+ /// Note: the time passed in affects the value of the key's keyId, so you probably only want
+ /// to do this once for a lightweight key, or make sure you keep track of the time you used.
+ ///
+ /// Asymmetric algorithm type representing the public key.
+ /// Actual public key to associate.
+ /// Date of creation.
+ /// If pubKey is not public.
+ /// On key creation problem.
+ public PgpPublicKey(
+ PublicKeyAlgorithmTag algorithm,
+ AsymmetricKeyParameter pubKey,
+ DateTime time)
+ {
+ if (pubKey.IsPrivate)
+ throw new ArgumentException("Expected a public key", "pubKey");
+
+ IBcpgKey bcpgKey;
+ if (pubKey is RsaKeyParameters)
+ {
+ RsaKeyParameters rK = (RsaKeyParameters) pubKey;
+
+ bcpgKey = new RsaPublicBcpgKey(rK.Modulus, rK.Exponent);
+ }
+ else if (pubKey is DsaPublicKeyParameters)
+ {
+ DsaPublicKeyParameters dK = (DsaPublicKeyParameters) pubKey;
+ DsaParameters dP = dK.Parameters;
+
+ bcpgKey = new DsaPublicBcpgKey(dP.P, dP.Q, dP.G, dK.Y);
+ }
+ else if (pubKey is ElGamalPublicKeyParameters)
+ {
+ ElGamalPublicKeyParameters eK = (ElGamalPublicKeyParameters) pubKey;
+ ElGamalParameters eS = eK.Parameters;
+
+ bcpgKey = new ElGamalPublicBcpgKey(eS.P, eS.G, eK.Y);
+ }
+ else
+ {
+ throw new PgpException("unknown key class");
+ }
+
+ this.publicPk = new PublicKeyPacket(algorithm, time, bcpgKey);
+ this.ids = new ArrayList();
+ this.idSigs = new ArrayList();
+
+ try
+ {
+ Init();
+ }
+ catch (IOException e)
+ {
+ throw new PgpException("exception calculating keyId", e);
+ }
+ }
+
+ /// Constructor for a sub-key.
+ internal PgpPublicKey(
+ PublicKeyPacket publicPk,
+ TrustPacket trustPk,
+ ArrayList sigs)
+ {
+ this.publicPk = publicPk;
+ this.trustPk = trustPk;
+ this.subSigs = sigs;
+
+ Init();
+ }
+
+ internal PgpPublicKey(
+ PgpPublicKey key,
+ TrustPacket trust,
+ ArrayList subSigs)
+ {
+ this.publicPk = key.publicPk;
+ this.trustPk = trust;
+ this.subSigs = subSigs;
+
+ this.fingerprint = key.fingerprint;
+ this.keyId = key.keyId;
+ this.keyStrength = key.keyStrength;
+ }
+
+ /// Copy constructor.
+ /// The public key to copy.
+ internal PgpPublicKey(
+ PgpPublicKey pubKey)
+ {
+ this.publicPk = pubKey.publicPk;
+
+ this.keySigs = new ArrayList(pubKey.keySigs);
+ this.ids = new ArrayList(pubKey.ids);
+ this.idTrusts = new ArrayList(pubKey.idTrusts);
+ this.idSigs = new ArrayList(pubKey.idSigs.Count);
+ for (int i = 0; i != pubKey.idSigs.Count; i++)
+ {
+ this.idSigs.Add(new ArrayList((ArrayList)pubKey.idSigs[i]));
+ }
+
+ if (pubKey.subSigs != null)
+ {
+ this.subSigs = new ArrayList(pubKey.subSigs.Count);
+ for (int i = 0; i != pubKey.subSigs.Count; i++)
+ {
+ this.subSigs.Add(pubKey.subSigs[i]);
+ }
+ }
+
+ this.fingerprint = pubKey.fingerprint;
+ this.keyId = pubKey.keyId;
+ this.keyStrength = pubKey.keyStrength;
+ }
+
+ internal PgpPublicKey(
+ PublicKeyPacket publicPk,
+ TrustPacket trustPk,
+ ArrayList keySigs,
+ ArrayList ids,
+ ArrayList idTrusts,
+ ArrayList idSigs)
+ {
+ this.publicPk = publicPk;
+ this.trustPk = trustPk;
+ this.keySigs = keySigs;
+ this.ids = ids;
+ this.idTrusts = idTrusts;
+ this.idSigs = idSigs;
+
+ Init();
+ }
+
+ internal PgpPublicKey(
+ PublicKeyPacket publicPk,
+ ArrayList ids,
+ ArrayList idSigs)
+ {
+ this.publicPk = publicPk;
+ this.ids = ids;
+ this.idSigs = idSigs;
+ Init();
+ }
+
+ /// The version of this key.
+ public int Version
+ {
+ get { return publicPk.Version; }
+ }
+
+ /// The creation time of this key.
+ public DateTime CreationTime
+ {
+ get { return publicPk.GetTime(); }
+ }
+
+ /// The number of valid days from creation time - zero means no expiry.
+ public int ValidDays
+ {
+ get
+ {
+ if (publicPk.Version > 3)
+ {
+ return (int)(GetValidSeconds() / (24 * 60 * 60));
+ }
+
+ return publicPk.ValidDays;
+ }
+ }
+
+ /// Return the trust data associated with the public key, if present.
+ /// A byte array with trust data, null otherwise.
+ public byte[] GetTrustData()
+ {
+ if (trustPk == null)
+ {
+ return null;
+ }
+
+ return trustPk.GetLevelAndTrustAmount();
+ }
+
+ /// The number of valid seconds from creation time - zero means no expiry.
+ public long GetValidSeconds()
+ {
+ if (publicPk.Version > 3)
+ {
+ if (IsMasterKey)
+ {
+ for (int i = 0; i != MasterKeyCertificationTypes.Length; i++)
+ {
+ long seconds = GetExpirationTimeFromSig(true, MasterKeyCertificationTypes[i]);
+
+ if (seconds >= 0)
+ {
+ return seconds;
+ }
+ }
+ }
+ else
+ {
+ long seconds = GetExpirationTimeFromSig(false, PgpSignature.SubkeyBinding);
+
+ if (seconds >= 0)
+ {
+ return seconds;
+ }
+ }
+
+ return 0;
+ }
+
+ return (long) publicPk.ValidDays * 24 * 60 * 60;
+ }
+
+ private long GetExpirationTimeFromSig(
+ bool selfSigned,
+ int signatureType)
+ {
+ foreach (PgpSignature sig in GetSignaturesOfType(signatureType))
+ {
+ if (!selfSigned || sig.KeyId == KeyId)
+ {
+ PgpSignatureSubpacketVector hashed = sig.GetHashedSubPackets();
+
+ if (hashed != null)
+ {
+ return hashed.GetKeyExpirationTime();
+ }
+
+ return 0;
+ }
+ }
+
+ return -1;
+ }
+
+ /// The keyId associated with the public key.
+ public long KeyId
+ {
+ get { return keyId; }
+ }
+
+ /// The fingerprint of the key
+ public byte[] GetFingerprint()
+ {
+ return (byte[]) fingerprint.Clone();
+ }
+
+ ///
+ /// Check if this key has an algorithm type that makes it suitable to use for encryption.
+ ///
+ ///
+ /// Note: with version 4 keys KeyFlags subpackets should also be considered when present for
+ /// determining the preferred use of the key.
+ ///
+ ///
+ /// true if this key algorithm is suitable for encryption.
+ ///
+ public bool IsEncryptionKey
+ {
+ get
+ {
+ switch (publicPk.Algorithm)
+ {
+ case PublicKeyAlgorithmTag.ElGamalEncrypt:
+ case PublicKeyAlgorithmTag.ElGamalGeneral:
+ case PublicKeyAlgorithmTag.RsaEncrypt:
+ case PublicKeyAlgorithmTag.RsaGeneral:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ /// True, if this is a master key.
+ public bool IsMasterKey
+ {
+ get { return subSigs == null; }
+ }
+
+ /// The algorithm code associated with the public key.
+ public PublicKeyAlgorithmTag Algorithm
+ {
+ get { return publicPk.Algorithm; }
+ }
+
+ /// The strength of the key in bits.
+ public int BitStrength
+ {
+ get { return keyStrength; }
+ }
+
+ /// The public key contained in the object.
+ /// A lightweight public key.
+ /// If the key algorithm is not recognised.
+ public AsymmetricKeyParameter GetKey()
+ {
+ try
+ {
+ switch (publicPk.Algorithm)
+ {
+ case PublicKeyAlgorithmTag.RsaEncrypt:
+ case PublicKeyAlgorithmTag.RsaGeneral:
+ case PublicKeyAlgorithmTag.RsaSign:
+ RsaPublicBcpgKey rsaK = (RsaPublicBcpgKey) publicPk.Key;
+ return new RsaKeyParameters(false, rsaK.Modulus, rsaK.PublicExponent);
+ case PublicKeyAlgorithmTag.Dsa:
+ DsaPublicBcpgKey dsaK = (DsaPublicBcpgKey) publicPk.Key;
+ return new DsaPublicKeyParameters(dsaK.Y, new DsaParameters(dsaK.P, dsaK.Q, dsaK.G));
+ case PublicKeyAlgorithmTag.ElGamalEncrypt:
+ case PublicKeyAlgorithmTag.ElGamalGeneral:
+ ElGamalPublicBcpgKey elK = (ElGamalPublicBcpgKey) publicPk.Key;
+ return new ElGamalPublicKeyParameters(elK.Y, new ElGamalParameters(elK.P, elK.G));
+ default:
+ throw new PgpException("unknown public key algorithm encountered");
+ }
+ }
+ catch (PgpException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("exception constructing public key", e);
+ }
+ }
+
+ /// Allows enumeration of any user IDs associated with the key.
+ /// An IEnumerable of string objects.
+ public IEnumerable GetUserIds()
+ {
+ ArrayList temp = new ArrayList();
+
+ foreach (object o in ids)
+ {
+ if (o is string)
+ {
+ temp.Add(o);
+ }
+ }
+
+ return new EnumerableProxy(temp);
+ }
+
+ /// Allows enumeration of any user attribute vectors associated with the key.
+ /// An IEnumerable of PgpUserAttributeSubpacketVector objects.
+ public IEnumerable GetUserAttributes()
+ {
+ ArrayList temp = new ArrayList();
+
+ foreach (object o in ids)
+ {
+ if (o is PgpUserAttributeSubpacketVector)
+ {
+ temp.Add(o);
+ }
+ }
+
+ return new EnumerableProxy(temp);
+ }
+
+ /// Allows enumeration of any signatures associated with the passed in id.
+ /// The ID to be matched.
+ /// An IEnumerable of PgpSignature objects.
+ public IEnumerable GetSignaturesForId(
+ string id)
+ {
+ if (id == null)
+ throw new ArgumentNullException("id");
+
+ for (int i = 0; i != ids.Count; i++)
+ {
+ if (id.Equals(ids[i]))
+ {
+ return new EnumerableProxy((ArrayList) idSigs[i]);
+ }
+ }
+
+ return null;
+ }
+
+ /// Allows enumeration of signatures associated with the passed in user attributes.
+ /// The vector of user attributes to be matched.
+ /// An IEnumerable of PgpSignature objects.
+ public IEnumerable GetSignaturesForUserAttribute(
+ PgpUserAttributeSubpacketVector userAttributes)
+ {
+ for (int i = 0; i != ids.Count; i++)
+ {
+ if (userAttributes.Equals(ids[i]))
+ {
+ return new EnumerableProxy((ArrayList) idSigs[i]);
+ }
+ }
+
+ return null;
+ }
+
+ /// Allows enumeration of signatures of the passed in type that are on this key.
+ /// The type of the signature to be returned.
+ /// An IEnumerable of PgpSignature objects.
+ public IEnumerable GetSignaturesOfType(
+ int signatureType)
+ {
+ ArrayList temp = new ArrayList();
+
+ foreach (PgpSignature sig in GetSignatures())
+ {
+ if (sig.SignatureType == signatureType)
+ {
+ temp.Add(sig);
+ }
+ }
+
+ return new EnumerableProxy(temp);
+ }
+
+ /// Allows enumeration of all signatures/certifications associated with this key.
+ /// An IEnumerable with all signatures/certifications.
+ public IEnumerable GetSignatures()
+ {
+ ArrayList sigs;
+ if (subSigs != null)
+ {
+ sigs = subSigs;
+ }
+ else
+ {
+ sigs = new ArrayList(keySigs);
+
+ foreach (ICollection extraSigs in idSigs)
+ {
+ sigs.AddRange(extraSigs);
+ }
+ }
+
+ return new EnumerableProxy(sigs);
+ }
+
+ public byte[] GetEncoded()
+ {
+ MemoryStream bOut = new MemoryStream();
+ Encode(bOut);
+ return bOut.ToArray();
+ }
+
+ public void Encode(
+ Stream outStr)
+ {
+ BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr);
+
+ bcpgOut.WritePacket(publicPk);
+ if (trustPk != null)
+ {
+ bcpgOut.WritePacket(trustPk);
+ }
+
+ if (subSigs == null) // not a sub-key
+ {
+ foreach (PgpSignature keySig in keySigs)
+ {
+ keySig.Encode(bcpgOut);
+ }
+
+ for (int i = 0; i != ids.Count; i++)
+ {
+ if (ids[i] is string)
+ {
+ string id = (string) ids[i];
+
+ bcpgOut.WritePacket(new UserIdPacket(id));
+ }
+ else
+ {
+ PgpUserAttributeSubpacketVector v = (PgpUserAttributeSubpacketVector)ids[i];
+ bcpgOut.WritePacket(new UserAttributePacket(v.ToSubpacketArray()));
+ }
+
+ if (idTrusts[i] != null)
+ {
+ bcpgOut.WritePacket((ContainedPacket)idTrusts[i]);
+ }
+
+ foreach (PgpSignature sig in (ArrayList) idSigs[i])
+ {
+ sig.Encode(bcpgOut);
+ }
+ }
+ }
+ else
+ {
+ foreach (PgpSignature subSig in subSigs)
+ {
+ subSig.Encode(bcpgOut);
+ }
+ }
+ }
+
+ /// Check whether this (sub)key has a revocation signature on it.
+ /// True, if this (sub)key has been revoked.
+ public bool IsRevoked()
+ {
+ int ns = 0;
+ bool revoked = false;
+ if (IsMasterKey) // Master key
+ {
+ while (!revoked && (ns < keySigs.Count))
+ {
+ if (((PgpSignature)keySigs[ns++]).SignatureType == PgpSignature.KeyRevocation)
+ {
+ revoked = true;
+ }
+ }
+ }
+ else // Sub-key
+ {
+ while (!revoked && (ns < subSigs.Count))
+ {
+ if (((PgpSignature)subSigs[ns++]).SignatureType == PgpSignature.SubkeyRevocation)
+ {
+ revoked = true;
+ }
+ }
+ }
+ return revoked;
+ }
+
+ /// Add a certification for an id to the given public key.
+ /// The key the certification is to be added to.
+ /// The ID the certification is associated with.
+ /// The new certification.
+ /// The re-certified key.
+ public static PgpPublicKey AddCertification(
+ PgpPublicKey key,
+ string id,
+ PgpSignature certification)
+ {
+ return AddCert(key, id, certification);
+ }
+
+ /// Add a certification for the given UserAttributeSubpackets to the given public key.
+ /// The key the certification is to be added to.
+ /// The attributes the certification is associated with.
+ /// The new certification.
+ /// The re-certified key.
+ public static PgpPublicKey AddCertification(
+ PgpPublicKey key,
+ PgpUserAttributeSubpacketVector userAttributes,
+ PgpSignature certification)
+ {
+ return AddCert(key, userAttributes, certification);
+ }
+
+ private static PgpPublicKey AddCert(
+ PgpPublicKey key,
+ object id,
+ PgpSignature certification)
+ {
+ PgpPublicKey returnKey = new PgpPublicKey(key);
+ IList sigList = null;
+
+ for (int i = 0; i != returnKey.ids.Count; i++)
+ {
+ if (id.Equals(returnKey.ids[i]))
+ {
+ sigList = (IList) returnKey.idSigs[i];
+ }
+ }
+
+ if (sigList != null)
+ {
+ sigList.Add(certification);
+ }
+ else
+ {
+ sigList = new ArrayList();
+ sigList.Add(certification);
+ returnKey.ids.Add(id);
+ returnKey.idTrusts.Add(null);
+ returnKey.idSigs.Add(sigList);
+ }
+
+ return returnKey;
+ }
+
+ ///
+ /// Remove any certifications associated with a user attribute subpacket on a key.
+ ///
+ /// The key the certifications are to be removed from.
+ /// The attributes to be removed.
+ ///
+ /// The re-certified key, or null if the user attribute subpacket was not found on the key.
+ ///
+ public static PgpPublicKey RemoveCertification(
+ PgpPublicKey key,
+ PgpUserAttributeSubpacketVector userAttributes)
+ {
+ return RemoveCert(key, userAttributes);
+ }
+
+ /// Remove any certifications associated with a given ID on a key.
+ /// The key the certifications are to be removed from.
+ /// The ID that is to be removed.
+ /// The re-certified key, or null if the ID was not found on the key.
+ public static PgpPublicKey RemoveCertification(
+ PgpPublicKey key,
+ string id)
+ {
+ return RemoveCert(key, id);
+ }
+
+ private static PgpPublicKey RemoveCert(
+ PgpPublicKey key,
+ object id)
+ {
+ PgpPublicKey returnKey = new PgpPublicKey(key);
+ bool found = false;
+
+ for (int i = 0; i < returnKey.ids.Count; i++)
+ {
+ if (id.Equals(returnKey.ids[i]))
+ {
+ found = true;
+ returnKey.ids.RemoveAt(i);
+ returnKey.idTrusts.RemoveAt(i);
+ returnKey.idSigs.RemoveAt(i);
+ }
+ }
+
+ return found ? returnKey : null;
+ }
+
+ /// Remove a certification associated with a given ID on a key.
+ /// The key the certifications are to be removed from.
+ /// The ID that the certfication is to be removed from.
+ /// The certfication to be removed.
+ /// The re-certified key, or null if the certification was not found.
+ public static PgpPublicKey RemoveCertification(
+ PgpPublicKey key,
+ string id,
+ PgpSignature certification)
+ {
+ return RemoveCert(key, id, certification);
+ }
+
+ /// Remove a certification associated with a given user attributes on a key.
+ /// The key the certifications are to be removed from.
+ /// The user attributes that the certfication is to be removed from.
+ /// The certification to be removed.
+ /// The re-certified key, or null if the certification was not found.
+ public static PgpPublicKey RemoveCertification(
+ PgpPublicKey key,
+ PgpUserAttributeSubpacketVector userAttributes,
+ PgpSignature certification)
+ {
+ return RemoveCert(key, userAttributes, certification);
+ }
+
+ private static PgpPublicKey RemoveCert(
+ PgpPublicKey key,
+ object id,
+ PgpSignature certification)
+ {
+ PgpPublicKey returnKey = new PgpPublicKey(key);
+ bool found = false;
+
+ for (int i = 0; i < returnKey.ids.Count; i++)
+ {
+ if (id.Equals(returnKey.ids[i]))
+ {
+ ArrayList certs = (ArrayList) returnKey.idSigs[i];
+ found = certs.Contains(certification);
+
+ if (found)
+ {
+ certs.Remove(certification);
+ }
+ }
+ }
+
+ return found ? returnKey : null;
+ }
+
+ /// Add a revocation or some other key certification to a key.
+ /// The key the revocation is to be added to.
+ /// The key signature to be added.
+ /// The new changed public key object.
+ public static PgpPublicKey AddCertification(
+ PgpPublicKey key,
+ PgpSignature certification)
+ {
+ if (key.IsMasterKey)
+ {
+ if (certification.SignatureType == PgpSignature.SubkeyRevocation)
+ {
+ throw new ArgumentException("signature type incorrect for master key revocation.");
+ }
+ }
+ else
+ {
+ if (certification.SignatureType == PgpSignature.KeyRevocation)
+ {
+ throw new ArgumentException("signature type incorrect for sub-key revocation.");
+ }
+ }
+
+ PgpPublicKey returnKey = new PgpPublicKey(key);
+
+ if (returnKey.subSigs != null)
+ {
+ returnKey.subSigs.Add(certification);
+ }
+ else
+ {
+ returnKey.keySigs.Add(certification);
+ }
+
+ return returnKey;
+ }
+
+ /// Remove a certification from the key.
+ /// The key the certifications are to be removed from.
+ /// The certfication to be removed.
+ /// The modified key, null if the certification was not found.
+ public static PgpPublicKey RemoveCertification(
+ PgpPublicKey key,
+ PgpSignature certification)
+ {
+ PgpPublicKey returnKey = new PgpPublicKey(key);
+ ArrayList sigs = returnKey.subSigs != null
+ ? returnKey.subSigs
+ : returnKey.keySigs;
+
+// bool found = sigs.Remove(certification);
+ int pos = sigs.IndexOf(certification);
+ bool found = pos >= 0;
+
+ if (found)
+ {
+ sigs.RemoveAt(pos);
+ }
+ else
+ {
+ foreach (String id in key.GetUserIds())
+ {
+ foreach (object sig in key.GetSignaturesForId(id))
+ {
+ // TODO Is this the right type of equality test?
+ if (certification == sig)
+ {
+ found = true;
+ returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification);
+ }
+ }
+ }
+
+ if (!found)
+ {
+ foreach (PgpUserAttributeSubpacketVector id in key.GetUserAttributes())
+ {
+ foreach (object sig in key.GetSignaturesForUserAttribute(id))
+ {
+ // TODO Is this the right type of equality test?
+ if (certification == sig)
+ {
+ found = true;
+ returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification);
+ }
+ }
+ }
+ }
+ }
+
+ return returnKey;
+ }
+ }
+}
diff --git a/src/core/srcbc/openpgp/PgpPublicKeyRing.cs b/src/core/srcbc/openpgp/PgpPublicKeyRing.cs
index 631e427..1ace9f7 100644
--- a/src/core/srcbc/openpgp/PgpPublicKeyRing.cs
+++ b/src/core/srcbc/openpgp/PgpPublicKeyRing.cs
@@ -1,187 +1,194 @@
-using System;
-using System.Collections;
-using System.IO;
-
-using Org.BouncyCastle.Utilities.Collections;
-
-namespace Org.BouncyCastle.Bcpg.OpenPgp
-{
- ///
- /// Class to hold a single master public key and its subkeys.
- ///
- /// Often PGP keyring files consist of multiple master keys, if you are trying to process
- /// or construct one of these you should use the PgpPublicKeyRingBundle class.
- ///
- ///
- public class PgpPublicKeyRing
- : PgpKeyRing
- {
- private readonly ArrayList keys;
-
- public PgpPublicKeyRing(
- byte[] encoding)
- : this(new MemoryStream(encoding, false))
- {
- }
-
- internal PgpPublicKeyRing(
- ArrayList pubKeys)
- {
- this.keys = pubKeys;
- }
-
- public PgpPublicKeyRing(
- Stream inputStream)
- {
- this.keys = new ArrayList();
-
- BcpgInputStream bcpgInput = BcpgInputStream.Wrap(inputStream);
-
- PacketTag initialTag = bcpgInput.NextPacketTag();
- if (initialTag != PacketTag.PublicKey && initialTag != PacketTag.PublicSubkey)
- {
- throw new IOException("public key ring doesn't start with public key tag: "
- + "tag 0x" + ((int)initialTag).ToString("X"));
- }
-
- PublicKeyPacket pubPk = (PublicKeyPacket) bcpgInput.ReadPacket();;
- TrustPacket trustPk = ReadOptionalTrustPacket(bcpgInput);
-
- // direct signatures and revocations
- ArrayList keySigs = ReadSignaturesAndTrust(bcpgInput);
-
- ArrayList ids, idTrusts, idSigs;
- ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs);
-
- keys.Add(new PgpPublicKey(pubPk, trustPk, keySigs, ids, idTrusts, idSigs));
-
-
- // Read subkeys
- while (bcpgInput.NextPacketTag() == PacketTag.PublicSubkey)
- {
- PublicKeyPacket pk = (PublicKeyPacket) bcpgInput.ReadPacket();
- TrustPacket kTrust = ReadOptionalTrustPacket(bcpgInput);
-
- // PGP 8 actually leaves out the signature.
- ArrayList sigList = ReadSignaturesAndTrust(bcpgInput);
-
- keys.Add(new PgpPublicKey(pk, kTrust, sigList));
- }
- }
-
- /// Return the first public key in the ring.
- public PgpPublicKey GetPublicKey()
- {
- return (PgpPublicKey) keys[0];
- }
-
- /// Return the public key referred to by the passed in key ID if it is present.
- public PgpPublicKey GetPublicKey(
- long keyId)
- {
- foreach (PgpPublicKey k in keys)
- {
- if (keyId == k.KeyId)
- {
- return k;
- }
- }
-
- return null;
- }
-
- /// Allows enumeration of all the public keys.
- /// An IEnumerable of PgpPublicKey objects.
- public IEnumerable GetPublicKeys()
- {
- return new EnumerableProxy(keys);
- }
-
- public byte[] GetEncoded()
- {
- MemoryStream bOut = new MemoryStream();
-
- Encode(bOut);
-
- return bOut.ToArray();
- }
-
- public void Encode(
- Stream outStr)
- {
- if (outStr == null)
- throw new ArgumentNullException("outStr");
-
- foreach (PgpPublicKey k in keys)
- {
- k.Encode(outStr);
- }
- }
-
- ///
- /// Returns a new key ring with the public key passed in either added or
- /// replacing an existing one.
- ///
- /// The public key ring to be modified.
- /// The public key to be inserted.
- /// A new PgpPublicKeyRing
- public static PgpPublicKeyRing InsertPublicKey(
- PgpPublicKeyRing pubRing,
- PgpPublicKey pubKey)
- {
- ArrayList keys = new ArrayList(pubRing.keys);
- bool found = false;
- bool masterFound = false;
-
- for (int i = 0; i != keys.Count; i++)
- {
- PgpPublicKey key = (PgpPublicKey) keys[i];
-
- if (key.KeyId == pubKey.KeyId)
- {
- found = true;
- keys[i] = pubKey;
- }
- if (key.IsMasterKey)
- {
- masterFound = true;
- }
- }
-
- if (!found)
- {
- if (pubKey.IsMasterKey && masterFound)
- throw new ArgumentException("cannot add a master key to a ring that already has one");
-
- keys.Add(pubKey);
- }
-
- return new PgpPublicKeyRing(keys);
- }
-
- /// Returns a new key ring with the public key passed in removed from the key ring.
- /// The public key ring to be modified.
- /// The public key to be removed.
- /// A new PgpPublicKeyRing, or null if pubKey is not found.
- public static PgpPublicKeyRing RemovePublicKey(
- PgpPublicKeyRing pubRing,
- PgpPublicKey pubKey)
- {
- ArrayList keys = new ArrayList(pubRing.keys);
- bool found = false;
-
- for (int i = 0; i < keys.Count; i++)
- {
- PgpPublicKey key = (PgpPublicKey) keys[i];
-
- if (key.KeyId == pubKey.KeyId)
- {
- found = true;
- keys.RemoveAt(i);
- }
- }
-
- return found ? new PgpPublicKeyRing(keys) : null;
- }
- }
-}
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+ ///
+ /// Class to hold a single master public key and its subkeys.
+ ///
+ /// Often PGP keyring files consist of multiple master keys, if you are trying to process
+ /// or construct one of these you should use the PgpPublicKeyRingBundle class.
+ ///
+ ///
+ public class PgpPublicKeyRing
+ : PgpKeyRing
+ {
+ private readonly ArrayList keys;
+
+ public PgpPublicKeyRing(
+ byte[] encoding)
+ : this(new MemoryStream(encoding, false))
+ {
+ }
+
+ internal PgpPublicKeyRing(
+ ArrayList pubKeys)
+ {
+ this.keys = pubKeys;
+ }
+
+ public PgpPublicKeyRing(
+ Stream inputStream)
+ {
+ this.keys = new ArrayList();
+
+ BcpgInputStream bcpgInput = BcpgInputStream.Wrap(inputStream);
+
+ PacketTag initialTag = bcpgInput.NextPacketTag();
+ if (initialTag != PacketTag.PublicKey && initialTag != PacketTag.PublicSubkey)
+ {
+ throw new IOException("public key ring doesn't start with public key tag: "
+ + "tag 0x" + ((int)initialTag).ToString("X"));
+ }
+
+ PublicKeyPacket pubPk = (PublicKeyPacket) bcpgInput.ReadPacket();;
+ TrustPacket trustPk = ReadOptionalTrustPacket(bcpgInput);
+
+ // direct signatures and revocations
+ ArrayList keySigs = ReadSignaturesAndTrust(bcpgInput);
+
+ ArrayList ids, idTrusts, idSigs;
+ ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs);
+
+ keys.Add(new PgpPublicKey(pubPk, trustPk, keySigs, ids, idTrusts, idSigs));
+
+
+ // Read subkeys
+ while (bcpgInput.NextPacketTag() == PacketTag.PublicSubkey)
+ {
+ PublicKeyPacket pk = (PublicKeyPacket) bcpgInput.ReadPacket();
+ TrustPacket kTrust = ReadOptionalTrustPacket(bcpgInput);
+
+ // PGP 8 actually leaves out the signature.
+ ArrayList sigList = ReadSignaturesAndTrust(bcpgInput);
+
+ keys.Add(new PgpPublicKey(pk, kTrust, sigList));
+ }
+ }
+
+ /// Return the first public key in the ring.
+ public PgpPublicKey GetPublicKey()
+ {
+ return (PgpPublicKey) keys[0];
+ }
+
+ /// Return the public key referred to by the passed in key ID if it is present.
+ public PgpPublicKey GetPublicKey(
+ long keyId)
+ {
+ foreach (PgpPublicKey k in keys)
+ {
+ if (keyId == k.KeyId)
+ {
+ return k;
+ }
+ }
+
+ return null;
+ }
+
+ /// Allows enumeration of all the public keys.
+ /// An IEnumerable of PgpPublicKey objects.
+ public IEnumerable GetPublicKeys()
+ {
+ return new EnumerableProxy(keys);
+ }
+
+ public byte[] GetEncoded()
+ {
+ MemoryStream bOut = new MemoryStream();
+
+ Encode(bOut);
+
+ return bOut.ToArray();
+ }
+
+ public void Encode(
+ Stream outStr)
+ {
+ if (outStr == null)
+ throw new ArgumentNullException("outStr");
+
+ foreach (PgpPublicKey k in keys)
+ {
+ k.Encode(outStr);
+ }
+ }
+
+ ///
+ /// Returns a new key ring with the public key passed in either added or
+ /// replacing an existing one.
+ ///
+ /// The public key ring to be modified.
+ /// The public key to be inserted.
+ /// A new PgpPublicKeyRing
+ public static PgpPublicKeyRing InsertPublicKey(
+ PgpPublicKeyRing pubRing,
+ PgpPublicKey pubKey)
+ {
+ ArrayList keys = new ArrayList(pubRing.keys);
+ bool found = false;
+ bool masterFound = false;
+
+ for (int i = 0; i != keys.Count; i++)
+ {
+ PgpPublicKey key = (PgpPublicKey) keys[i];
+
+ if (key.KeyId == pubKey.KeyId)
+ {
+ found = true;
+ keys[i] = pubKey;
+ }
+ if (key.IsMasterKey)
+ {
+ masterFound = true;
+ }
+ }
+
+ if (!found)
+ {
+ if (pubKey.IsMasterKey)
+ {
+ if (masterFound)
+ throw new ArgumentException("cannot add a master key to a ring that already has one");
+
+ keys.Insert(0, pubKey);
+ }
+ else
+ {
+ keys.Add(pubKey);
+ }
+ }
+
+ return new PgpPublicKeyRing(keys);
+ }
+
+ /// Returns a new key ring with the public key passed in removed from the key ring.
+ /// The public key ring to be modified.
+ /// The public key to be removed.
+ /// A new PgpPublicKeyRing, or null if pubKey is not found.
+ public static PgpPublicKeyRing RemovePublicKey(
+ PgpPublicKeyRing pubRing,
+ PgpPublicKey pubKey)
+ {
+ ArrayList keys = new ArrayList(pubRing.keys);
+ bool found = false;
+
+ for (int i = 0; i < keys.Count; i++)
+ {
+ PgpPublicKey key = (PgpPublicKey) keys[i];
+
+ if (key.KeyId == pubKey.KeyId)
+ {
+ found = true;
+ keys.RemoveAt(i);
+ }
+ }
+
+ return found ? new PgpPublicKeyRing(keys) : null;
+ }
+ }
+}
diff --git a/src/core/srcbc/openpgp/PgpSecretKey.cs b/src/core/srcbc/openpgp/PgpSecretKey.cs
index cda7c43..c7036c8 100644
--- a/src/core/srcbc/openpgp/PgpSecretKey.cs
+++ b/src/core/srcbc/openpgp/PgpSecretKey.cs
@@ -1,716 +1,667 @@
-using System;
-using System.Collections;
-using System.IO;
-
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Security;
-
-namespace Org.BouncyCastle.Bcpg.OpenPgp
-{
- /// General class to handle a PGP secret key object.
- public class PgpSecretKey
- {
- private SecretKeyPacket secret;
- private TrustPacket trust;
- private ArrayList keySigs;
- private ArrayList ids;
- private ArrayList idTrusts;
- private ArrayList idSigs;
- private PgpPublicKey pub;
- private ArrayList subSigs;
-
- /// Copy constructor - master key.
- private PgpSecretKey(
- SecretKeyPacket secret,
- TrustPacket trust,
- ArrayList keySigs,
- ArrayList ids,
- ArrayList idTrusts,
- ArrayList idSigs,
- PgpPublicKey pub)
- {
- this.secret = secret;
- this.trust = trust;
- this.keySigs = keySigs;
- this.ids = ids;
- this.idTrusts = idTrusts;
- this.idSigs = idSigs;
- this.pub = pub;
- }
-
- /// Copy constructor - subkey.
- private PgpSecretKey(
- SecretKeyPacket secret,
- TrustPacket trust,
- ArrayList subSigs,
- PgpPublicKey pub)
- {
- this.secret = secret;
- this.trust = trust;
- this.subSigs = subSigs;
- this.pub = pub;
- }
-
- internal PgpSecretKey(
- SecretKeyPacket secret,
- TrustPacket trust,
- ArrayList keySigs,
- ArrayList ids,
- ArrayList idTrusts,
- ArrayList idSigs)
- {
- this.secret = secret;
- this.trust = trust;
- this.keySigs = keySigs;
- this.ids = ids;
- this.idTrusts = idTrusts;
- this.idSigs = idSigs;
- this.pub = new PgpPublicKey(secret.PublicKeyPacket, trust, keySigs, ids, idTrusts, idSigs);
- }
-
- internal PgpSecretKey(
- SecretKeyPacket secret,
- TrustPacket trust,
- ArrayList subSigs)
- {
- this.secret = secret;
- this.trust = trust;
- this.subSigs = subSigs;
- this.pub = new PgpPublicKey(secret.PublicKeyPacket, trust, subSigs);
- }
-
- /// Create a subkey
- internal PgpSecretKey(
- PgpKeyPair keyPair,
- TrustPacket trust,
- ArrayList subSigs,
- SymmetricKeyAlgorithmTag encAlgorithm,
- char[] passPhrase,
- bool useSHA1,
- SecureRandom rand)
- : this(keyPair, encAlgorithm, passPhrase, useSHA1, rand)
- {
- this.secret = new SecretSubkeyPacket(
- secret.PublicKeyPacket,
- secret.EncAlgorithm,
- secret.S2kUsage,
- secret.S2k,
- secret.GetIV(),
- secret.GetSecretKeyData());
-
- this.trust = trust;
- this.subSigs = subSigs;
- this.pub = new PgpPublicKey(keyPair.PublicKey, trust, subSigs);
- }
-
- internal PgpSecretKey(
- PgpKeyPair keyPair,
- SymmetricKeyAlgorithmTag encAlgorithm,
- char[] passPhrase,
- bool useSHA1,
- SecureRandom rand)
- {
- PublicKeyPacket pubPk = keyPair.PublicKey.publicPk;
-
- BcpgObject secKey;
- switch (keyPair.PublicKey.Algorithm)
- {
- case PublicKeyAlgorithmTag.RsaEncrypt:
- case PublicKeyAlgorithmTag.RsaSign:
- case PublicKeyAlgorithmTag.RsaGeneral:
- RsaPrivateCrtKeyParameters rsK = (RsaPrivateCrtKeyParameters) keyPair.PrivateKey.Key;
- secKey = new RsaSecretBcpgKey(rsK.Exponent, rsK.P, rsK.Q);
- break;
- case PublicKeyAlgorithmTag.Dsa:
- DsaPrivateKeyParameters dsK = (DsaPrivateKeyParameters) keyPair.PrivateKey.Key;
- secKey = new DsaSecretBcpgKey(dsK.X);
- break;
- case PublicKeyAlgorithmTag.ElGamalEncrypt:
- case PublicKeyAlgorithmTag.ElGamalGeneral:
- ElGamalPrivateKeyParameters esK = (ElGamalPrivateKeyParameters) keyPair.PrivateKey.Key;
- secKey = new ElGamalSecretBcpgKey(esK.X);
- break;
- default:
- throw new PgpException("unknown key class");
- }
-
- try
- {
- MemoryStream bOut = new MemoryStream();
- BcpgOutputStream pOut = new BcpgOutputStream(bOut);
-
- pOut.WriteObject(secKey);
-
- byte[] keyData = bOut.ToArray();
- byte[] checksumBytes = Checksum(useSHA1, keyData, keyData.Length);
-
- pOut.Write(checksumBytes);
-
- byte[] bOutData = bOut.ToArray();
-
- if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
- {
- this.secret = new SecretKeyPacket(pubPk, encAlgorithm, null, null, bOutData);
- }
- else
- {
- S2k s2k;
- byte[] iv;
- byte[] encData = EncryptKeyData(bOutData, encAlgorithm, passPhrase, rand, out s2k, out iv);
-
- int usage = useSHA1
- ? SecretKeyPacket.UsageSha1
- : SecretKeyPacket.UsageChecksum;
-
- this.secret = new SecretKeyPacket(pubPk, encAlgorithm, usage, s2k, iv, encData);
- }
-
- this.trust = null;
- }
- catch (PgpException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new PgpException("Exception encrypting key", e);
- }
-
- this.keySigs = new ArrayList();
- }
-
- public PgpSecretKey(
- int certificationLevel,
- PgpKeyPair keyPair,
- string id,
- SymmetricKeyAlgorithmTag encAlgorithm,
- char[] passPhrase,
- PgpSignatureSubpacketVector hashedPackets,
- PgpSignatureSubpacketVector unhashedPackets,
- SecureRandom rand)
- : this(certificationLevel, keyPair, id, encAlgorithm, passPhrase, false, hashedPackets, unhashedPackets, rand)
- {
- }
-
- public PgpSecretKey(
- int certificationLevel,
- PgpKeyPair keyPair,
- string id,
- SymmetricKeyAlgorithmTag encAlgorithm,
- char[] passPhrase,
- bool useSHA1,
- PgpSignatureSubpacketVector hashedPackets,
- PgpSignatureSubpacketVector unhashedPackets,
- SecureRandom rand)
- : this(keyPair, encAlgorithm, passPhrase, useSHA1, rand)
- {
- try
- {
- this.trust = null;
- this.ids = new ArrayList();
- ids.Add(id);
-
- this.idTrusts = new ArrayList();
- idTrusts.Add(null);
-
- this.idSigs = new ArrayList();
-
- PgpSignatureGenerator sGen = new PgpSignatureGenerator(
- keyPair.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
-
- //
- // Generate the certification
- //
- sGen.InitSign(certificationLevel, keyPair.PrivateKey);
-
- sGen.SetHashedSubpackets(hashedPackets);
- sGen.SetUnhashedSubpackets(unhashedPackets);
-
- PgpSignature certification = sGen.GenerateCertification(id, keyPair.PublicKey);
- this.pub = PgpPublicKey.AddCertification(keyPair.PublicKey, id, certification);
-
- ArrayList sigList = new ArrayList();
- sigList.Add(certification);
- idSigs.Add(sigList);
- }
- catch (PgpException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new PgpException("Exception encrypting key", e);
- }
- }
-
- public PgpSecretKey(
- int certificationLevel,
- PublicKeyAlgorithmTag algorithm,
- AsymmetricKeyParameter pubKey,
- AsymmetricKeyParameter privKey,
- DateTime time,
- string id,
- SymmetricKeyAlgorithmTag encAlgorithm,
- char[] passPhrase,
- PgpSignatureSubpacketVector hashedPackets,
- PgpSignatureSubpacketVector unhashedPackets,
- SecureRandom rand)
- : this(certificationLevel,
- new PgpKeyPair(algorithm, pubKey, privKey, time),
- id, encAlgorithm, passPhrase, hashedPackets, unhashedPackets, rand)
- {
- }
-
- public PgpSecretKey(
- int certificationLevel,
- PublicKeyAlgorithmTag algorithm,
- AsymmetricKeyParameter pubKey,
- AsymmetricKeyParameter privKey,
- DateTime time,
- string id,
- SymmetricKeyAlgorithmTag encAlgorithm,
- char[] passPhrase,
- bool useSHA1,
- PgpSignatureSubpacketVector hashedPackets,
- PgpSignatureSubpacketVector unhashedPackets,
- SecureRandom rand)
- : this(certificationLevel, new PgpKeyPair(algorithm, pubKey, privKey, time), id, encAlgorithm, passPhrase, useSHA1, hashedPackets, unhashedPackets, rand)
- {
- }
-
- ///
- /// Check if this key has an algorithm type that makes it suitable to use for signing.
- ///
- ///
- /// Note: with version 4 keys KeyFlags subpackets should also be considered when present for
- /// determining the preferred use of the key.
- ///
- ///
- /// true if this key algorithm is suitable for use with signing.
- ///
- public bool IsSigningKey
- {
- get
- {
- switch (pub.Algorithm)
- {
- case PublicKeyAlgorithmTag.RsaGeneral:
- case PublicKeyAlgorithmTag.RsaSign:
- case PublicKeyAlgorithmTag.Dsa:
- case PublicKeyAlgorithmTag.ECDsa:
- case PublicKeyAlgorithmTag.ElGamalGeneral:
- return true;
- default:
- return false;
- }
- }
- }
-
- /// True, if this is a master key.
- public bool IsMasterKey
- {
- get { return subSigs == null; }
- }
-
- /// The algorithm the key is encrypted with.
- public SymmetricKeyAlgorithmTag KeyEncryptionAlgorithm
- {
- get { return secret.EncAlgorithm; }
- }
-
- /// The key ID of the public key associated with this key.
- public long KeyId
- {
- get { return pub.KeyId; }
- }
-
- /// The public key associated with this key.
- public PgpPublicKey PublicKey
- {
- get { return pub; }
- }
-
- /// Allows enumeration of any user IDs associated with the key.
- /// An IEnumerable of string objects.
- public IEnumerable UserIds
- {
- get { return pub.GetUserIds(); }
- }
-
- /// Allows enumeration of any user attribute vectors associated with the key.
- /// An IEnumerable of string objects.
- public IEnumerable UserAttributes
- {
- get { return pub.GetUserAttributes(); }
- }
-
- private byte[] ExtractKeyData(
- char[] passPhrase)
- {
- SymmetricKeyAlgorithmTag alg = secret.EncAlgorithm;
- byte[] encData = secret.GetSecretKeyData();
-
- if (alg == SymmetricKeyAlgorithmTag.Null)
- return encData;
-
- byte[] data;
- IBufferedCipher c = null;
- try
- {
- string cName = PgpUtilities.GetSymmetricCipherName(alg);
- c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding");
- }
- catch (Exception e)
- {
- throw new PgpException("Exception creating cipher", e);
- }
-
- // TODO Factor this block out as 'encryptData'
- try
- {
- KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(secret.EncAlgorithm, secret.S2k, passPhrase);
- byte[] iv = secret.GetIV();
-
- if (secret.PublicKeyPacket.Version == 4)
- {
- c.Init(false, new ParametersWithIV(key, iv));
-
- data = c.DoFinal(encData);
-
- bool useSHA1 = secret.S2kUsage == SecretKeyPacket.UsageSha1;
- byte[] check = Checksum(useSHA1, data, (useSHA1) ? data.Length - 20 : data.Length - 2);
-
- for (int i = 0; i != check.Length; i++)
- {
- if (check[i] != data[data.Length - check.Length + i])
- {
- throw new PgpException("Checksum mismatch at " + i + " of " + check.Length);
- }
- }
- }
- else // version 2 or 3, RSA only.
- {
- data = new byte[encData.Length];
-
- //
- // read in the four numbers
- //
- int pos = 0;
-
- for (int i = 0; i != 4; i++)
- {
- c.Init(false, new ParametersWithIV(key, iv));
-
- int encLen = (((encData[pos] << 8) | (encData[pos + 1] & 0xff)) + 7) / 8;
-
- data[pos] = encData[pos];
- data[pos + 1] = encData[pos + 1];
- pos += 2;
-
- c.DoFinal(encData, pos, encLen, data, pos);
- pos += encLen;
-
- if (i != 3)
- {
- Array.Copy(encData, pos - iv.Length, iv, 0, iv.Length);
- }
- }
-
- //
- // verify Checksum
- //
- int cs = ((encData[pos] << 8) & 0xff00) | (encData[pos + 1] & 0xff);
- int calcCs = 0;
- for (int j=0; j < data.Length-2; j++)
- {
- calcCs += data[j] & 0xff;
- }
-
- calcCs &= 0xffff;
- if (calcCs != cs)
- {
- throw new PgpException("Checksum mismatch: passphrase wrong, expected "
- + cs.ToString("X")
- + " found " + calcCs.ToString("X"));
- }
- }
-
- return data;
- }
- catch (PgpException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new PgpException("Exception decrypting key", e);
- }
- }
-
- /// Extract a PgpPrivateKey from this secret key's encrypted contents.
- public PgpPrivateKey ExtractPrivateKey(
- char[] passPhrase)
- {
- byte[] secKeyData = secret.GetSecretKeyData();
- if (secKeyData == null || secKeyData.Length < 1)
- return null;
-
- PublicKeyPacket pubPk = secret.PublicKeyPacket;
- try
- {
- byte[] data = ExtractKeyData(passPhrase);
- BcpgInputStream bcpgIn = BcpgInputStream.Wrap(new MemoryStream(data, false));
- AsymmetricKeyParameter privateKey;
- switch (pubPk.Algorithm)
- {
- case PublicKeyAlgorithmTag.RsaEncrypt:
- case PublicKeyAlgorithmTag.RsaGeneral:
- case PublicKeyAlgorithmTag.RsaSign:
- RsaPublicBcpgKey rsaPub = (RsaPublicBcpgKey)pubPk.Key;
- RsaSecretBcpgKey rsaPriv = new RsaSecretBcpgKey(bcpgIn);
- RsaPrivateCrtKeyParameters rsaPrivSpec = new RsaPrivateCrtKeyParameters(
- rsaPriv.Modulus,
- rsaPub.PublicExponent,
- rsaPriv.PrivateExponent,
- rsaPriv.PrimeP,
- rsaPriv.PrimeQ,
- rsaPriv.PrimeExponentP,
- rsaPriv.PrimeExponentQ,
- rsaPriv.CrtCoefficient);
- privateKey = rsaPrivSpec;
- break;
- case PublicKeyAlgorithmTag.Dsa:
- DsaPublicBcpgKey dsaPub = (DsaPublicBcpgKey)pubPk.Key;
- DsaSecretBcpgKey dsaPriv = new DsaSecretBcpgKey(bcpgIn);
- DsaParameters dsaParams = new DsaParameters(dsaPub.P, dsaPub.Q, dsaPub.G);
- privateKey = new DsaPrivateKeyParameters(dsaPriv.X, dsaParams);
- break;
- case PublicKeyAlgorithmTag.ElGamalEncrypt:
- case PublicKeyAlgorithmTag.ElGamalGeneral:
- ElGamalPublicBcpgKey elPub = (ElGamalPublicBcpgKey)pubPk.Key;
- ElGamalSecretBcpgKey elPriv = new ElGamalSecretBcpgKey(bcpgIn);
- ElGamalParameters elParams = new ElGamalParameters(elPub.P, elPub.G);
- privateKey = new ElGamalPrivateKeyParameters(elPriv.X, elParams);
- break;
- default:
- throw new PgpException("unknown public key algorithm encountered");
- }
-
- return new PgpPrivateKey(privateKey, KeyId);
- }
- catch (PgpException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new PgpException("Exception constructing key", e);
- }
- }
-
- private static byte[] Checksum(
- bool useSHA1,
- byte[] bytes,
- int length)
- {
- if (useSHA1)
- {
- try
- {
- IDigest dig = DigestUtilities.GetDigest("SHA1");
- dig.BlockUpdate(bytes, 0, length);
- return DigestUtilities.DoFinal(dig);
- }
- //catch (NoSuchAlgorithmException e)
- catch (Exception e)
- {
- throw new PgpException("Can't find SHA-1", e);
- }
- }
- else
- {
- int Checksum = 0;
- for (int i = 0; i != length; i++)
- {
- Checksum += bytes[i];
- }
-
- return new byte[] { (byte)(Checksum >> 8), (byte)Checksum };
- }
- }
-
- public byte[] GetEncoded()
- {
- MemoryStream bOut = new MemoryStream();
- Encode(bOut);
- return bOut.ToArray();
- }
-
- public void Encode(
- Stream outStr)
- {
- BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr);
-
- bcpgOut.WritePacket(secret);
- if (trust != null)
- {
- bcpgOut.WritePacket(trust);
- }
-
- if (subSigs == null) // is not a sub key
- {
- foreach (PgpSignature keySig in keySigs)
- {
- keySig.Encode(bcpgOut);
- }
-
- for (int i = 0; i != ids.Count; i++)
- {
- if (ids[i] is string)
- {
- string id = (string) ids[i];
-
- bcpgOut.WritePacket(new UserIdPacket(id));
- }
- else
- {
- PgpUserAttributeSubpacketVector v = (PgpUserAttributeSubpacketVector)ids[i];
- bcpgOut.WritePacket(new UserAttributePacket(v.ToSubpacketArray()));
- }
-
- if (idTrusts[i] != null)
- {
- bcpgOut.WritePacket((ContainedPacket)idTrusts[i]);
- }
-
- foreach (PgpSignature sig in (ArrayList) idSigs[i])
- {
- sig.Encode(bcpgOut);
- }
- }
- }
- else
- {
- foreach (PgpSignature subSig in subSigs)
- {
- subSig.Encode(bcpgOut);
- }
- }
-
- // TODO Check that this is right/necessary
- //bcpgOut.Finish();
- }
-
- ///
- /// Return a copy of the passed in secret key, encrypted using a new password
- /// and the passed in algorithm.
- ///
- /// The PgpSecretKey to be copied.
- /// The current password for the key.
- /// The new password for the key.
- /// The algorithm to be used for the encryption.
- /// Source of randomness.
- public static PgpSecretKey CopyWithNewPassword(
- PgpSecretKey key,
- char[] oldPassPhrase,
- char[] newPassPhrase,
- SymmetricKeyAlgorithmTag newEncAlgorithm,
- SecureRandom rand)
- {
- byte[] rawKeyData = key.ExtractKeyData(oldPassPhrase);
- int s2kUsage = key.secret.S2kUsage;
- byte[] iv = null;
- S2k s2k = null;
- byte[] keyData;
-
- if (newEncAlgorithm == SymmetricKeyAlgorithmTag.Null)
- {
- s2kUsage = SecretKeyPacket.UsageNone;
- if (key.secret.S2kUsage == SecretKeyPacket.UsageSha1) // SHA-1 hash, need to rewrite Checksum
- {
- keyData = new byte[rawKeyData.Length - 18];
-
- Array.Copy(rawKeyData, 0, keyData, 0, keyData.Length - 2);
-
- byte[] check = Checksum(false, keyData, keyData.Length - 2);
-
- keyData[keyData.Length - 2] = check[0];
- keyData[keyData.Length - 1] = check[1];
- }
- else
- {
- keyData = rawKeyData;
- }
- }
- else
- {
- try
- {
- keyData = EncryptKeyData(rawKeyData, newEncAlgorithm, newPassPhrase, rand, out s2k, out iv);
- }
- catch (PgpException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new PgpException("Exception encrypting key", e);
- }
- }
-
- SecretKeyPacket secret;
- if (key.secret is SecretSubkeyPacket)
- {
- secret = new SecretSubkeyPacket(key.secret.PublicKeyPacket,
- newEncAlgorithm, s2kUsage, s2k, iv, keyData);
- }
- else
- {
- secret = new SecretKeyPacket(key.secret.PublicKeyPacket,
- newEncAlgorithm, s2kUsage, s2k, iv, keyData);
- }
-
- if (key.subSigs == null)
- {
- return new PgpSecretKey(secret, key.trust, key.keySigs, key.ids,
- key.idTrusts, key.idSigs, key.pub);
- }
-
- return new PgpSecretKey(secret, key.trust, key.subSigs, key.pub);
- }
-
- private static byte[] EncryptKeyData(
- byte[] rawKeyData,
- SymmetricKeyAlgorithmTag encAlgorithm,
- char[] passPhrase,
- SecureRandom random,
- out S2k s2k,
- out byte[] iv)
- {
- IBufferedCipher c;
- try
- {
- string cName = PgpUtilities.GetSymmetricCipherName(encAlgorithm);
- c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding");
- }
- catch (Exception e)
- {
- throw new PgpException("Exception creating cipher", e);
- }
-
- byte[] s2kIV = new byte[8];
- random.NextBytes(s2kIV);
- s2k = new S2k(HashAlgorithmTag.Sha1, s2kIV, 0x60);
-
- KeyParameter kp = PgpUtilities.MakeKeyFromPassPhrase(encAlgorithm, s2k, passPhrase);
-
- iv = new byte[c.GetBlockSize()];
- random.NextBytes(iv);
-
- c.Init(true, new ParametersWithRandom(new ParametersWithIV(kp, iv), random));
-
- return c.DoFinal(rawKeyData);
- }
- }
-}
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+ /// General class to handle a PGP secret key object.
+ public class PgpSecretKey
+ {
+ private readonly SecretKeyPacket secret;
+ private readonly PgpPublicKey pub;
+
+ internal PgpSecretKey(
+ SecretKeyPacket secret,
+ PgpPublicKey pub)
+ {
+ this.secret = secret;
+ this.pub = pub;
+ }
+
+ internal PgpSecretKey(
+ PgpPrivateKey privKey,
+ PgpPublicKey pubKey,
+ SymmetricKeyAlgorithmTag encAlgorithm,
+ char[] passPhrase,
+ bool useSha1,
+ SecureRandom rand)
+ : this(privKey, pubKey, encAlgorithm, passPhrase, useSha1, rand, false)
+ {
+ }
+
+ internal PgpSecretKey(
+ PgpPrivateKey privKey,
+ PgpPublicKey pubKey,
+ SymmetricKeyAlgorithmTag encAlgorithm,
+ char[] passPhrase,
+ bool useSha1,
+ SecureRandom rand,
+ bool isMasterKey)
+ {
+ BcpgObject secKey;
+
+ this.pub = pubKey;
+
+ switch (pubKey.Algorithm)
+ {
+ case PublicKeyAlgorithmTag.RsaEncrypt:
+ case PublicKeyAlgorithmTag.RsaSign:
+ case PublicKeyAlgorithmTag.RsaGeneral:
+ RsaPrivateCrtKeyParameters rsK = (RsaPrivateCrtKeyParameters) privKey.Key;
+ secKey = new RsaSecretBcpgKey(rsK.Exponent, rsK.P, rsK.Q);
+ break;
+ case PublicKeyAlgorithmTag.Dsa:
+ DsaPrivateKeyParameters dsK = (DsaPrivateKeyParameters) privKey.Key;
+ secKey = new DsaSecretBcpgKey(dsK.X);
+ break;
+ case PublicKeyAlgorithmTag.ElGamalEncrypt:
+ case PublicKeyAlgorithmTag.ElGamalGeneral:
+ ElGamalPrivateKeyParameters esK = (ElGamalPrivateKeyParameters) privKey.Key;
+ secKey = new ElGamalSecretBcpgKey(esK.X);
+ break;
+ default:
+ throw new PgpException("unknown key class");
+ }
+
+ try
+ {
+ MemoryStream bOut = new MemoryStream();
+ BcpgOutputStream pOut = new BcpgOutputStream(bOut);
+
+ pOut.WriteObject(secKey);
+
+ byte[] keyData = bOut.ToArray();
+ byte[] checksumBytes = Checksum(useSha1, keyData, keyData.Length);
+
+ pOut.Write(checksumBytes);
+
+ byte[] bOutData = bOut.ToArray();
+
+ if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
+ {
+ if (isMasterKey)
+ {
+ this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, null, null, bOutData);
+ }
+ else
+ {
+ this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, null, null, bOutData);
+ }
+ }
+ else
+ {
+ S2k s2k;
+ byte[] iv;
+ byte[] encData = EncryptKeyData(bOutData, encAlgorithm, passPhrase, rand, out s2k, out iv);
+
+ int s2kUsage = useSha1
+ ? SecretKeyPacket.UsageSha1
+ : SecretKeyPacket.UsageChecksum;
+
+ if (isMasterKey)
+ {
+ this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
+ }
+ else
+ {
+ this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
+ }
+ }
+ }
+ catch (PgpException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.StackTrace);
+ throw new PgpException("Exception encrypting key", e);
+ }
+ }
+
+ public PgpSecretKey(
+ int certificationLevel,
+ PgpKeyPair keyPair,
+ string id,
+ SymmetricKeyAlgorithmTag encAlgorithm,
+ char[] passPhrase,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ SecureRandom rand)
+ : this(certificationLevel, keyPair, id, encAlgorithm, passPhrase, false, hashedPackets, unhashedPackets, rand)
+ {
+ }
+
+ public PgpSecretKey(
+ int certificationLevel,
+ PgpKeyPair keyPair,
+ string id,
+ SymmetricKeyAlgorithmTag encAlgorithm,
+ char[] passPhrase,
+ bool useSha1,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ SecureRandom rand)
+ : this(keyPair.PrivateKey, certifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets), encAlgorithm, passPhrase, useSha1, rand, true)
+ {
+ }
+
+ private static PgpPublicKey certifiedPublicKey(
+ int certificationLevel,
+ PgpKeyPair keyPair,
+ string id,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets)
+ {
+ PgpSignatureGenerator sGen;
+ try
+ {
+ sGen = new PgpSignatureGenerator(keyPair.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("Creating signature generator: " + e.Message, e);
+ }
+
+ //
+ // Generate the certification
+ //
+ sGen.InitSign(certificationLevel, keyPair.PrivateKey);
+
+ sGen.SetHashedSubpackets(hashedPackets);
+ sGen.SetUnhashedSubpackets(unhashedPackets);
+
+ try
+ {
+ PgpSignature certification = sGen.GenerateCertification(id, keyPair.PublicKey);
+ return PgpPublicKey.AddCertification(keyPair.PublicKey, id, certification);
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("Exception doing certification: " + e.Message, e);
+ }
+ }
+
+ public PgpSecretKey(
+ int certificationLevel,
+ PublicKeyAlgorithmTag algorithm,
+ AsymmetricKeyParameter pubKey,
+ AsymmetricKeyParameter privKey,
+ DateTime time,
+ string id,
+ SymmetricKeyAlgorithmTag encAlgorithm,
+ char[] passPhrase,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ SecureRandom rand)
+ : this(certificationLevel,
+ new PgpKeyPair(algorithm, pubKey, privKey, time),
+ id, encAlgorithm, passPhrase, hashedPackets, unhashedPackets, rand)
+ {
+ }
+
+ public PgpSecretKey(
+ int certificationLevel,
+ PublicKeyAlgorithmTag algorithm,
+ AsymmetricKeyParameter pubKey,
+ AsymmetricKeyParameter privKey,
+ DateTime time,
+ string id,
+ SymmetricKeyAlgorithmTag encAlgorithm,
+ char[] passPhrase,
+ bool useSha1,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ SecureRandom rand)
+ : this(certificationLevel, new PgpKeyPair(algorithm, pubKey, privKey, time), id, encAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand)
+ {
+ }
+
+ ///
+ /// Check if this key has an algorithm type that makes it suitable to use for signing.
+ ///
+ ///
+ /// Note: with version 4 keys KeyFlags subpackets should also be considered when present for
+ /// determining the preferred use of the key.
+ ///
+ ///
+ /// true if this key algorithm is suitable for use with signing.
+ ///
+ public bool IsSigningKey
+ {
+ get
+ {
+ switch (pub.Algorithm)
+ {
+ case PublicKeyAlgorithmTag.RsaGeneral:
+ case PublicKeyAlgorithmTag.RsaSign:
+ case PublicKeyAlgorithmTag.Dsa:
+ case PublicKeyAlgorithmTag.ECDsa:
+ case PublicKeyAlgorithmTag.ElGamalGeneral:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ /// True, if this is a master key.
+ public bool IsMasterKey
+ {
+ get { return pub.IsMasterKey; }
+ }
+
+ /// The algorithm the key is encrypted with.
+ public SymmetricKeyAlgorithmTag KeyEncryptionAlgorithm
+ {
+ get { return secret.EncAlgorithm; }
+ }
+
+ /// The key ID of the public key associated with this key.
+ public long KeyId
+ {
+ get { return pub.KeyId; }
+ }
+
+ /// The public key associated with this key.
+ public PgpPublicKey PublicKey
+ {
+ get { return pub; }
+ }
+
+ /// Allows enumeration of any user IDs associated with the key.
+ /// An IEnumerable of string objects.
+ public IEnumerable UserIds
+ {
+ get { return pub.GetUserIds(); }
+ }
+
+ /// Allows enumeration of any user attribute vectors associated with the key.
+ /// An IEnumerable of string objects.
+ public IEnumerable UserAttributes
+ {
+ get { return pub.GetUserAttributes(); }
+ }
+
+ private byte[] ExtractKeyData(
+ char[] passPhrase)
+ {
+ SymmetricKeyAlgorithmTag alg = secret.EncAlgorithm;
+ byte[] encData = secret.GetSecretKeyData();
+
+ if (alg == SymmetricKeyAlgorithmTag.Null)
+ return encData;
+
+ byte[] data;
+ IBufferedCipher c = null;
+ try
+ {
+ string cName = PgpUtilities.GetSymmetricCipherName(alg);
+ c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding");
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("Exception creating cipher", e);
+ }
+
+ // TODO Factor this block out as 'encryptData'
+ try
+ {
+ KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(secret.EncAlgorithm, secret.S2k, passPhrase);
+ byte[] iv = secret.GetIV();
+
+ if (secret.PublicKeyPacket.Version == 4)
+ {
+ c.Init(false, new ParametersWithIV(key, iv));
+
+ data = c.DoFinal(encData);
+
+ bool useSha1 = secret.S2kUsage == SecretKeyPacket.UsageSha1;
+ byte[] check = Checksum(useSha1, data, (useSha1) ? data.Length - 20 : data.Length - 2);
+
+ for (int i = 0; i != check.Length; i++)
+ {
+ if (check[i] != data[data.Length - check.Length + i])
+ {
+ throw new PgpException("Checksum mismatch at " + i + " of " + check.Length);
+ }
+ }
+ }
+ else // version 2 or 3, RSA only.
+ {
+ data = new byte[encData.Length];
+
+ //
+ // read in the four numbers
+ //
+ int pos = 0;
+
+ for (int i = 0; i != 4; i++)
+ {
+ c.Init(false, new ParametersWithIV(key, iv));
+
+ int encLen = (((encData[pos] << 8) | (encData[pos + 1] & 0xff)) + 7) / 8;
+
+ data[pos] = encData[pos];
+ data[pos + 1] = encData[pos + 1];
+ pos += 2;
+
+ c.DoFinal(encData, pos, encLen, data, pos);
+ pos += encLen;
+
+ if (i != 3)
+ {
+ Array.Copy(encData, pos - iv.Length, iv, 0, iv.Length);
+ }
+ }
+
+ //
+ // verify Checksum
+ //
+ int cs = ((encData[pos] << 8) & 0xff00) | (encData[pos + 1] & 0xff);
+ int calcCs = 0;
+ for (int j=0; j < data.Length-2; j++)
+ {
+ calcCs += data[j] & 0xff;
+ }
+
+ calcCs &= 0xffff;
+ if (calcCs != cs)
+ {
+ throw new PgpException("Checksum mismatch: passphrase wrong, expected "
+ + cs.ToString("X")
+ + " found " + calcCs.ToString("X"));
+ }
+ }
+
+ return data;
+ }
+ catch (PgpException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("Exception decrypting key", e);
+ }
+ }
+
+ /// Extract a PgpPrivateKey from this secret key's encrypted contents.
+ public PgpPrivateKey ExtractPrivateKey(
+ char[] passPhrase)
+ {
+ byte[] secKeyData = secret.GetSecretKeyData();
+ if (secKeyData == null || secKeyData.Length < 1)
+ return null;
+
+ PublicKeyPacket pubPk = secret.PublicKeyPacket;
+ try
+ {
+ byte[] data = ExtractKeyData(passPhrase);
+ BcpgInputStream bcpgIn = BcpgInputStream.Wrap(new MemoryStream(data, false));
+ AsymmetricKeyParameter privateKey;
+ switch (pubPk.Algorithm)
+ {
+ case PublicKeyAlgorithmTag.RsaEncrypt:
+ case PublicKeyAlgorithmTag.RsaGeneral:
+ case PublicKeyAlgorithmTag.RsaSign:
+ RsaPublicBcpgKey rsaPub = (RsaPublicBcpgKey)pubPk.Key;
+ RsaSecretBcpgKey rsaPriv = new RsaSecretBcpgKey(bcpgIn);
+ RsaPrivateCrtKeyParameters rsaPrivSpec = new RsaPrivateCrtKeyParameters(
+ rsaPriv.Modulus,
+ rsaPub.PublicExponent,
+ rsaPriv.PrivateExponent,
+ rsaPriv.PrimeP,
+ rsaPriv.PrimeQ,
+ rsaPriv.PrimeExponentP,
+ rsaPriv.PrimeExponentQ,
+ rsaPriv.CrtCoefficient);
+ privateKey = rsaPrivSpec;
+ break;
+ case PublicKeyAlgorithmTag.Dsa:
+ DsaPublicBcpgKey dsaPub = (DsaPublicBcpgKey)pubPk.Key;
+ DsaSecretBcpgKey dsaPriv = new DsaSecretBcpgKey(bcpgIn);
+ DsaParameters dsaParams = new DsaParameters(dsaPub.P, dsaPub.Q, dsaPub.G);
+ privateKey = new DsaPrivateKeyParameters(dsaPriv.X, dsaParams);
+ break;
+ case PublicKeyAlgorithmTag.ElGamalEncrypt:
+ case PublicKeyAlgorithmTag.ElGamalGeneral:
+ ElGamalPublicBcpgKey elPub = (ElGamalPublicBcpgKey)pubPk.Key;
+ ElGamalSecretBcpgKey elPriv = new ElGamalSecretBcpgKey(bcpgIn);
+ ElGamalParameters elParams = new ElGamalParameters(elPub.P, elPub.G);
+ privateKey = new ElGamalPrivateKeyParameters(elPriv.X, elParams);
+ break;
+ default:
+ throw new PgpException("unknown public key algorithm encountered");
+ }
+
+ return new PgpPrivateKey(privateKey, KeyId);
+ }
+ catch (PgpException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("Exception constructing key", e);
+ }
+ }
+
+ private static byte[] Checksum(
+ bool useSha1,
+ byte[] bytes,
+ int length)
+ {
+ if (useSha1)
+ {
+ try
+ {
+ IDigest dig = DigestUtilities.GetDigest("SHA1");
+ dig.BlockUpdate(bytes, 0, length);
+ return DigestUtilities.DoFinal(dig);
+ }
+ //catch (NoSuchAlgorithmException e)
+ catch (Exception e)
+ {
+ throw new PgpException("Can't find SHA-1", e);
+ }
+ }
+ else
+ {
+ int Checksum = 0;
+ for (int i = 0; i != length; i++)
+ {
+ Checksum += bytes[i];
+ }
+
+ return new byte[] { (byte)(Checksum >> 8), (byte)Checksum };
+ }
+ }
+
+ public byte[] GetEncoded()
+ {
+ MemoryStream bOut = new MemoryStream();
+ Encode(bOut);
+ return bOut.ToArray();
+ }
+
+ public void Encode(
+ Stream outStr)
+ {
+ BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr);
+
+ bcpgOut.WritePacket(secret);
+ if (pub.trustPk != null)
+ {
+ bcpgOut.WritePacket(pub.trustPk);
+ }
+
+ if (pub.subSigs == null) // is not a sub key
+ {
+ foreach (PgpSignature keySig in pub.keySigs)
+ {
+ keySig.Encode(bcpgOut);
+ }
+
+ for (int i = 0; i != pub.ids.Count; i++)
+ {
+ object pubID = pub.ids[i];
+ if (pubID is string)
+ {
+ string id = (string) pubID;
+ bcpgOut.WritePacket(new UserIdPacket(id));
+ }
+ else
+ {
+ PgpUserAttributeSubpacketVector v = (PgpUserAttributeSubpacketVector) pubID;
+ bcpgOut.WritePacket(new UserAttributePacket(v.ToSubpacketArray()));
+ }
+
+ if (pub.idTrusts[i] != null)
+ {
+ bcpgOut.WritePacket((ContainedPacket)pub.idTrusts[i]);
+ }
+
+ foreach (PgpSignature sig in (ArrayList) pub.idSigs[i])
+ {
+ sig.Encode(bcpgOut);
+ }
+ }
+ }
+ else
+ {
+ foreach (PgpSignature subSig in pub.subSigs)
+ {
+ subSig.Encode(bcpgOut);
+ }
+ }
+
+ // TODO Check that this is right/necessary
+ //bcpgOut.Finish();
+ }
+
+ ///
+ /// Return a copy of the passed in secret key, encrypted using a new password
+ /// and the passed in algorithm.
+ ///
+ /// The PgpSecretKey to be copied.
+ /// The current password for the key.
+ /// The new password for the key.
+ /// The algorithm to be used for the encryption.
+ /// Source of randomness.
+ public static PgpSecretKey CopyWithNewPassword(
+ PgpSecretKey key,
+ char[] oldPassPhrase,
+ char[] newPassPhrase,
+ SymmetricKeyAlgorithmTag newEncAlgorithm,
+ SecureRandom rand)
+ {
+ byte[] rawKeyData = key.ExtractKeyData(oldPassPhrase);
+ int s2kUsage = key.secret.S2kUsage;
+ byte[] iv = null;
+ S2k s2k = null;
+ byte[] keyData;
+
+ if (newEncAlgorithm == SymmetricKeyAlgorithmTag.Null)
+ {
+ s2kUsage = SecretKeyPacket.UsageNone;
+ if (key.secret.S2kUsage == SecretKeyPacket.UsageSha1) // SHA-1 hash, need to rewrite Checksum
+ {
+ keyData = new byte[rawKeyData.Length - 18];
+
+ Array.Copy(rawKeyData, 0, keyData, 0, keyData.Length - 2);
+
+ byte[] check = Checksum(false, keyData, keyData.Length - 2);
+
+ keyData[keyData.Length - 2] = check[0];
+ keyData[keyData.Length - 1] = check[1];
+ }
+ else
+ {
+ keyData = rawKeyData;
+ }
+ }
+ else
+ {
+ try
+ {
+ keyData = EncryptKeyData(rawKeyData, newEncAlgorithm, newPassPhrase, rand, out s2k, out iv);
+ }
+ catch (PgpException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("Exception encrypting key", e);
+ }
+ }
+
+ SecretKeyPacket secret;
+ if (key.secret is SecretSubkeyPacket)
+ {
+ secret = new SecretSubkeyPacket(key.secret.PublicKeyPacket,
+ newEncAlgorithm, s2kUsage, s2k, iv, keyData);
+ }
+ else
+ {
+ secret = new SecretKeyPacket(key.secret.PublicKeyPacket,
+ newEncAlgorithm, s2kUsage, s2k, iv, keyData);
+ }
+
+ return new PgpSecretKey(secret, key.pub);
+ }
+
+ /// Replace the passed the public key on the passed in secret key.
+ /// Secret key to change.
+ /// New public key.
+ /// A new secret key.
+ /// If KeyId's do not match.
+ public static PgpSecretKey ReplacePublicKey(
+ PgpSecretKey secretKey,
+ PgpPublicKey publicKey)
+ {
+ if (publicKey.KeyId != secretKey.KeyId)
+ throw new ArgumentException("KeyId's do not match");
+
+ return new PgpSecretKey(secretKey.secret, publicKey);
+ }
+
+ private static byte[] EncryptKeyData(
+ byte[] rawKeyData,
+ SymmetricKeyAlgorithmTag encAlgorithm,
+ char[] passPhrase,
+ SecureRandom random,
+ out S2k s2k,
+ out byte[] iv)
+ {
+ IBufferedCipher c;
+ try
+ {
+ string cName = PgpUtilities.GetSymmetricCipherName(encAlgorithm);
+ c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding");
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("Exception creating cipher", e);
+ }
+
+ byte[] s2kIV = new byte[8];
+ random.NextBytes(s2kIV);
+ s2k = new S2k(HashAlgorithmTag.Sha1, s2kIV, 0x60);
+
+ KeyParameter kp = PgpUtilities.MakeKeyFromPassPhrase(encAlgorithm, s2k, passPhrase);
+
+ iv = new byte[c.GetBlockSize()];
+ random.NextBytes(iv);
+
+ c.Init(true, new ParametersWithRandom(new ParametersWithIV(kp, iv), random));
+
+ return c.DoFinal(rawKeyData);
+ }
+ }
+}
diff --git a/src/core/srcbc/openpgp/PgpSecretKeyRing.cs b/src/core/srcbc/openpgp/PgpSecretKeyRing.cs
index b6fa630..2973d5a 100644
--- a/src/core/srcbc/openpgp/PgpSecretKeyRing.cs
+++ b/src/core/srcbc/openpgp/PgpSecretKeyRing.cs
@@ -1,208 +1,308 @@
-using System;
-using System.Collections;
-using System.IO;
-
-using Org.BouncyCastle.Utilities.Collections;
-
-namespace Org.BouncyCastle.Bcpg.OpenPgp
-{
- ///
- /// Class to hold a single master secret key and its subkeys.
- ///
- /// Often PGP keyring files consist of multiple master keys, if you are trying to process
- /// or construct one of these you should use the PgpSecretKeyRingBundle class.
- ///
- ///
- public class PgpSecretKeyRing
- : PgpKeyRing
- {
- private readonly ArrayList keys;
-
- internal PgpSecretKeyRing(
- ArrayList keys)
- {
- this.keys = keys;
- }
-
- public PgpSecretKeyRing(
- byte[] encoding)
- : this(new MemoryStream(encoding))
- {
- }
-
- public PgpSecretKeyRing(
- Stream inputStream)
- {
- this.keys = new ArrayList();
-
- BcpgInputStream bcpgInput = BcpgInputStream.Wrap(inputStream);
-
- PacketTag initialTag = bcpgInput.NextPacketTag();
- if (initialTag != PacketTag.SecretKey && initialTag != PacketTag.SecretSubkey)
- {
- throw new IOException("secret key ring doesn't start with secret key tag: "
- + "tag 0x" + ((int)initialTag).ToString("X"));
- }
-
- SecretKeyPacket secret = (SecretKeyPacket) bcpgInput.ReadPacket();
-
- //
- // ignore GPG comment packets if found.
- //
- while (bcpgInput.NextPacketTag() == PacketTag.Experimental2)
- {
- bcpgInput.ReadPacket();
- }
-
- TrustPacket trust = ReadOptionalTrustPacket(bcpgInput);
-
- // revocation and direct signatures
- ArrayList keySigs = ReadSignaturesAndTrust(bcpgInput);
-
- ArrayList ids, idTrusts, idSigs;
- ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs);
-
- keys.Add(new PgpSecretKey(secret, trust, keySigs, ids, idTrusts, idSigs));
-
-
- // Read subkeys
- while (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey)
- {
- SecretSubkeyPacket sub = (SecretSubkeyPacket) bcpgInput.ReadPacket();
-
- //
- // ignore GPG comment packets if found.
- //
- while (bcpgInput.NextPacketTag() == PacketTag.Experimental2)
- {
- bcpgInput.ReadPacket();
- }
-
- TrustPacket subTrust = ReadOptionalTrustPacket(bcpgInput);
- ArrayList sigList = ReadSignaturesAndTrust(bcpgInput);
-
- keys.Add(new PgpSecretKey(sub, subTrust, sigList));
- }
- }
-
- /// Return the public key for the master key.
- public PgpPublicKey GetPublicKey()
- {
- return ((PgpSecretKey) keys[0]).PublicKey;
- }
-
- /// Return the master private key.
- public PgpSecretKey GetSecretKey()
- {
- return (PgpSecretKey) keys[0];
- }
-
- /// Allows enumeration of the secret keys.
- /// An IEnumerable of PgpSecretKey objects.
- public IEnumerable GetSecretKeys()
- {
- return new EnumerableProxy(keys);
- }
-
- public PgpSecretKey GetSecretKey(
- long keyId)
- {
- foreach (PgpSecretKey k in keys)
- {
- if (keyId == k.KeyId)
- {
- return k;
- }
- }
-
- return null;
- }
-
- public byte[] GetEncoded()
- {
- MemoryStream bOut = new MemoryStream();
-
- Encode(bOut);
-
- return bOut.ToArray();
- }
-
- public void Encode(
- Stream outStr)
- {
- if (outStr == null)
- throw new ArgumentNullException("outStr");
-
- foreach (PgpSecretKey k in keys)
- {
- k.Encode(outStr);
- }
- }
-
- ///
- /// Returns a new key ring with the secret key passed in either added or
- /// replacing an existing one with the same key ID.
- ///
- /// The secret key ring to be modified.
- /// The secret key to be inserted.
- /// A new PgpSecretKeyRing
- public static PgpSecretKeyRing InsertSecretKey(
- PgpSecretKeyRing secRing,
- PgpSecretKey secKey)
- {
- ArrayList keys = new ArrayList(secRing.keys);
- bool found = false;
- bool masterFound = false;
-
- for (int i = 0; i != keys.Count; i++)
- {
- PgpSecretKey key = (PgpSecretKey) keys[i];
-
- if (key.KeyId == secKey.KeyId)
- {
- found = true;
- keys[i] = secKey;
- }
- if (key.IsMasterKey)
- {
- masterFound = true;
- }
- }
-
- if (!found)
- {
- if (secKey.IsMasterKey && masterFound)
- throw new ArgumentException("cannot add a master key to a ring that already has one");
-
- keys.Add(secKey);
- }
-
- return new PgpSecretKeyRing(keys);
- }
-
- /// Returns a new key ring with the secret key passed in removed from the key ring.
- /// The secret key ring to be modified.
- /// The secret key to be removed.
- /// A new PgpSecretKeyRing, or null if secKey is not found.
- public static PgpSecretKeyRing RemoveSecretKey(
- PgpSecretKeyRing secRing,
- PgpSecretKey secKey)
- {
- ArrayList keys = new ArrayList(secRing.keys);
- bool found = false;
-
- for (int i = 0; i < keys.Count; i++)
- {
- PgpSecretKey key = (PgpSecretKey)keys[i];
-
- if (key.KeyId == secKey.KeyId)
- {
- found = true;
- keys.RemoveAt(i);
- }
- }
-
- return found ? new PgpSecretKeyRing(keys) : null;
- }
- }
-}
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+ ///
+ /// Class to hold a single master secret key and its subkeys.
+ ///
+ /// Often PGP keyring files consist of multiple master keys, if you are trying to process
+ /// or construct one of these you should use the PgpSecretKeyRingBundle class.
+ ///
+ ///
+ public class PgpSecretKeyRing
+ : PgpKeyRing
+ {
+ private readonly IList keys;
+ private readonly IList extraPubKeys;
+
+ internal PgpSecretKeyRing(
+ IList keys)
+ : this(keys, new ArrayList())
+ {
+ }
+
+ private PgpSecretKeyRing(
+ IList keys,
+ IList extraPubKeys)
+ {
+ this.keys = keys;
+ this.extraPubKeys = extraPubKeys;
+ }
+
+ public PgpSecretKeyRing(
+ byte[] encoding)
+ : this(new MemoryStream(encoding))
+ {
+ }
+
+ public PgpSecretKeyRing(
+ Stream inputStream)
+ {
+ this.keys = new ArrayList();
+ this.extraPubKeys = new ArrayList();
+
+ BcpgInputStream bcpgInput = BcpgInputStream.Wrap(inputStream);
+
+ PacketTag initialTag = bcpgInput.NextPacketTag();
+ if (initialTag != PacketTag.SecretKey && initialTag != PacketTag.SecretSubkey)
+ {
+ throw new IOException("secret key ring doesn't start with secret key tag: "
+ + "tag 0x" + ((int)initialTag).ToString("X"));
+ }
+
+ SecretKeyPacket secret = (SecretKeyPacket) bcpgInput.ReadPacket();
+
+ //
+ // ignore GPG comment packets if found.
+ //
+ while (bcpgInput.NextPacketTag() == PacketTag.Experimental2)
+ {
+ bcpgInput.ReadPacket();
+ }
+
+ TrustPacket trust = ReadOptionalTrustPacket(bcpgInput);
+
+ // revocation and direct signatures
+ ArrayList keySigs = ReadSignaturesAndTrust(bcpgInput);
+
+ ArrayList ids, idTrusts, idSigs;
+ ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs);
+
+ keys.Add(new PgpSecretKey(secret, new PgpPublicKey(secret.PublicKeyPacket, trust, keySigs, ids, idTrusts, idSigs)));
+
+
+ // Read subkeys
+ while (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey
+ || bcpgInput.NextPacketTag() == PacketTag.PublicSubkey)
+ {
+ if (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey)
+ {
+ SecretSubkeyPacket sub = (SecretSubkeyPacket) bcpgInput.ReadPacket();
+
+ //
+ // ignore GPG comment packets if found.
+ //
+ while (bcpgInput.NextPacketTag() == PacketTag.Experimental2)
+ {
+ bcpgInput.ReadPacket();
+ }
+
+ TrustPacket subTrust = ReadOptionalTrustPacket(bcpgInput);
+ ArrayList sigList = ReadSignaturesAndTrust(bcpgInput);
+
+ keys.Add(new PgpSecretKey(sub, new PgpPublicKey(sub.PublicKeyPacket, subTrust, sigList)));
+ }
+ else
+ {
+ PublicSubkeyPacket sub = (PublicSubkeyPacket) bcpgInput.ReadPacket();
+
+ TrustPacket subTrust = ReadOptionalTrustPacket(bcpgInput);
+ ArrayList sigList = ReadSignaturesAndTrust(bcpgInput);
+
+ extraPubKeys.Add(new PgpPublicKey(sub, subTrust, sigList));
+ }
+ }
+ }
+
+ /// Return the public key for the master key.
+ public PgpPublicKey GetPublicKey()
+ {
+ return ((PgpSecretKey) keys[0]).PublicKey;
+ }
+
+ /// Return the master private key.
+ public PgpSecretKey GetSecretKey()
+ {
+ return (PgpSecretKey) keys[0];
+ }
+
+ /// Allows enumeration of the secret keys.
+ /// An IEnumerable of PgpSecretKey objects.
+ public IEnumerable GetSecretKeys()
+ {
+ return new EnumerableProxy(keys);
+ }
+
+ public PgpSecretKey GetSecretKey(
+ long keyId)
+ {
+ foreach (PgpSecretKey k in keys)
+ {
+ if (keyId == k.KeyId)
+ {
+ return k;
+ }
+ }
+
+ return null;
+ }
+
+ ///
+ /// Return an iterator of the public keys in the secret key ring that
+ /// have no matching private key. At the moment only personal certificate data
+ /// appears in this fashion.
+ ///
+ /// An IEnumerable of unattached, or extra, public keys.
+ public IEnumerable GetExtraPublicKeys()
+ {
+ return new EnumerableProxy(extraPubKeys);
+ }
+
+ public byte[] GetEncoded()
+ {
+ MemoryStream bOut = new MemoryStream();
+
+ Encode(bOut);
+
+ return bOut.ToArray();
+ }
+
+ public void Encode(
+ Stream outStr)
+ {
+ if (outStr == null)
+ throw new ArgumentNullException("outStr");
+
+ foreach (PgpSecretKey key in keys)
+ {
+ key.Encode(outStr);
+ }
+ foreach (PgpPublicKey extraPubKey in extraPubKeys)
+ {
+ extraPubKey.Encode(outStr);
+ }
+ }
+
+ ///
+ /// Replace the public key set on the secret ring with the corresponding key off the public ring.
+ ///
+ /// Secret ring to be changed.
+ /// Public ring containing the new public key set.
+ public static PgpSecretKeyRing ReplacePublicKeys(
+ PgpSecretKeyRing secretRing,
+ PgpPublicKeyRing publicRing)
+ {
+ IList newList = new ArrayList(secretRing.keys.Count);
+
+ foreach (PgpSecretKey sk in secretRing.keys)
+ {
+ PgpPublicKey pk = null;
+ try
+ {
+ pk = publicRing.GetPublicKey(sk.KeyId);
+ }
+ catch (PgpException e)
+ {
+ throw new InvalidOperationException(e.Message, e);
+ }
+
+ newList.Add(PgpSecretKey.ReplacePublicKey(sk, pk));
+ }
+
+ return new PgpSecretKeyRing(newList);
+ }
+
+ ///
+ /// Return a copy of the passed in secret key ring, with the master key and sub keys encrypted
+ /// using a new password and the passed in algorithm.
+ ///
+ /// The PgpSecretKeyRing to be copied.
+ /// The current password for key.
+ /// The new password for the key.
+ /// The algorithm to be used for the encryption.
+ /// Source of randomness.
+ public static PgpSecretKeyRing CopyWithNewPassword(
+ PgpSecretKeyRing ring,
+ char[] oldPassPhrase,
+ char[] newPassPhrase,
+ SymmetricKeyAlgorithmTag newEncAlgorithm,
+ SecureRandom rand)
+ {
+ IList newKeys = new ArrayList(ring.keys.Count);
+ foreach (PgpSecretKey secretKey in ring.GetSecretKeys())
+ {
+ newKeys.Add(PgpSecretKey.CopyWithNewPassword(secretKey, oldPassPhrase, newPassPhrase, newEncAlgorithm, rand));
+ }
+
+ return new PgpSecretKeyRing(newKeys, ring.extraPubKeys);
+ }
+
+ ///
+ /// Returns a new key ring with the secret key passed in either added or
+ /// replacing an existing one with the same key ID.
+ ///
+ /// The secret key ring to be modified.
+ /// The secret key to be inserted.
+ /// A new PgpSecretKeyRing
+ public static PgpSecretKeyRing InsertSecretKey(
+ PgpSecretKeyRing secRing,
+ PgpSecretKey secKey)
+ {
+ ArrayList keys = new ArrayList(secRing.keys);
+ bool found = false;
+ bool masterFound = false;
+
+ for (int i = 0; i != keys.Count; i++)
+ {
+ PgpSecretKey key = (PgpSecretKey) keys[i];
+
+ if (key.KeyId == secKey.KeyId)
+ {
+ found = true;
+ keys[i] = secKey;
+ }
+ if (key.IsMasterKey)
+ {
+ masterFound = true;
+ }
+ }
+
+ if (!found)
+ {
+ if (secKey.IsMasterKey)
+ {
+ if (masterFound)
+ throw new ArgumentException("cannot add a master key to a ring that already has one");
+
+ keys.Insert(0, secKey);
+ }
+ else
+ {
+ keys.Add(secKey);
+ }
+ }
+
+ return new PgpSecretKeyRing(keys, secRing.extraPubKeys);
+ }
+
+ /// Returns a new key ring with the secret key passed in removed from the key ring.
+ /// The secret key ring to be modified.
+ /// The secret key to be removed.
+ /// A new PgpSecretKeyRing, or null if secKey is not found.
+ public static PgpSecretKeyRing RemoveSecretKey(
+ PgpSecretKeyRing secRing,
+ PgpSecretKey secKey)
+ {
+ ArrayList keys = new ArrayList(secRing.keys);
+ bool found = false;
+
+ for (int i = 0; i < keys.Count; i++)
+ {
+ PgpSecretKey key = (PgpSecretKey)keys[i];
+
+ if (key.KeyId == secKey.KeyId)
+ {
+ found = true;
+ keys.RemoveAt(i);
+ }
+ }
+
+ return found ? new PgpSecretKeyRing(keys, secRing.extraPubKeys) : null;
+ }
+ }
+}
diff --git a/src/core/srcbc/openpgp/PgpSignature.cs b/src/core/srcbc/openpgp/PgpSignature.cs
index e40d431..cbe0d83 100644
--- a/src/core/srcbc/openpgp/PgpSignature.cs
+++ b/src/core/srcbc/openpgp/PgpSignature.cs
@@ -1,421 +1,422 @@
-using System;
-using System.IO;
-using Org.BouncyCastle.Asn1;
-
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Utilities;
-using Org.BouncyCastle.Utilities.Date;
-
-namespace Org.BouncyCastle.Bcpg.OpenPgp
-{
- /// A PGP signature object.
- public class PgpSignature
- {
- public const int BinaryDocument = 0x00;
- public const int CanonicalTextDocument = 0x01;
- public const int StandAlone = 0x02;
-
- public const int DefaultCertification = 0x10;
- public const int NoCertification = 0x11;
- public const int CasualCertification = 0x12;
- public const int PositiveCertification = 0x13;
-
- public const int SubkeyBinding = 0x18;
- public const int DirectKey = 0x1f;
- public const int KeyRevocation = 0x20;
- public const int SubkeyRevocation = 0x28;
- public const int CertificationRevocation = 0x30;
- public const int Timestamp = 0x40;
-
- private readonly SignaturePacket sigPck;
- private readonly int signatureType;
- private readonly TrustPacket trustPck;
-
- private ISigner sig;
- private byte lastb; // Initial value anything but '\r'
-
- internal PgpSignature(
- BcpgInputStream bcpgInput)
- : this((SignaturePacket)bcpgInput.ReadPacket())
- {
- }
-
- internal PgpSignature(
- SignaturePacket sigPacket)
- : this(sigPacket, null)
- {
- }
-
- internal PgpSignature(
- SignaturePacket sigPacket,
- TrustPacket trustPacket)
- {
- if (sigPacket == null)
- throw new ArgumentNullException("sigPacket");
-
- this.sigPck = sigPacket;
- this.signatureType = sigPck.SignatureType;
- this.trustPck = trustPacket;
- }
-
- private void GetSig()
- {
- this.sig = SignerUtilities.GetSigner(
- PgpUtilities.GetSignatureName(sigPck.KeyAlgorithm, sigPck.HashAlgorithm));
- }
-
- /// The OpenPGP version number for this signature.
- public int Version
- {
- get { return sigPck.Version; }
- }
-
- /// The key algorithm associated with this signature.
- public PublicKeyAlgorithmTag KeyAlgorithm
- {
- get { return sigPck.KeyAlgorithm; }
- }
-
- /// The hash algorithm associated with this signature.
- public HashAlgorithmTag HashAlgorithm
- {
- get { return sigPck.HashAlgorithm; }
- }
-
- public void InitVerify(
- PgpPublicKey pubKey)
- {
- lastb = 0;
- if (sig == null)
- {
- GetSig();
- }
- try
- {
- sig.Init(false, pubKey.GetKey());
- }
- catch (InvalidKeyException e)
- {
- throw new PgpException("invalid key.", e);
- }
- }
-
- public void Update(
- byte b)
- {
- if (signatureType == CanonicalTextDocument)
- {
- doCanonicalUpdateByte(b);
- }
- else
- {
- sig.Update(b);
- }
- }
-
- private void doCanonicalUpdateByte(
- byte b)
- {
- if (b == '\r')
- {
- doUpdateCRLF();
- }
- else if (b == '\n')
- {
- if (lastb != '\r')
- {
- doUpdateCRLF();
- }
- }
- else
- {
- sig.Update(b);
- }
-
- lastb = b;
- }
-
- private void doUpdateCRLF()
- {
- sig.Update((byte)'\r');
- sig.Update((byte)'\n');
- }
-
- public void Update(
- params byte[] bytes)
- {
- Update(bytes, 0, bytes.Length);
- }
-
- public void Update(
- byte[] bytes,
- int off,
- int length)
- {
- if (signatureType == CanonicalTextDocument)
- {
- int finish = off + length;
-
- for (int i = off; i != finish; i++)
- {
- doCanonicalUpdateByte(bytes[i]);
- }
- }
- else
- {
- sig.BlockUpdate(bytes, off, length);
- }
- }
-
- public bool Verify()
- {
- byte[] trailer = GetSignatureTrailer();
- sig.BlockUpdate(trailer, 0, trailer.Length);
-
- return sig.VerifySignature(GetSignature());
- }
-
- private void UpdateWithIdData(
- int header,
- byte[] idBytes)
- {
- this.Update(
- (byte) header,
- (byte)(idBytes.Length >> 24),
- (byte)(idBytes.Length >> 16),
- (byte)(idBytes.Length >> 8),
- (byte)(idBytes.Length));
- this.Update(idBytes);
- }
-
- private void UpdateWithPublicKey(
- PgpPublicKey key)
- {
- byte[] keyBytes = GetEncodedPublicKey(key);
-
- this.Update(
- (byte) 0x99,
- (byte)(keyBytes.Length >> 8),
- (byte)(keyBytes.Length));
- this.Update(keyBytes);
- }
-
- ///
- /// Verify the signature as certifying the passed in public key as associated
- /// with the passed in user attributes.
- ///
- /// User attributes the key was stored under.
- /// The key to be verified.
- /// True, if the signature matches, false otherwise.
- public bool VerifyCertification(
- PgpUserAttributeSubpacketVector userAttributes,
- PgpPublicKey key)
- {
- UpdateWithPublicKey(key);
-
- //
- // hash in the userAttributes
- //
- try
- {
- MemoryStream bOut = new MemoryStream();
- foreach (UserAttributeSubpacket packet in userAttributes.ToSubpacketArray())
- {
- packet.Encode(bOut);
- }
- UpdateWithIdData(0xd1, bOut.ToArray());
- }
- catch (IOException e)
- {
- throw new PgpException("cannot encode subpacket array", e);
- }
-
- this.Update(sigPck.GetSignatureTrailer());
-
- return sig.VerifySignature(this.GetSignature());
- }
-
- ///
- /// Verify the signature as certifying the passed in public key as associated
- /// with the passed in ID.
- ///
- /// ID the key was stored under.
- /// The key to be verified.
- /// True, if the signature matches, false otherwise.
- public bool VerifyCertification(
- string id,
- PgpPublicKey key)
- {
- UpdateWithPublicKey(key);
-
- //
- // hash in the id
- //
- UpdateWithIdData(0xb4, Strings.ToByteArray(id));
-
- Update(sigPck.GetSignatureTrailer());
-
- return sig.VerifySignature(GetSignature());
- }
-
- /// Verify a certification for the passed in key against the passed in master key.
- /// The key we are verifying against.
- /// The key we are verifying.
- /// True, if the certification is valid, false otherwise.
- public bool VerifyCertification(
- PgpPublicKey masterKey,
- PgpPublicKey pubKey)
- {
- UpdateWithPublicKey(masterKey);
- UpdateWithPublicKey(pubKey);
-
- Update(sigPck.GetSignatureTrailer());
-
- return sig.VerifySignature(GetSignature());
- }
-
- /// Verify a key certification, such as revocation, for the passed in key.
- /// The key we are checking.
- /// True, if the certification is valid, false otherwise.
- public bool VerifyCertification(
- PgpPublicKey pubKey)
- {
- if (SignatureType != KeyRevocation
- && SignatureType != SubkeyRevocation)
- {
- throw new InvalidOperationException("signature is not a key signature");
- }
-
- UpdateWithPublicKey(pubKey);
-
- Update(sigPck.GetSignatureTrailer());
-
- return sig.VerifySignature(GetSignature());
- }
-
- public int SignatureType
- {
- get { return sigPck.SignatureType; }
- }
-
- /// The ID of the key that created the signature.
- public long KeyId
- {
- get { return sigPck.KeyId; }
- }
-
- [Obsolete("Use 'CreationTime' property instead")]
- public DateTime GetCreationTime()
- {
- return CreationTime;
- }
-
- /// The creation time of this signature.
- public DateTime CreationTime
- {
- get { return DateTimeUtilities.UnixMsToDateTime(sigPck.CreationTime); }
- }
-
- public byte[] GetSignatureTrailer()
- {
- return sigPck.GetSignatureTrailer();
- }
-
- ///
- /// Return true if the signature has either hashed or unhashed subpackets.
- ///
- public bool HasSubpackets
- {
- get
- {
- return sigPck.GetHashedSubPackets() != null
- || sigPck.GetUnhashedSubPackets() != null;
- }
- }
-
- public PgpSignatureSubpacketVector GetHashedSubPackets()
- {
- return createSubpacketVector(sigPck.GetHashedSubPackets());
- }
-
- public PgpSignatureSubpacketVector GetUnhashedSubPackets()
- {
- return createSubpacketVector(sigPck.GetUnhashedSubPackets());
- }
-
- private PgpSignatureSubpacketVector createSubpacketVector(SignatureSubpacket[] pcks)
- {
- return pcks == null ? null : new PgpSignatureSubpacketVector(pcks);
- }
-
- public byte[] GetSignature()
- {
- MPInteger[] sigValues = sigPck.GetSignature();
- byte[] signature;
-
- if (sigValues != null)
- {
- if (sigValues.Length == 1) // an RSA signature
- {
- signature = sigValues[0].Value.ToByteArrayUnsigned();
- }
- else
- {
- try
- {
- signature = new DerSequence(
- new DerInteger(sigValues[0].Value),
- new DerInteger(sigValues[1].Value)).GetEncoded();
- }
- catch (IOException e)
- {
- throw new PgpException("exception encoding DSA sig.", e);
- }
- }
- }
- else
- {
- signature = sigPck.GetSignatureBytes();
- }
-
- return signature;
- }
-
- // TODO Handle the encoding stuff by subclassing BcpgObject?
- public byte[] GetEncoded()
- {
- MemoryStream bOut = new MemoryStream();
-
- Encode(bOut);
-
- return bOut.ToArray();
- }
-
- public void Encode(
- Stream outStream)
- {
- BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStream);
-
- bcpgOut.WritePacket(sigPck);
-
- if (trustPck != null)
- {
- bcpgOut.WritePacket(trustPck);
- }
- }
-
- private byte[] GetEncodedPublicKey(
- PgpPublicKey pubKey)
- {
- try
- {
- return pubKey.publicPk.GetEncodedContents();
- }
- catch (IOException e)
- {
- throw new PgpException("exception preparing key.", e);
- }
- }
- }
-}
+using System;
+using System.IO;
+using Org.BouncyCastle.Asn1;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+ /// A PGP signature object.
+ public class PgpSignature
+ {
+ public const int BinaryDocument = 0x00;
+ public const int CanonicalTextDocument = 0x01;
+ public const int StandAlone = 0x02;
+
+ public const int DefaultCertification = 0x10;
+ public const int NoCertification = 0x11;
+ public const int CasualCertification = 0x12;
+ public const int PositiveCertification = 0x13;
+
+ public const int SubkeyBinding = 0x18;
+ public const int PrimaryKeyBinding = 0x19;
+ public const int DirectKey = 0x1f;
+ public const int KeyRevocation = 0x20;
+ public const int SubkeyRevocation = 0x28;
+ public const int CertificationRevocation = 0x30;
+ public const int Timestamp = 0x40;
+
+ private readonly SignaturePacket sigPck;
+ private readonly int signatureType;
+ private readonly TrustPacket trustPck;
+
+ private ISigner sig;
+ private byte lastb; // Initial value anything but '\r'
+
+ internal PgpSignature(
+ BcpgInputStream bcpgInput)
+ : this((SignaturePacket)bcpgInput.ReadPacket())
+ {
+ }
+
+ internal PgpSignature(
+ SignaturePacket sigPacket)
+ : this(sigPacket, null)
+ {
+ }
+
+ internal PgpSignature(
+ SignaturePacket sigPacket,
+ TrustPacket trustPacket)
+ {
+ if (sigPacket == null)
+ throw new ArgumentNullException("sigPacket");
+
+ this.sigPck = sigPacket;
+ this.signatureType = sigPck.SignatureType;
+ this.trustPck = trustPacket;
+ }
+
+ private void GetSig()
+ {
+ this.sig = SignerUtilities.GetSigner(
+ PgpUtilities.GetSignatureName(sigPck.KeyAlgorithm, sigPck.HashAlgorithm));
+ }
+
+ /// The OpenPGP version number for this signature.
+ public int Version
+ {
+ get { return sigPck.Version; }
+ }
+
+ /// The key algorithm associated with this signature.
+ public PublicKeyAlgorithmTag KeyAlgorithm
+ {
+ get { return sigPck.KeyAlgorithm; }
+ }
+
+ /// The hash algorithm associated with this signature.
+ public HashAlgorithmTag HashAlgorithm
+ {
+ get { return sigPck.HashAlgorithm; }
+ }
+
+ public void InitVerify(
+ PgpPublicKey pubKey)
+ {
+ lastb = 0;
+ if (sig == null)
+ {
+ GetSig();
+ }
+ try
+ {
+ sig.Init(false, pubKey.GetKey());
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new PgpException("invalid key.", e);
+ }
+ }
+
+ public void Update(
+ byte b)
+ {
+ if (signatureType == CanonicalTextDocument)
+ {
+ doCanonicalUpdateByte(b);
+ }
+ else
+ {
+ sig.Update(b);
+ }
+ }
+
+ private void doCanonicalUpdateByte(
+ byte b)
+ {
+ if (b == '\r')
+ {
+ doUpdateCRLF();
+ }
+ else if (b == '\n')
+ {
+ if (lastb != '\r')
+ {
+ doUpdateCRLF();
+ }
+ }
+ else
+ {
+ sig.Update(b);
+ }
+
+ lastb = b;
+ }
+
+ private void doUpdateCRLF()
+ {
+ sig.Update((byte)'\r');
+ sig.Update((byte)'\n');
+ }
+
+ public void Update(
+ params byte[] bytes)
+ {
+ Update(bytes, 0, bytes.Length);
+ }
+
+ public void Update(
+ byte[] bytes,
+ int off,
+ int length)
+ {
+ if (signatureType == CanonicalTextDocument)
+ {
+ int finish = off + length;
+
+ for (int i = off; i != finish; i++)
+ {
+ doCanonicalUpdateByte(bytes[i]);
+ }
+ }
+ else
+ {
+ sig.BlockUpdate(bytes, off, length);
+ }
+ }
+
+ public bool Verify()
+ {
+ byte[] trailer = GetSignatureTrailer();
+ sig.BlockUpdate(trailer, 0, trailer.Length);
+
+ return sig.VerifySignature(GetSignature());
+ }
+
+ private void UpdateWithIdData(
+ int header,
+ byte[] idBytes)
+ {
+ this.Update(
+ (byte) header,
+ (byte)(idBytes.Length >> 24),
+ (byte)(idBytes.Length >> 16),
+ (byte)(idBytes.Length >> 8),
+ (byte)(idBytes.Length));
+ this.Update(idBytes);
+ }
+
+ private void UpdateWithPublicKey(
+ PgpPublicKey key)
+ {
+ byte[] keyBytes = GetEncodedPublicKey(key);
+
+ this.Update(
+ (byte) 0x99,
+ (byte)(keyBytes.Length >> 8),
+ (byte)(keyBytes.Length));
+ this.Update(keyBytes);
+ }
+
+ ///
+ /// Verify the signature as certifying the passed in public key as associated
+ /// with the passed in user attributes.
+ ///
+ /// User attributes the key was stored under.
+ /// The key to be verified.
+ /// True, if the signature matches, false otherwise.
+ public bool VerifyCertification(
+ PgpUserAttributeSubpacketVector userAttributes,
+ PgpPublicKey key)
+ {
+ UpdateWithPublicKey(key);
+
+ //
+ // hash in the userAttributes
+ //
+ try
+ {
+ MemoryStream bOut = new MemoryStream();
+ foreach (UserAttributeSubpacket packet in userAttributes.ToSubpacketArray())
+ {
+ packet.Encode(bOut);
+ }
+ UpdateWithIdData(0xd1, bOut.ToArray());
+ }
+ catch (IOException e)
+ {
+ throw new PgpException("cannot encode subpacket array", e);
+ }
+
+ this.Update(sigPck.GetSignatureTrailer());
+
+ return sig.VerifySignature(this.GetSignature());
+ }
+
+ ///
+ /// Verify the signature as certifying the passed in public key as associated
+ /// with the passed in ID.
+ ///
+ /// ID the key was stored under.
+ /// The key to be verified.
+ /// True, if the signature matches, false otherwise.
+ public bool VerifyCertification(
+ string id,
+ PgpPublicKey key)
+ {
+ UpdateWithPublicKey(key);
+
+ //
+ // hash in the id
+ //
+ UpdateWithIdData(0xb4, Strings.ToByteArray(id));
+
+ Update(sigPck.GetSignatureTrailer());
+
+ return sig.VerifySignature(GetSignature());
+ }
+
+ /// Verify a certification for the passed in key against the passed in master key.
+ /// The key we are verifying against.
+ /// The key we are verifying.
+ /// True, if the certification is valid, false otherwise.
+ public bool VerifyCertification(
+ PgpPublicKey masterKey,
+ PgpPublicKey pubKey)
+ {
+ UpdateWithPublicKey(masterKey);
+ UpdateWithPublicKey(pubKey);
+
+ Update(sigPck.GetSignatureTrailer());
+
+ return sig.VerifySignature(GetSignature());
+ }
+
+ /// Verify a key certification, such as revocation, for the passed in key.
+ /// The key we are checking.
+ /// True, if the certification is valid, false otherwise.
+ public bool VerifyCertification(
+ PgpPublicKey pubKey)
+ {
+ if (SignatureType != KeyRevocation
+ && SignatureType != SubkeyRevocation)
+ {
+ throw new InvalidOperationException("signature is not a key signature");
+ }
+
+ UpdateWithPublicKey(pubKey);
+
+ Update(sigPck.GetSignatureTrailer());
+
+ return sig.VerifySignature(GetSignature());
+ }
+
+ public int SignatureType
+ {
+ get { return sigPck.SignatureType; }
+ }
+
+ /// The ID of the key that created the signature.
+ public long KeyId
+ {
+ get { return sigPck.KeyId; }
+ }
+
+ [Obsolete("Use 'CreationTime' property instead")]
+ public DateTime GetCreationTime()
+ {
+ return CreationTime;
+ }
+
+ /// The creation time of this signature.
+ public DateTime CreationTime
+ {
+ get { return DateTimeUtilities.UnixMsToDateTime(sigPck.CreationTime); }
+ }
+
+ public byte[] GetSignatureTrailer()
+ {
+ return sigPck.GetSignatureTrailer();
+ }
+
+ ///
+ /// Return true if the signature has either hashed or unhashed subpackets.
+ ///
+ public bool HasSubpackets
+ {
+ get
+ {
+ return sigPck.GetHashedSubPackets() != null
+ || sigPck.GetUnhashedSubPackets() != null;
+ }
+ }
+
+ public PgpSignatureSubpacketVector GetHashedSubPackets()
+ {
+ return createSubpacketVector(sigPck.GetHashedSubPackets());
+ }
+
+ public PgpSignatureSubpacketVector GetUnhashedSubPackets()
+ {
+ return createSubpacketVector(sigPck.GetUnhashedSubPackets());
+ }
+
+ private PgpSignatureSubpacketVector createSubpacketVector(SignatureSubpacket[] pcks)
+ {
+ return pcks == null ? null : new PgpSignatureSubpacketVector(pcks);
+ }
+
+ public byte[] GetSignature()
+ {
+ MPInteger[] sigValues = sigPck.GetSignature();
+ byte[] signature;
+
+ if (sigValues != null)
+ {
+ if (sigValues.Length == 1) // an RSA signature
+ {
+ signature = sigValues[0].Value.ToByteArrayUnsigned();
+ }
+ else
+ {
+ try
+ {
+ signature = new DerSequence(
+ new DerInteger(sigValues[0].Value),
+ new DerInteger(sigValues[1].Value)).GetEncoded();
+ }
+ catch (IOException e)
+ {
+ throw new PgpException("exception encoding DSA sig.", e);
+ }
+ }
+ }
+ else
+ {
+ signature = sigPck.GetSignatureBytes();
+ }
+
+ return signature;
+ }
+
+ // TODO Handle the encoding stuff by subclassing BcpgObject?
+ public byte[] GetEncoded()
+ {
+ MemoryStream bOut = new MemoryStream();
+
+ Encode(bOut);
+
+ return bOut.ToArray();
+ }
+
+ public void Encode(
+ Stream outStream)
+ {
+ BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStream);
+
+ bcpgOut.WritePacket(sigPck);
+
+ if (trustPck != null)
+ {
+ bcpgOut.WritePacket(trustPck);
+ }
+ }
+
+ private byte[] GetEncodedPublicKey(
+ PgpPublicKey pubKey)
+ {
+ try
+ {
+ return pubKey.publicPk.GetEncodedContents();
+ }
+ catch (IOException e)
+ {
+ throw new PgpException("exception preparing key.", e);
+ }
+ }
+ }
+}
diff --git a/src/core/srcbc/openpgp/PgpSignatureSubpacketGenerator.cs b/src/core/srcbc/openpgp/PgpSignatureSubpacketGenerator.cs
index 740d6ce..aca968c 100644
--- a/src/core/srcbc/openpgp/PgpSignatureSubpacketGenerator.cs
+++ b/src/core/srcbc/openpgp/PgpSignatureSubpacketGenerator.cs
@@ -1,141 +1,163 @@
-using System;
-using System.Collections;
-
-using Org.BouncyCastle.Bcpg.Sig;
-
-namespace Org.BouncyCastle.Bcpg.OpenPgp
-{
- /// Generator for signature subpackets.
- public class PgpSignatureSubpacketGenerator
- {
- private ArrayList list = new ArrayList();
-
- public void SetRevocable(
- bool isCritical,
- bool isRevocable)
- {
- list.Add(new Revocable(isCritical, isRevocable));
- }
-
- public void SetExportable(
- bool isCritical,
- bool isExportable)
- {
- list.Add(new Exportable(isCritical, isExportable));
- }
-
- ///
- /// Add a TrustSignature packet to the signature. The values for depth and trust are largely
- /// installation dependent but there are some guidelines in RFC 4880 - 5.2.3.13.
- ///
- /// true if the packet is critical.
- /// depth level.
- /// trust amount.
- public void SetTrust(
- bool isCritical,
- int depth,
- int trustAmount)
- {
- list.Add(new TrustSignature(isCritical, depth, trustAmount));
- }
-
- ///
- /// Set the number of seconds a key is valid for after the time of its creation.
- /// A value of zero means the key never expires.
- ///
- /// True, if should be treated as critical, false otherwise.
- /// The number of seconds the key is valid, or zero if no expiry.
- public void SetKeyExpirationTime(
- bool isCritical,
- long seconds)
- {
- list.Add(new KeyExpirationTime(isCritical, seconds));
- }
-
- ///
- /// Set the number of seconds a signature is valid for after the time of its creation.
- /// A value of zero means the signature never expires.
- ///
- /// True, if should be treated as critical, false otherwise.
- /// The number of seconds the signature is valid, or zero if no expiry.
- public void SetSignatureExpirationTime(
- bool isCritical,
- long seconds)
- {
- list.Add(new SignatureExpirationTime(isCritical, seconds));
- }
-
- ///
- /// Set the creation time for the signature.
- ///
- /// Note: this overrides the generation of a creation time when the signature
- /// is generated.
- ///
- public void SetSignatureCreationTime(
- bool isCritical,
- DateTime date)
- {
- list.Add(new SignatureCreationTime(isCritical, date));
- }
-
- public void SetPreferredHashAlgorithms(
- bool isCritical,
- int[] algorithms)
- {
- list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredHashAlgorithms, isCritical, algorithms));
- }
-
- public void SetPreferredSymmetricAlgorithms(
- bool isCritical,
- int[] algorithms)
- {
- list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredSymmetricAlgorithms, isCritical, algorithms));
- }
-
- public void SetPreferredCompressionAlgorithms(
- bool isCritical,
- int[] algorithms)
- {
- list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredCompressionAlgorithms, isCritical, algorithms));
- }
-
- public void SetKeyFlags(
- bool isCritical,
- int flags)
- {
- list.Add(new KeyFlags(isCritical, flags));
- }
-
- public void SetSignerUserId(
- bool isCritical,
- string userId)
- {
- if (userId == null)
- throw new ArgumentNullException("userId");
-
- list.Add(new SignerUserId(isCritical, userId));
- }
-
- public void SetPrimaryUserId(
- bool isCritical,
- bool isPrimaryUserId)
- {
- list.Add(new PrimaryUserId(isCritical, isPrimaryUserId));
- }
-
- public void SetNotationData(
- bool isCritical,
- bool isHumanReadable,
- string notationName,
- string notationValue)
- {
- list.Add(new NotationData(isCritical, isHumanReadable, notationName, notationValue));
- }
-
- public PgpSignatureSubpacketVector Generate()
- {
- return new PgpSignatureSubpacketVector(
- (SignatureSubpacket[]) list.ToArray(typeof(SignatureSubpacket)));
- }
- }
-}
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Bcpg.Sig;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+ /// Generator for signature subpackets.
+ public class PgpSignatureSubpacketGenerator
+ {
+ private ArrayList list = new ArrayList();
+
+ public void SetRevocable(
+ bool isCritical,
+ bool isRevocable)
+ {
+ list.Add(new Revocable(isCritical, isRevocable));
+ }
+
+ public void SetExportable(
+ bool isCritical,
+ bool isExportable)
+ {
+ list.Add(new Exportable(isCritical, isExportable));
+ }
+
+ ///
+ /// Add a TrustSignature packet to the signature. The values for depth and trust are largely
+ /// installation dependent but there are some guidelines in RFC 4880 - 5.2.3.13.
+ ///
+ /// true if the packet is critical.
+ /// depth level.
+ /// trust amount.
+ public void SetTrust(
+ bool isCritical,
+ int depth,
+ int trustAmount)
+ {
+ list.Add(new TrustSignature(isCritical, depth, trustAmount));
+ }
+
+ ///
+ /// Set the number of seconds a key is valid for after the time of its creation.
+ /// A value of zero means the key never expires.
+ ///
+ /// True, if should be treated as critical, false otherwise.
+ /// The number of seconds the key is valid, or zero if no expiry.
+ public void SetKeyExpirationTime(
+ bool isCritical,
+ long seconds)
+ {
+ list.Add(new KeyExpirationTime(isCritical, seconds));
+ }
+
+ ///
+ /// Set the number of seconds a signature is valid for after the time of its creation.
+ /// A value of zero means the signature never expires.
+ ///
+ /// True, if should be treated as critical, false otherwise.
+ /// The number of seconds the signature is valid, or zero if no expiry.
+ public void SetSignatureExpirationTime(
+ bool isCritical,
+ long seconds)
+ {
+ list.Add(new SignatureExpirationTime(isCritical, seconds));
+ }
+
+ ///
+ /// Set the creation time for the signature.
+ ///
+ /// Note: this overrides the generation of a creation time when the signature
+ /// is generated.
+ ///
+ public void SetSignatureCreationTime(
+ bool isCritical,
+ DateTime date)
+ {
+ list.Add(new SignatureCreationTime(isCritical, date));
+ }
+
+ public void SetPreferredHashAlgorithms(
+ bool isCritical,
+ int[] algorithms)
+ {
+ list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredHashAlgorithms, isCritical, algorithms));
+ }
+
+ public void SetPreferredSymmetricAlgorithms(
+ bool isCritical,
+ int[] algorithms)
+ {
+ list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredSymmetricAlgorithms, isCritical, algorithms));
+ }
+
+ public void SetPreferredCompressionAlgorithms(
+ bool isCritical,
+ int[] algorithms)
+ {
+ list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredCompressionAlgorithms, isCritical, algorithms));
+ }
+
+ public void SetKeyFlags(
+ bool isCritical,
+ int flags)
+ {
+ list.Add(new KeyFlags(isCritical, flags));
+ }
+
+ public void SetSignerUserId(
+ bool isCritical,
+ string userId)
+ {
+ if (userId == null)
+ throw new ArgumentNullException("userId");
+
+ list.Add(new SignerUserId(isCritical, userId));
+ }
+
+ public void SetEmbeddedSignature(
+ bool isCritical,
+ PgpSignature pgpSignature)
+ {
+ byte[] sig = pgpSignature.GetEncoded();
+ byte[] data;
+
+ // TODO Should be >= ?
+ if (sig.Length - 1 > 256)
+ {
+ data = new byte[sig.Length - 3];
+ }
+ else
+ {
+ data = new byte[sig.Length - 2];
+ }
+
+ Array.Copy(sig, sig.Length - data.Length, data, 0, data.Length);
+
+ list.Add(new EmbeddedSignature(isCritical, data));
+ }
+
+ public void SetPrimaryUserId(
+ bool isCritical,
+ bool isPrimaryUserId)
+ {
+ list.Add(new PrimaryUserId(isCritical, isPrimaryUserId));
+ }
+
+ public void SetNotationData(
+ bool isCritical,
+ bool isHumanReadable,
+ string notationName,
+ string notationValue)
+ {
+ list.Add(new NotationData(isCritical, isHumanReadable, notationName, notationValue));
+ }
+
+ public PgpSignatureSubpacketVector Generate()
+ {
+ return new PgpSignatureSubpacketVector(
+ (SignatureSubpacket[]) list.ToArray(typeof(SignatureSubpacket)));
+ }
+ }
+}
diff --git a/src/core/srcbc/pkcs/EncryptedPrivateKeyInfoFactory.cs b/src/core/srcbc/pkcs/EncryptedPrivateKeyInfoFactory.cs
index 67fcee3..b696934 100644
--- a/src/core/srcbc/pkcs/EncryptedPrivateKeyInfoFactory.cs
+++ b/src/core/srcbc/pkcs/EncryptedPrivateKeyInfoFactory.cs
@@ -1,75 +1,75 @@
-using System;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Asn1.Pkcs;
-using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Security;
-
-namespace Org.BouncyCastle.Pkcs
-{
- public sealed class EncryptedPrivateKeyInfoFactory
- {
- private EncryptedPrivateKeyInfoFactory()
- {
- }
-
- public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo(
- DerObjectIdentifier algorithm,
- char[] passPhrase,
- byte[] salt,
- int iterationCount,
- AsymmetricKeyParameter key)
- {
- return CreateEncryptedPrivateKeyInfo(
- algorithm.Id, passPhrase, salt, iterationCount,
- PrivateKeyInfoFactory.CreatePrivateKeyInfo(key));
- }
-
- public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo(
- string algorithm,
- char[] passPhrase,
- byte[] salt,
- int iterationCount,
- AsymmetricKeyParameter key)
- {
- return CreateEncryptedPrivateKeyInfo(
- algorithm, passPhrase, salt, iterationCount,
- PrivateKeyInfoFactory.CreatePrivateKeyInfo(key));
- }
-
- public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo(
- string algorithm,
- char[] passPhrase,
- byte[] salt,
- int iterationCount,
- PrivateKeyInfo keyInfo)
- {
- if (!PbeUtilities.IsPbeAlgorithm(algorithm))
- throw new ArgumentException("attempt to use non-Pbe algorithm with Pbe EncryptedPrivateKeyInfo generation");
-
- IBufferedCipher cipher = PbeUtilities.CreateEngine(algorithm) as IBufferedCipher;
-
- if (cipher == null)
- {
- // TODO Throw exception?
- }
-
- Asn1Encodable parameters = PbeUtilities.GenerateAlgorithmParameters(
- algorithm, salt, iterationCount);
-
- ICipherParameters keyParameters = PbeUtilities.GenerateCipherParameters(
- algorithm, passPhrase, parameters);
-
- cipher.Init(true, keyParameters);
-
- byte[] keyBytes = keyInfo.GetEncoded();
- byte[] encoding = cipher.DoFinal(keyBytes);
-
- DerObjectIdentifier oid = PbeUtilities.GetObjectIdentifier(algorithm);
- AlgorithmIdentifier algID = new AlgorithmIdentifier(oid, parameters);
-
- return new EncryptedPrivateKeyInfo(algID, encoding);
- }
- }
-}
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Pkcs
+{
+ public sealed class EncryptedPrivateKeyInfoFactory
+ {
+ private EncryptedPrivateKeyInfoFactory()
+ {
+ }
+
+ public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo(
+ DerObjectIdentifier algorithm,
+ char[] passPhrase,
+ byte[] salt,
+ int iterationCount,
+ AsymmetricKeyParameter key)
+ {
+ return CreateEncryptedPrivateKeyInfo(
+ algorithm.Id, passPhrase, salt, iterationCount,
+ PrivateKeyInfoFactory.CreatePrivateKeyInfo(key));
+ }
+
+ public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo(
+ string algorithm,
+ char[] passPhrase,
+ byte[] salt,
+ int iterationCount,
+ AsymmetricKeyParameter key)
+ {
+ return CreateEncryptedPrivateKeyInfo(
+ algorithm, passPhrase, salt, iterationCount,
+ PrivateKeyInfoFactory.CreatePrivateKeyInfo(key));
+ }
+
+ public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo(
+ string algorithm,
+ char[] passPhrase,
+ byte[] salt,
+ int iterationCount,
+ PrivateKeyInfo keyInfo)
+ {
+ if (!PbeUtilities.IsPbeAlgorithm(algorithm))
+ throw new ArgumentException("attempt to use non-PBE algorithm with PBE EncryptedPrivateKeyInfo generation");
+
+ IBufferedCipher cipher = PbeUtilities.CreateEngine(algorithm) as IBufferedCipher;
+
+ if (cipher == null)
+ {
+ // TODO Throw exception?
+ }
+
+ Asn1Encodable parameters = PbeUtilities.GenerateAlgorithmParameters(
+ algorithm, salt, iterationCount);
+
+ ICipherParameters keyParameters = PbeUtilities.GenerateCipherParameters(
+ algorithm, passPhrase, parameters);
+
+ cipher.Init(true, keyParameters);
+
+ byte[] keyBytes = keyInfo.GetEncoded();
+ byte[] encoding = cipher.DoFinal(keyBytes);
+
+ DerObjectIdentifier oid = PbeUtilities.GetObjectIdentifier(algorithm);
+ AlgorithmIdentifier algID = new AlgorithmIdentifier(oid, parameters);
+
+ return new EncryptedPrivateKeyInfo(algID, encoding);
+ }
+ }
+}
diff --git a/src/core/srcbc/security/AgreementUtilities.cs b/src/core/srcbc/security/AgreementUtilities.cs
index 704dbcc..4a40e61 100644
--- a/src/core/srcbc/security/AgreementUtilities.cs
+++ b/src/core/srcbc/security/AgreementUtilities.cs
@@ -1,99 +1,100 @@
-using System.Collections;
-using System.Globalization;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Asn1.X9;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Agreement;
-using Org.BouncyCastle.Crypto.Agreement.Kdf;
-using Org.BouncyCastle.Crypto.Digests;
-
-namespace Org.BouncyCastle.Security
-{
- ///
- /// Utility class for creating IBasicAgreement objects from their names/Oids
- ///
- public sealed class AgreementUtilities
- {
- private AgreementUtilities()
- {
- }
-
- private static readonly Hashtable algorithms = new Hashtable();
- // private static readonly Hashtable oids = new Hashtable();
-
- static AgreementUtilities()
- {
- //algorithms[X9ObjectIdentifiers.DHSinglePassCofactorDHSha1KdfScheme.Id] = ?;
- algorithms[X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme.Id] = "DHWITHSHA1KDF";
- //algorithms[X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme.Id] = ?;
- }
-
- public static IBasicAgreement GetBasicAgreement(
- DerObjectIdentifier oid)
- {
- return GetBasicAgreement(oid.Id);
- }
-
- public static IBasicAgreement GetBasicAgreement(
- string algorithm)
- {
- string upper = algorithm.ToUpper(CultureInfo.InvariantCulture);
- string mechanism = (string) algorithms[upper];
-
- if (mechanism == null)
- {
- mechanism = upper;
- }
-
- switch (mechanism)
- {
- case "DH":
- return new DHBasicAgreement();
- case "ECDH":
- return new ECDHBasicAgreement();
- case "ECDHC":
- return new ECDHCBasicAgreement();
- }
-
- throw new SecurityUtilityException("Basic Agreement " + algorithm + " not recognised.");
- }
-
- public static IBasicAgreement GetBasicAgreementWithKdf(
- DerObjectIdentifier oid,
- string wrapAlgorithm)
- {
- return GetBasicAgreementWithKdf(oid.Id, wrapAlgorithm);
- }
-
- public static IBasicAgreement GetBasicAgreementWithKdf(
- string agreeAlgorithm,
- string wrapAlgorithm)
- {
- string upper = agreeAlgorithm.ToUpper(CultureInfo.InvariantCulture);
- string mechanism = (string) algorithms[upper];
-
- if (mechanism == null)
- {
- mechanism = upper;
- }
-
- switch (mechanism)
- {
- case "DHWITHSHA1KDF":
- return new ECDHWithKdfBasicAgreement(
- wrapAlgorithm,
- new ECDHKekGenerator(
- new Sha1Digest()));
- }
-
- throw new SecurityUtilityException("Basic Agreement (with KDF) " + agreeAlgorithm + " not recognised.");
- }
-
- public static string GetAlgorithmName(
- DerObjectIdentifier oid)
- {
- return (string) algorithms[oid.Id];
- }
- }
-}
+using System.Collections;
+using System.Globalization;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Agreement.Kdf;
+using Org.BouncyCastle.Crypto.Digests;
+
+namespace Org.BouncyCastle.Security
+{
+ ///
+ /// Utility class for creating IBasicAgreement objects from their names/Oids
+ ///
+ public sealed class AgreementUtilities
+ {
+ private AgreementUtilities()
+ {
+ }
+
+ private static readonly Hashtable algorithms = new Hashtable();
+ // private static readonly Hashtable oids = new Hashtable();
+
+ static AgreementUtilities()
+ {
+ //algorithms[X9ObjectIdentifiers.DHSinglePassCofactorDHSha1KdfScheme.Id] = ?;
+ algorithms[X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme.Id] = "DHWITHSHA1KDF";
+ //algorithms[X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme.Id] = ?;
+ }
+
+ public static IBasicAgreement GetBasicAgreement(
+ DerObjectIdentifier oid)
+ {
+ return GetBasicAgreement(oid.Id);
+ }
+
+ public static IBasicAgreement GetBasicAgreement(
+ string algorithm)
+ {
+ string upper = algorithm.ToUpper(CultureInfo.InvariantCulture);
+ string mechanism = (string) algorithms[upper];
+
+ if (mechanism == null)
+ {
+ mechanism = upper;
+ }
+
+ switch (mechanism)
+ {
+ case "DH":
+ case "DIFFIEHELLMAN":
+ return new DHBasicAgreement();
+ case "ECDH":
+ return new ECDHBasicAgreement();
+ case "ECDHC":
+ return new ECDHCBasicAgreement();
+ }
+
+ throw new SecurityUtilityException("Basic Agreement " + algorithm + " not recognised.");
+ }
+
+ public static IBasicAgreement GetBasicAgreementWithKdf(
+ DerObjectIdentifier oid,
+ string wrapAlgorithm)
+ {
+ return GetBasicAgreementWithKdf(oid.Id, wrapAlgorithm);
+ }
+
+ public static IBasicAgreement GetBasicAgreementWithKdf(
+ string agreeAlgorithm,
+ string wrapAlgorithm)
+ {
+ string upper = agreeAlgorithm.ToUpper(CultureInfo.InvariantCulture);
+ string mechanism = (string) algorithms[upper];
+
+ if (mechanism == null)
+ {
+ mechanism = upper;
+ }
+
+ switch (mechanism)
+ {
+ case "DHWITHSHA1KDF":
+ return new ECDHWithKdfBasicAgreement(
+ wrapAlgorithm,
+ new ECDHKekGenerator(
+ new Sha1Digest()));
+ }
+
+ throw new SecurityUtilityException("Basic Agreement (with KDF) " + agreeAlgorithm + " not recognised.");
+ }
+
+ public static string GetAlgorithmName(
+ DerObjectIdentifier oid)
+ {
+ return (string) algorithms[oid.Id];
+ }
+ }
+}
diff --git a/src/core/srcbc/security/GeneratorUtilities.cs b/src/core/srcbc/security/GeneratorUtilities.cs
index 9e9df9a..0a4a0c5 100644
--- a/src/core/srcbc/security/GeneratorUtilities.cs
+++ b/src/core/srcbc/security/GeneratorUtilities.cs
@@ -1,352 +1,353 @@
-using System.Collections;
-using System.Globalization;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Asn1.CryptoPro;
-using Org.BouncyCastle.Asn1.Iana;
-using Org.BouncyCastle.Asn1.Kisa;
-using Org.BouncyCastle.Asn1.Nist;
-using Org.BouncyCastle.Asn1.Ntt;
-using Org.BouncyCastle.Asn1.Oiw;
-using Org.BouncyCastle.Asn1.Pkcs;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Generators;
-
-namespace Org.BouncyCastle.Security
-{
- public sealed class GeneratorUtilities
- {
- private GeneratorUtilities()
- {
- }
-
- private static readonly Hashtable kgAlgorithms = new Hashtable();
- private static readonly Hashtable kpgAlgorithms = new Hashtable();
-
- static GeneratorUtilities()
- {
- //
- // key generators.
- //
- AddKgAlgorithm("AES",
- "AESWRAP");
- AddKgAlgorithm("AES128",
- "2.16.840.1.101.3.4.2",
- NistObjectIdentifiers.IdAes128Cbc,
- NistObjectIdentifiers.IdAes128Cfb,
- NistObjectIdentifiers.IdAes128Ecb,
- NistObjectIdentifiers.IdAes128Ofb,
- NistObjectIdentifiers.IdAes128Wrap);
- AddKgAlgorithm("AES192",
- "2.16.840.1.101.3.4.22",
- NistObjectIdentifiers.IdAes192Cbc,
- NistObjectIdentifiers.IdAes192Cfb,
- NistObjectIdentifiers.IdAes192Ecb,
- NistObjectIdentifiers.IdAes192Ofb,
- NistObjectIdentifiers.IdAes192Wrap);
- AddKgAlgorithm("AES256",
- "2.16.840.1.101.3.4.42",
- NistObjectIdentifiers.IdAes256Cbc,
- NistObjectIdentifiers.IdAes256Cfb,
- NistObjectIdentifiers.IdAes256Ecb,
- NistObjectIdentifiers.IdAes256Ofb,
- NistObjectIdentifiers.IdAes256Wrap);
- AddKgAlgorithm("BLOWFISH");
- AddKgAlgorithm("CAMELLIA",
- "CAMELLIAWRAP");
- AddKgAlgorithm("CAMELLIA128",
- NttObjectIdentifiers.IdCamellia128Cbc,
- NttObjectIdentifiers.IdCamellia128Wrap);
- AddKgAlgorithm("CAMELLIA192",
- NttObjectIdentifiers.IdCamellia192Cbc,
- NttObjectIdentifiers.IdCamellia192Wrap);
- AddKgAlgorithm("CAMELLIA256",
- NttObjectIdentifiers.IdCamellia256Cbc,
- NttObjectIdentifiers.IdCamellia256Wrap);
- AddKgAlgorithm("CAST5",
- "1.2.840.113533.7.66.10");
- AddKgAlgorithm("CAST6");
- AddKgAlgorithm("DES",
- OiwObjectIdentifiers.DesCbc);
- AddKgAlgorithm("DESEDE",
- "DESEDEWRAP",
- PkcsObjectIdentifiers.IdAlgCms3DesWrap);
- AddKgAlgorithm("DESEDE3",
- PkcsObjectIdentifiers.DesEde3Cbc);
- AddKgAlgorithm("GOST28147",
- "GOST",
- "GOST-28147",
- CryptoProObjectIdentifiers.GostR28147Cbc);
- AddKgAlgorithm("HC128");
- AddKgAlgorithm("HC256");
- AddKgAlgorithm("IDEA",
- "1.3.6.1.4.1.188.7.1.1.2");
- AddKgAlgorithm("NOEKEON");
- AddKgAlgorithm("RC2",
- PkcsObjectIdentifiers.RC2Cbc,
- PkcsObjectIdentifiers.IdAlgCmsRC2Wrap);
- AddKgAlgorithm("RC4",
- "ARC4",
- "1.2.840.113549.3.4");
- AddKgAlgorithm("RC5",
- "RC5-32");
- AddKgAlgorithm("RC5-64");
- AddKgAlgorithm("RC6");
- AddKgAlgorithm("RIJNDAEL");
- AddKgAlgorithm("SALSA20");
- AddKgAlgorithm("SEED",
- KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap,
- KisaObjectIdentifiers.IdSeedCbc);
- AddKgAlgorithm("SERPENT");
- AddKgAlgorithm("SKIPJACK");
- AddKgAlgorithm("TEA");
- AddKgAlgorithm("TWOFISH");
- AddKgAlgorithm("VMPC");
- AddKgAlgorithm("VMPC-KSA3");
- AddKgAlgorithm("XTEA");
-
- //
- // HMac key generators
- //
- AddHMacKeyGenerator("MD2");
- AddHMacKeyGenerator("MD4");
- AddHMacKeyGenerator("MD5",
- IanaObjectIdentifiers.HmacMD5);
- AddHMacKeyGenerator("SHA1",
- PkcsObjectIdentifiers.IdHmacWithSha1,
- IanaObjectIdentifiers.HmacSha1);
- AddHMacKeyGenerator("SHA224",
- PkcsObjectIdentifiers.IdHmacWithSha224);
- AddHMacKeyGenerator("SHA256",
- PkcsObjectIdentifiers.IdHmacWithSha256);
- AddHMacKeyGenerator("SHA384",
- PkcsObjectIdentifiers.IdHmacWithSha384);
- AddHMacKeyGenerator("SHA512",
- PkcsObjectIdentifiers.IdHmacWithSha512);
- AddHMacKeyGenerator("RIPEMD128");
- AddHMacKeyGenerator("RIPEMD160",
- IanaObjectIdentifiers.HmacRipeMD160);
- AddHMacKeyGenerator("TIGER",
- IanaObjectIdentifiers.HmacTiger);
-
-
-
- //
- // key pair generators.
- //
- AddKpgAlgorithm("DH");
- AddKpgAlgorithm("DSA");
- AddKpgAlgorithm("EC");
- AddKpgAlgorithm("ECDH",
- "ECIES");
- AddKpgAlgorithm("ECDHC");
- AddKpgAlgorithm("ECDSA");
- AddKpgAlgorithm("ECGOST3410",
- "ECGOST-3410",
- "GOST-3410-2001");
- AddKpgAlgorithm("ELGAMAL");
- AddKpgAlgorithm("GOST3410",
- "GOST-3410",
- "GOST-3410-94");
- AddKpgAlgorithm("RSA",
- "1.2.840.113549.1.1.1");
- }
-
- private static void AddKgAlgorithm(
- string canonicalName,
- params object[] aliases)
- {
- kgAlgorithms[canonicalName] = canonicalName;
-
- foreach (object alias in aliases)
- {
- kgAlgorithms[alias.ToString()] = canonicalName;
- }
- }
-
- private static void AddKpgAlgorithm(
- string canonicalName,
- params object[] aliases)
- {
- kpgAlgorithms[canonicalName] = canonicalName;
-
- foreach (object alias in aliases)
- {
- kpgAlgorithms[alias.ToString()] = canonicalName;
- }
- }
-
- private static void AddHMacKeyGenerator(
- string algorithm,
- params object[] aliases)
- {
- string mainName = "HMAC" + algorithm;
-
- kgAlgorithms[mainName] = mainName;
- kgAlgorithms["HMAC-" + algorithm] = mainName;
- kgAlgorithms["HMAC/" + algorithm] = mainName;
-
- foreach (object alias in aliases)
- {
- kgAlgorithms[alias.ToString()] = mainName;
- }
- }
-
- // TODO Consider making this public
- internal static string GetCanonicalKeyGeneratorAlgorithm(
- string algorithm)
- {
- return (string) kgAlgorithms[algorithm.ToUpper(CultureInfo.InvariantCulture)];
- }
-
- // TODO Consider making this public
- internal static string GetCanonicalKeyPairGeneratorAlgorithm(
- string algorithm)
- {
- return (string) kpgAlgorithms[algorithm.ToUpper(CultureInfo.InvariantCulture)];
- }
-
- public static CipherKeyGenerator GetKeyGenerator(
- DerObjectIdentifier oid)
- {
- return GetKeyGenerator(oid.Id);
- }
-
- public static CipherKeyGenerator GetKeyGenerator(
- string algorithm)
- {
- string canonicalName = GetCanonicalKeyGeneratorAlgorithm(algorithm);
-
- if (canonicalName == null)
- throw new SecurityUtilityException("KeyGenerator " + algorithm + " not recognised.");
-
- switch (canonicalName)
- {
- case "DES":
- return new DesKeyGenerator(64);
- case "DESEDE":
- return new DesEdeKeyGenerator(128);
- case "DESEDE3":
- return new DesEdeKeyGenerator(192);
- case "AES":
- return new CipherKeyGenerator(192);
- case "AES128":
- return new CipherKeyGenerator(128);
- case "AES192":
- return new CipherKeyGenerator(192);
- case "AES256":
- return new CipherKeyGenerator(256);
- case "BLOWFISH":
- return new CipherKeyGenerator(448);
- case "CAMELLIA":
- return new CipherKeyGenerator(256);
- case "CAMELLIA128":
- return new CipherKeyGenerator(128);
- case "CAMELLIA192":
- return new CipherKeyGenerator(192);
- case "CAMELLIA256":
- return new CipherKeyGenerator(256);
- case "CAST5":
- return new CipherKeyGenerator(128);
- case "CAST6":
- return new CipherKeyGenerator(256);
- case "GOST28147":
- return new CipherKeyGenerator(256);
- case "HC128":
- return new CipherKeyGenerator(128);
- case "HC256":
- return new CipherKeyGenerator(256);
- case "HMACMD2":
- case "HMACMD4":
- case "HMACMD5":
- return new CipherKeyGenerator(128);
- case "HMACSHA1":
- return new CipherKeyGenerator(160);
- case "HMACSHA224":
- return new CipherKeyGenerator(224);
- case "HMACSHA256":
- return new CipherKeyGenerator(256);
- case "HMACSHA384":
- return new CipherKeyGenerator(384);
- case "HMACSHA512":
- return new CipherKeyGenerator(512);
- case "HMACRIPEMD128":
- return new CipherKeyGenerator(128);
- case "HMACRIPEMD160":
- return new CipherKeyGenerator(160);
- case "HMACTIGER":
- return new CipherKeyGenerator(192);
- case "IDEA":
- return new CipherKeyGenerator(128);
- case "NOEKEON":
- return new CipherKeyGenerator(128);
- case "RC2":
- case "RC4":
- case "RC5":
- return new CipherKeyGenerator(128);
- case "RC5-64":
- case "RC6":
- return new CipherKeyGenerator(256);
- case "RIJNDAEL":
- return new CipherKeyGenerator(192);
- case "SALSA20":
- return new CipherKeyGenerator(128);
- case "SEED":
- return new CipherKeyGenerator(128);
- case "SERPENT":
- return new CipherKeyGenerator(192);
- case "SKIPJACK":
- return new CipherKeyGenerator(80);
- case "TEA":
- case "XTEA":
- return new CipherKeyGenerator(128);
- case "TWOFISH":
- return new CipherKeyGenerator(256);
- case "VMPC":
- case "VMPC-KSA3":
- return new CipherKeyGenerator(128);
- }
-
- throw new SecurityUtilityException("KeyGenerator " + algorithm + " not recognised.");
- }
-
- public static IAsymmetricCipherKeyPairGenerator GetKeyPairGenerator(
- DerObjectIdentifier oid)
- {
- return GetKeyPairGenerator(oid.Id);
- }
-
- public static IAsymmetricCipherKeyPairGenerator GetKeyPairGenerator(
- string algorithm)
- {
- string canonicalName = GetCanonicalKeyPairGeneratorAlgorithm(algorithm);
-
- if (canonicalName == null)
- throw new SecurityUtilityException("KeyPairGenerator " + algorithm + " not recognised.");
-
- switch (canonicalName)
- {
- case "DH":
- return new DHKeyPairGenerator();
- case "DSA":
- return new DsaKeyPairGenerator();
- case "EC":
- case "ECDH":
- case "ECDHC":
- case "ECDSA":
- case "ECGOST3410":
- return new ECKeyPairGenerator(canonicalName);
- case "ELGAMAL":
- return new ElGamalKeyPairGenerator();
- case "GOST3410":
- return new Gost3410KeyPairGenerator();
- case "RSA":
- return new RsaKeyPairGenerator();
- default:
- break;
- }
-
- throw new SecurityUtilityException("KeyPairGenerator " + algorithm + " not recognised.");
- }
- }
-}
+using System.Collections;
+using System.Globalization;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Iana;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+
+namespace Org.BouncyCastle.Security
+{
+ public sealed class GeneratorUtilities
+ {
+ private GeneratorUtilities()
+ {
+ }
+
+ private static readonly Hashtable kgAlgorithms = new Hashtable();
+ private static readonly Hashtable kpgAlgorithms = new Hashtable();
+
+ static GeneratorUtilities()
+ {
+ //
+ // key generators.
+ //
+ AddKgAlgorithm("AES",
+ "AESWRAP");
+ AddKgAlgorithm("AES128",
+ "2.16.840.1.101.3.4.2",
+ NistObjectIdentifiers.IdAes128Cbc,
+ NistObjectIdentifiers.IdAes128Cfb,
+ NistObjectIdentifiers.IdAes128Ecb,
+ NistObjectIdentifiers.IdAes128Ofb,
+ NistObjectIdentifiers.IdAes128Wrap);
+ AddKgAlgorithm("AES192",
+ "2.16.840.1.101.3.4.22",
+ NistObjectIdentifiers.IdAes192Cbc,
+ NistObjectIdentifiers.IdAes192Cfb,
+ NistObjectIdentifiers.IdAes192Ecb,
+ NistObjectIdentifiers.IdAes192Ofb,
+ NistObjectIdentifiers.IdAes192Wrap);
+ AddKgAlgorithm("AES256",
+ "2.16.840.1.101.3.4.42",
+ NistObjectIdentifiers.IdAes256Cbc,
+ NistObjectIdentifiers.IdAes256Cfb,
+ NistObjectIdentifiers.IdAes256Ecb,
+ NistObjectIdentifiers.IdAes256Ofb,
+ NistObjectIdentifiers.IdAes256Wrap);
+ AddKgAlgorithm("BLOWFISH");
+ AddKgAlgorithm("CAMELLIA",
+ "CAMELLIAWRAP");
+ AddKgAlgorithm("CAMELLIA128",
+ NttObjectIdentifiers.IdCamellia128Cbc,
+ NttObjectIdentifiers.IdCamellia128Wrap);
+ AddKgAlgorithm("CAMELLIA192",
+ NttObjectIdentifiers.IdCamellia192Cbc,
+ NttObjectIdentifiers.IdCamellia192Wrap);
+ AddKgAlgorithm("CAMELLIA256",
+ NttObjectIdentifiers.IdCamellia256Cbc,
+ NttObjectIdentifiers.IdCamellia256Wrap);
+ AddKgAlgorithm("CAST5",
+ "1.2.840.113533.7.66.10");
+ AddKgAlgorithm("CAST6");
+ AddKgAlgorithm("DES",
+ OiwObjectIdentifiers.DesCbc);
+ AddKgAlgorithm("DESEDE",
+ "DESEDEWRAP",
+ PkcsObjectIdentifiers.IdAlgCms3DesWrap);
+ AddKgAlgorithm("DESEDE3",
+ PkcsObjectIdentifiers.DesEde3Cbc);
+ AddKgAlgorithm("GOST28147",
+ "GOST",
+ "GOST-28147",
+ CryptoProObjectIdentifiers.GostR28147Cbc);
+ AddKgAlgorithm("HC128");
+ AddKgAlgorithm("HC256");
+ AddKgAlgorithm("IDEA",
+ "1.3.6.1.4.1.188.7.1.1.2");
+ AddKgAlgorithm("NOEKEON");
+ AddKgAlgorithm("RC2",
+ PkcsObjectIdentifiers.RC2Cbc,
+ PkcsObjectIdentifiers.IdAlgCmsRC2Wrap);
+ AddKgAlgorithm("RC4",
+ "ARC4",
+ "1.2.840.113549.3.4");
+ AddKgAlgorithm("RC5",
+ "RC5-32");
+ AddKgAlgorithm("RC5-64");
+ AddKgAlgorithm("RC6");
+ AddKgAlgorithm("RIJNDAEL");
+ AddKgAlgorithm("SALSA20");
+ AddKgAlgorithm("SEED",
+ KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap,
+ KisaObjectIdentifiers.IdSeedCbc);
+ AddKgAlgorithm("SERPENT");
+ AddKgAlgorithm("SKIPJACK");
+ AddKgAlgorithm("TEA");
+ AddKgAlgorithm("TWOFISH");
+ AddKgAlgorithm("VMPC");
+ AddKgAlgorithm("VMPC-KSA3");
+ AddKgAlgorithm("XTEA");
+
+ //
+ // HMac key generators
+ //
+ AddHMacKeyGenerator("MD2");
+ AddHMacKeyGenerator("MD4");
+ AddHMacKeyGenerator("MD5",
+ IanaObjectIdentifiers.HmacMD5);
+ AddHMacKeyGenerator("SHA1",
+ PkcsObjectIdentifiers.IdHmacWithSha1,
+ IanaObjectIdentifiers.HmacSha1);
+ AddHMacKeyGenerator("SHA224",
+ PkcsObjectIdentifiers.IdHmacWithSha224);
+ AddHMacKeyGenerator("SHA256",
+ PkcsObjectIdentifiers.IdHmacWithSha256);
+ AddHMacKeyGenerator("SHA384",
+ PkcsObjectIdentifiers.IdHmacWithSha384);
+ AddHMacKeyGenerator("SHA512",
+ PkcsObjectIdentifiers.IdHmacWithSha512);
+ AddHMacKeyGenerator("RIPEMD128");
+ AddHMacKeyGenerator("RIPEMD160",
+ IanaObjectIdentifiers.HmacRipeMD160);
+ AddHMacKeyGenerator("TIGER",
+ IanaObjectIdentifiers.HmacTiger);
+
+
+
+ //
+ // key pair generators.
+ //
+ AddKpgAlgorithm("DH",
+ "DIFFIEHELLMAN");
+ AddKpgAlgorithm("DSA");
+ AddKpgAlgorithm("EC");
+ AddKpgAlgorithm("ECDH",
+ "ECIES");
+ AddKpgAlgorithm("ECDHC");
+ AddKpgAlgorithm("ECDSA");
+ AddKpgAlgorithm("ECGOST3410",
+ "ECGOST-3410",
+ "GOST-3410-2001");
+ AddKpgAlgorithm("ELGAMAL");
+ AddKpgAlgorithm("GOST3410",
+ "GOST-3410",
+ "GOST-3410-94");
+ AddKpgAlgorithm("RSA",
+ "1.2.840.113549.1.1.1");
+ }
+
+ private static void AddKgAlgorithm(
+ string canonicalName,
+ params object[] aliases)
+ {
+ kgAlgorithms[canonicalName] = canonicalName;
+
+ foreach (object alias in aliases)
+ {
+ kgAlgorithms[alias.ToString()] = canonicalName;
+ }
+ }
+
+ private static void AddKpgAlgorithm(
+ string canonicalName,
+ params object[] aliases)
+ {
+ kpgAlgorithms[canonicalName] = canonicalName;
+
+ foreach (object alias in aliases)
+ {
+ kpgAlgorithms[alias.ToString()] = canonicalName;
+ }
+ }
+
+ private static void AddHMacKeyGenerator(
+ string algorithm,
+ params object[] aliases)
+ {
+ string mainName = "HMAC" + algorithm;
+
+ kgAlgorithms[mainName] = mainName;
+ kgAlgorithms["HMAC-" + algorithm] = mainName;
+ kgAlgorithms["HMAC/" + algorithm] = mainName;
+
+ foreach (object alias in aliases)
+ {
+ kgAlgorithms[alias.ToString()] = mainName;
+ }
+ }
+
+ // TODO Consider making this public
+ internal static string GetCanonicalKeyGeneratorAlgorithm(
+ string algorithm)
+ {
+ return (string) kgAlgorithms[algorithm.ToUpper(CultureInfo.InvariantCulture)];
+ }
+
+ // TODO Consider making this public
+ internal static string GetCanonicalKeyPairGeneratorAlgorithm(
+ string algorithm)
+ {
+ return (string) kpgAlgorithms[algorithm.ToUpper(CultureInfo.InvariantCulture)];
+ }
+
+ public static CipherKeyGenerator GetKeyGenerator(
+ DerObjectIdentifier oid)
+ {
+ return GetKeyGenerator(oid.Id);
+ }
+
+ public static CipherKeyGenerator GetKeyGenerator(
+ string algorithm)
+ {
+ string canonicalName = GetCanonicalKeyGeneratorAlgorithm(algorithm);
+
+ if (canonicalName == null)
+ throw new SecurityUtilityException("KeyGenerator " + algorithm + " not recognised.");
+
+ switch (canonicalName)
+ {
+ case "DES":
+ return new DesKeyGenerator(64);
+ case "DESEDE":
+ return new DesEdeKeyGenerator(128);
+ case "DESEDE3":
+ return new DesEdeKeyGenerator(192);
+ case "AES":
+ return new CipherKeyGenerator(192);
+ case "AES128":
+ return new CipherKeyGenerator(128);
+ case "AES192":
+ return new CipherKeyGenerator(192);
+ case "AES256":
+ return new CipherKeyGenerator(256);
+ case "BLOWFISH":
+ return new CipherKeyGenerator(448);
+ case "CAMELLIA":
+ return new CipherKeyGenerator(256);
+ case "CAMELLIA128":
+ return new CipherKeyGenerator(128);
+ case "CAMELLIA192":
+ return new CipherKeyGenerator(192);
+ case "CAMELLIA256":
+ return new CipherKeyGenerator(256);
+ case "CAST5":
+ return new CipherKeyGenerator(128);
+ case "CAST6":
+ return new CipherKeyGenerator(256);
+ case "GOST28147":
+ return new CipherKeyGenerator(256);
+ case "HC128":
+ return new CipherKeyGenerator(128);
+ case "HC256":
+ return new CipherKeyGenerator(256);
+ case "HMACMD2":
+ case "HMACMD4":
+ case "HMACMD5":
+ return new CipherKeyGenerator(128);
+ case "HMACSHA1":
+ return new CipherKeyGenerator(160);
+ case "HMACSHA224":
+ return new CipherKeyGenerator(224);
+ case "HMACSHA256":
+ return new CipherKeyGenerator(256);
+ case "HMACSHA384":
+ return new CipherKeyGenerator(384);
+ case "HMACSHA512":
+ return new CipherKeyGenerator(512);
+ case "HMACRIPEMD128":
+ return new CipherKeyGenerator(128);
+ case "HMACRIPEMD160":
+ return new CipherKeyGenerator(160);
+ case "HMACTIGER":
+ return new CipherKeyGenerator(192);
+ case "IDEA":
+ return new CipherKeyGenerator(128);
+ case "NOEKEON":
+ return new CipherKeyGenerator(128);
+ case "RC2":
+ case "RC4":
+ case "RC5":
+ return new CipherKeyGenerator(128);
+ case "RC5-64":
+ case "RC6":
+ return new CipherKeyGenerator(256);
+ case "RIJNDAEL":
+ return new CipherKeyGenerator(192);
+ case "SALSA20":
+ return new CipherKeyGenerator(128);
+ case "SEED":
+ return new CipherKeyGenerator(128);
+ case "SERPENT":
+ return new CipherKeyGenerator(192);
+ case "SKIPJACK":
+ return new CipherKeyGenerator(80);
+ case "TEA":
+ case "XTEA":
+ return new CipherKeyGenerator(128);
+ case "TWOFISH":
+ return new CipherKeyGenerator(256);
+ case "VMPC":
+ case "VMPC-KSA3":
+ return new CipherKeyGenerator(128);
+ }
+
+ throw new SecurityUtilityException("KeyGenerator " + algorithm + " not recognised.");
+ }
+
+ public static IAsymmetricCipherKeyPairGenerator GetKeyPairGenerator(
+ DerObjectIdentifier oid)
+ {
+ return GetKeyPairGenerator(oid.Id);
+ }
+
+ public static IAsymmetricCipherKeyPairGenerator GetKeyPairGenerator(
+ string algorithm)
+ {
+ string canonicalName = GetCanonicalKeyPairGeneratorAlgorithm(algorithm);
+
+ if (canonicalName == null)
+ throw new SecurityUtilityException("KeyPairGenerator " + algorithm + " not recognised.");
+
+ switch (canonicalName)
+ {
+ case "DH":
+ return new DHKeyPairGenerator();
+ case "DSA":
+ return new DsaKeyPairGenerator();
+ case "EC":
+ case "ECDH":
+ case "ECDHC":
+ case "ECDSA":
+ case "ECGOST3410":
+ return new ECKeyPairGenerator(canonicalName);
+ case "ELGAMAL":
+ return new ElGamalKeyPairGenerator();
+ case "GOST3410":
+ return new Gost3410KeyPairGenerator();
+ case "RSA":
+ return new RsaKeyPairGenerator();
+ default:
+ break;
+ }
+
+ throw new SecurityUtilityException("KeyPairGenerator " + algorithm + " not recognised.");
+ }
+ }
+}
diff --git a/src/core/srcbc/security/PrivateKeyFactory.cs b/src/core/srcbc/security/PrivateKeyFactory.cs
index 79fa72d..0235c23 100644
--- a/src/core/srcbc/security/PrivateKeyFactory.cs
+++ b/src/core/srcbc/security/PrivateKeyFactory.cs
@@ -1,181 +1,210 @@
-using System;
-using System.Collections;
-using System.IO;
-using System.Text;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Asn1.CryptoPro;
-using Org.BouncyCastle.Asn1.Nist;
-using Org.BouncyCastle.Asn1.Oiw;
-using Org.BouncyCastle.Asn1.Pkcs;
-using Org.BouncyCastle.Asn1.Sec;
-using Org.BouncyCastle.Asn1.TeleTrust;
-using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Asn1.X9;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
-
-namespace Org.BouncyCastle.Security
-{
- public sealed class PrivateKeyFactory
- {
- private PrivateKeyFactory()
- {
- }
-
- public static AsymmetricKeyParameter CreateKey(
- byte[] privateKeyInfoData)
- {
- return CreateKey(
- PrivateKeyInfo.GetInstance(
- Asn1Object.FromByteArray(privateKeyInfoData)));
- }
-
- public static AsymmetricKeyParameter CreateKey(
- Stream inStr)
- {
- return CreateKey(
- PrivateKeyInfo.GetInstance(
- Asn1Object.FromStream(inStr)));
- }
-
- public static AsymmetricKeyParameter CreateKey(
- PrivateKeyInfo keyInfo)
- {
- AlgorithmIdentifier algID = keyInfo.AlgorithmID;
- DerObjectIdentifier algOid = algID.ObjectID;
-
- if (algOid.Equals(PkcsObjectIdentifiers.RsaEncryption))
- {
- RsaPrivateKeyStructure keyStructure = new RsaPrivateKeyStructure(
- Asn1Sequence.GetInstance(keyInfo.PrivateKey));
-
- return new RsaPrivateCrtKeyParameters(
- keyStructure.Modulus,
- keyStructure.PublicExponent,
- keyStructure.PrivateExponent,
- keyStructure.Prime1,
- keyStructure.Prime2,
- keyStructure.Exponent1,
- keyStructure.Exponent2,
- keyStructure.Coefficient);
- }
- else if (algOid.Equals(PkcsObjectIdentifiers.DhKeyAgreement))
- {
- DHParameter para = new DHParameter(
- Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
- DerInteger derX = (DerInteger)keyInfo.PrivateKey;
-
- return new DHPrivateKeyParameters(
- derX.Value,
- new DHParameters(para.P, para.G));
- }
- else if (algOid.Equals(OiwObjectIdentifiers.ElGamalAlgorithm))
- {
- ElGamalParameter para = new ElGamalParameter(
- Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
- DerInteger derX = (DerInteger)keyInfo.PrivateKey;
-
- return new ElGamalPrivateKeyParameters(
- derX.Value,
- new ElGamalParameters(para.P, para.G));
- }
- else if (algOid.Equals(X9ObjectIdentifiers.IdDsa))
- {
- DerInteger derX = (DerInteger) keyInfo.PrivateKey;
- Asn1Encodable ae = algID.Parameters;
-
- DsaParameters parameters = null;
- if (ae != null)
- {
- DsaParameter para = DsaParameter.GetInstance(ae.ToAsn1Object());
- parameters = new DsaParameters(para.P, para.Q, para.G);
- }
-
- return new DsaPrivateKeyParameters(derX.Value, parameters);
- }
- else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey))
- {
- X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object());
- X9ECParameters ecP;
-
- if (para.IsNamedCurve)
- {
- // TODO ECGost3410NamedCurves support (returns ECDomainParameters though)
-
- DerObjectIdentifier oid = (DerObjectIdentifier) para.Parameters;
- ecP = X962NamedCurves.GetByOid(oid);
-
- if (ecP == null)
- {
- ecP = SecNamedCurves.GetByOid(oid);
-
- if (ecP == null)
- {
- ecP = NistNamedCurves.GetByOid(oid);
-
- if (ecP == null)
- {
- ecP = TeleTrusTNamedCurves.GetByOid(oid);
- }
- }
- }
- }
- else
- {
- ecP = new X9ECParameters((Asn1Sequence) para.Parameters);
- }
-
- ECDomainParameters dParams = new ECDomainParameters(
- ecP.Curve,
- ecP.G,
- ecP.N,
- ecP.H,
- ecP.GetSeed());
-
- ECPrivateKeyStructure ec = new ECPrivateKeyStructure(
- Asn1Sequence.GetInstance(keyInfo.PrivateKey));
-
- return new ECPrivateKeyParameters(ec.GetKey(), dParams);
- }
- else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001))
- {
- Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
- Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
-
- ECPrivateKeyStructure ec = new ECPrivateKeyStructure(
- Asn1Sequence.GetInstance(keyInfo.PrivateKey));
-
- ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
-
- if (ecP == null)
- return null;
-
- return new ECPrivateKeyParameters(ec.GetKey(), gostParams.PublicKeyParamSet);
- }
- else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94))
- {
- Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
- Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
-
- DerOctetString derX = (DerOctetString) keyInfo.PrivateKey;
- byte[] keyEnc = derX.GetOctets();
- byte[] keyBytes = new byte[keyEnc.Length];
-
- for (int i = 0; i != keyEnc.Length; i++)
- {
- keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // was little endian
- }
-
- BigInteger x = new BigInteger(1, keyBytes);
-
- return new Gost3410PrivateKeyParameters(x, gostParams.PublicKeyParamSet);
- }
- else
- {
- throw new SecurityUtilityException("algorithm identifier in key not recognised");
- }
- }
- }
-}
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Pkcs;
+
+namespace Org.BouncyCastle.Security
+{
+ public sealed class PrivateKeyFactory
+ {
+ private PrivateKeyFactory()
+ {
+ }
+
+ public static AsymmetricKeyParameter CreateKey(
+ byte[] privateKeyInfoData)
+ {
+ return CreateKey(
+ PrivateKeyInfo.GetInstance(
+ Asn1Object.FromByteArray(privateKeyInfoData)));
+ }
+
+ public static AsymmetricKeyParameter CreateKey(
+ Stream inStr)
+ {
+ return CreateKey(
+ PrivateKeyInfo.GetInstance(
+ Asn1Object.FromStream(inStr)));
+ }
+
+ public static AsymmetricKeyParameter CreateKey(
+ PrivateKeyInfo keyInfo)
+ {
+ AlgorithmIdentifier algID = keyInfo.AlgorithmID;
+ DerObjectIdentifier algOid = algID.ObjectID;
+
+ if (algOid.Equals(PkcsObjectIdentifiers.RsaEncryption))
+ {
+ RsaPrivateKeyStructure keyStructure = new RsaPrivateKeyStructure(
+ Asn1Sequence.GetInstance(keyInfo.PrivateKey));
+
+ return new RsaPrivateCrtKeyParameters(
+ keyStructure.Modulus,
+ keyStructure.PublicExponent,
+ keyStructure.PrivateExponent,
+ keyStructure.Prime1,
+ keyStructure.Prime2,
+ keyStructure.Exponent1,
+ keyStructure.Exponent2,
+ keyStructure.Coefficient);
+ }
+ else if (algOid.Equals(PkcsObjectIdentifiers.DhKeyAgreement))
+ {
+ DHParameter para = new DHParameter(
+ Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+ DerInteger derX = (DerInteger)keyInfo.PrivateKey;
+
+ return new DHPrivateKeyParameters(
+ derX.Value,
+ new DHParameters(para.P, para.G));
+ }
+ else if (algOid.Equals(OiwObjectIdentifiers.ElGamalAlgorithm))
+ {
+ ElGamalParameter para = new ElGamalParameter(
+ Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+ DerInteger derX = (DerInteger)keyInfo.PrivateKey;
+
+ return new ElGamalPrivateKeyParameters(
+ derX.Value,
+ new ElGamalParameters(para.P, para.G));
+ }
+ else if (algOid.Equals(X9ObjectIdentifiers.IdDsa))
+ {
+ DerInteger derX = (DerInteger) keyInfo.PrivateKey;
+ Asn1Encodable ae = algID.Parameters;
+
+ DsaParameters parameters = null;
+ if (ae != null)
+ {
+ DsaParameter para = DsaParameter.GetInstance(ae.ToAsn1Object());
+ parameters = new DsaParameters(para.P, para.Q, para.G);
+ }
+
+ return new DsaPrivateKeyParameters(derX.Value, parameters);
+ }
+ else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey))
+ {
+ X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object());
+ X9ECParameters ecP;
+
+ if (para.IsNamedCurve)
+ {
+ // TODO ECGost3410NamedCurves support (returns ECDomainParameters though)
+
+ DerObjectIdentifier oid = (DerObjectIdentifier) para.Parameters;
+ ecP = X962NamedCurves.GetByOid(oid);
+
+ if (ecP == null)
+ {
+ ecP = SecNamedCurves.GetByOid(oid);
+
+ if (ecP == null)
+ {
+ ecP = NistNamedCurves.GetByOid(oid);
+
+ if (ecP == null)
+ {
+ ecP = TeleTrusTNamedCurves.GetByOid(oid);
+ }
+ }
+ }
+ }
+ else
+ {
+ ecP = new X9ECParameters((Asn1Sequence) para.Parameters);
+ }
+
+ ECDomainParameters dParams = new ECDomainParameters(
+ ecP.Curve,
+ ecP.G,
+ ecP.N,
+ ecP.H,
+ ecP.GetSeed());
+
+ ECPrivateKeyStructure ec = new ECPrivateKeyStructure(
+ Asn1Sequence.GetInstance(keyInfo.PrivateKey));
+
+ return new ECPrivateKeyParameters(ec.GetKey(), dParams);
+ }
+ else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001))
+ {
+ Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
+ Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+
+ ECPrivateKeyStructure ec = new ECPrivateKeyStructure(
+ Asn1Sequence.GetInstance(keyInfo.PrivateKey));
+
+ ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
+
+ if (ecP == null)
+ return null;
+
+ return new ECPrivateKeyParameters(ec.GetKey(), gostParams.PublicKeyParamSet);
+ }
+ else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94))
+ {
+ Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
+ Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+
+ DerOctetString derX = (DerOctetString) keyInfo.PrivateKey;
+ byte[] keyEnc = derX.GetOctets();
+ byte[] keyBytes = new byte[keyEnc.Length];
+
+ for (int i = 0; i != keyEnc.Length; i++)
+ {
+ keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // was little endian
+ }
+
+ BigInteger x = new BigInteger(1, keyBytes);
+
+ return new Gost3410PrivateKeyParameters(x, gostParams.PublicKeyParamSet);
+ }
+ else
+ {
+ throw new SecurityUtilityException("algorithm identifier in key not recognised");
+ }
+ }
+
+ public static AsymmetricKeyParameter DecryptKey(
+ char[] passPhrase,
+ EncryptedPrivateKeyInfo encInfo)
+ {
+ return CreateKey(PrivateKeyInfoFactory.CreatePrivateKeyInfo(passPhrase, encInfo));
+ }
+
+ public static AsymmetricKeyParameter DecryptKey(
+ char[] passPhrase,
+ byte[] encryptedPrivateKeyInfoData)
+ {
+ return DecryptKey(passPhrase, Asn1Object.FromByteArray(encryptedPrivateKeyInfoData));
+ }
+
+ public static AsymmetricKeyParameter DecryptKey(
+ char[] passPhrase,
+ Stream encryptedPrivateKeyInfoStream)
+ {
+ return DecryptKey(passPhrase, Asn1Object.FromStream(encryptedPrivateKeyInfoStream));
+ }
+
+ private static AsymmetricKeyParameter DecryptKey(
+ char[] passPhrase,
+ Asn1Object asn1Object)
+ {
+ return DecryptKey(passPhrase, EncryptedPrivateKeyInfo.GetInstance(asn1Object));
+ }
+ }
+}
diff --git a/src/core/srcbc/x509/PEMParser.cs b/src/core/srcbc/x509/PEMParser.cs
index 149e14f..8c117f3 100644
--- a/src/core/srcbc/x509/PEMParser.cs
+++ b/src/core/srcbc/x509/PEMParser.cs
@@ -1,94 +1,94 @@
-using System;
-using System.IO;
-using System.Text;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Utilities.Encoders;
-
-namespace Org.BouncyCastle.X509
-{
- class PemParser
- {
- private readonly string _header1;
- private readonly string _header2;
- private readonly string _footer1;
- private readonly string _footer2;
-
- internal PemParser(
- string type)
- {
- _header1 = "-----BEGIN " + type + "-----";
- _header2 = "-----BEGIN X509 " + type + "-----";
- _footer1 = "-----END " + type + "-----";
- _footer2 = "-----END X509 " + type + "-----";
- }
-
- private string ReadLine(
- Stream inStream)
- {
- int c;
- StringBuilder l = new StringBuilder();
-
- do
- {
- while (((c = inStream.ReadByte()) != '\r') && c != '\n' && (c >= 0))
- {
- if (c == '\r')
- {
- continue;
- }
-
- l.Append((char)c);
- }
- }
- while (c >= 0 && l.Length == 0);
-
- if (c < 0)
- {
- return null;
- }
-
- return l.ToString();
- }
-
- internal Asn1Sequence ReadPemObject(
- Stream inStream)
- {
- string line;
- StringBuilder pemBuf = new StringBuilder();
-
- while ((line = ReadLine(inStream)) != null)
- {
- if (line.Equals(_header1) || line.Equals(_header2))
- {
- break;
- }
- }
-
- while ((line = ReadLine(inStream)) != null)
- {
- if (line.Equals(_footer1) || line.Equals(_footer2))
- {
- break;
- }
-
- pemBuf.Append(line);
- }
-
- if (pemBuf.Length != 0)
- {
- Asn1Object o = Asn1Object.FromByteArray(Base64.Decode(pemBuf.ToString()));
-
- if (!(o is Asn1Sequence))
- {
- throw new IOException("malformed PEM data encountered");
- }
-
- return (Asn1Sequence) o;
- }
-
- return null;
- }
- }
-}
-
+using System;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.X509
+{
+ class PemParser
+ {
+ private readonly string _header1;
+ private readonly string _header2;
+ private readonly string _footer1;
+ private readonly string _footer2;
+
+ internal PemParser(
+ string type)
+ {
+ _header1 = "-----BEGIN " + type + "-----";
+ _header2 = "-----BEGIN X509 " + type + "-----";
+ _footer1 = "-----END " + type + "-----";
+ _footer2 = "-----END X509 " + type + "-----";
+ }
+
+ private string ReadLine(
+ Stream inStream)
+ {
+ int c;
+ StringBuilder l = new StringBuilder();
+
+ do
+ {
+ while (((c = inStream.ReadByte()) != '\r') && c != '\n' && (c >= 0))
+ {
+ if (c == '\r')
+ {
+ continue;
+ }
+
+ l.Append((char)c);
+ }
+ }
+ while (c >= 0 && l.Length == 0);
+
+ if (c < 0)
+ {
+ return null;
+ }
+
+ return l.ToString();
+ }
+
+ internal Asn1Sequence ReadPemObject(
+ Stream inStream)
+ {
+ string line;
+ StringBuilder pemBuf = new StringBuilder();
+
+ while ((line = ReadLine(inStream)) != null)
+ {
+ if (line.StartsWith(_header1) || line.StartsWith(_header2))
+ {
+ break;
+ }
+ }
+
+ while ((line = ReadLine(inStream)) != null)
+ {
+ if (line.StartsWith(_footer1) || line.StartsWith(_footer2))
+ {
+ break;
+ }
+
+ pemBuf.Append(line);
+ }
+
+ if (pemBuf.Length != 0)
+ {
+ Asn1Object o = Asn1Object.FromByteArray(Base64.Decode(pemBuf.ToString()));
+
+ if (!(o is Asn1Sequence))
+ {
+ throw new IOException("malformed PEM data encountered");
+ }
+
+ return (Asn1Sequence) o;
+ }
+
+ return null;
+ }
+ }
+}
+
diff --git a/src/core/srcbc/x509/store/X509CertStoreSelector.cs b/src/core/srcbc/x509/store/X509CertStoreSelector.cs
index b9c2ff6..3874edf 100644
--- a/src/core/srcbc/x509/store/X509CertStoreSelector.cs
+++ b/src/core/srcbc/x509/store/X509CertStoreSelector.cs
@@ -1,337 +1,337 @@
-using System;
-using System.Collections;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Math;
-using Org.BouncyCastle.Utilities;
-using Org.BouncyCastle.Utilities.Collections;
-using Org.BouncyCastle.Utilities.Date;
-using Org.BouncyCastle.X509.Extension;
-
-namespace Org.BouncyCastle.X509.Store
-{
- public class X509CertStoreSelector
- : IX509Selector
- {
- // TODO Missing criteria?
-
- private byte[] authorityKeyIdentifier;
- private int basicConstraints = -1;
- private X509Certificate certificate;
- private DateTimeObject certificateValid;
- private ISet extendedKeyUsage;
- private X509Name issuer;
- private bool[] keyUsage;
- private ISet policy;
- private DateTimeObject privateKeyValid;
- private BigInteger serialNumber;
- private X509Name subject;
- private byte[] subjectKeyIdentifier;
- private SubjectPublicKeyInfo subjectPublicKey;
- private DerObjectIdentifier subjectPublicKeyAlgID;
-
- public X509CertStoreSelector()
- {
- }
-
- public X509CertStoreSelector(
- X509CertStoreSelector o)
- {
- this.authorityKeyIdentifier = o.AuthorityKeyIdentifier;
- this.basicConstraints = o.BasicConstraints;
- this.certificate = o.Certificate;
- this.certificateValid = o.CertificateValid;
- this.extendedKeyUsage = o.ExtendedKeyUsage;
- this.issuer = o.Issuer;
- this.keyUsage = o.KeyUsage;
- this.policy = o.Policy;
- this.privateKeyValid = o.PrivateKeyValid;
- this.serialNumber = o.SerialNumber;
- this.subject = o.Subject;
- this.subjectKeyIdentifier = o.SubjectKeyIdentifier;
- this.subjectPublicKey = o.SubjectPublicKey;
- this.subjectPublicKeyAlgID = o.SubjectPublicKeyAlgID;
- }
-
- public virtual object Clone()
- {
- return new X509CertStoreSelector(this);
- }
-
- public byte[] AuthorityKeyIdentifier
- {
- get { return Arrays.Clone(authorityKeyIdentifier); }
- set { authorityKeyIdentifier = Arrays.Clone(value); }
- }
-
- public int BasicConstraints
- {
- get { return basicConstraints; }
- set
- {
- if (value < -2)
- throw new ArgumentException("value can't be less than -2", "value");
-
- basicConstraints = value;
- }
- }
-
- public X509Certificate Certificate
- {
- get { return certificate; }
- set { this.certificate = value; }
- }
-
- public DateTimeObject CertificateValid
- {
- get { return certificateValid; }
- set { certificateValid = value; }
- }
-
- public ISet ExtendedKeyUsage
- {
- get { return CopySet(extendedKeyUsage); }
- set { extendedKeyUsage = CopySet(value); }
- }
-
- public X509Name Issuer
- {
- get { return issuer; }
- set { issuer = value; }
- }
-
- [Obsolete("Avoid working with X509Name objects in string form")]
- public string IssuerAsString
- {
- get { return issuer != null ? issuer.ToString() : null; }
- }
-
- public bool[] KeyUsage
- {
- get { return CopyBoolArray(keyUsage); }
- set { keyUsage = CopyBoolArray(value); }
- }
-
- ///
- /// An ISet
of DerObjectIdentifier
objects.
- ///
- public ISet Policy
- {
- get { return CopySet(policy); }
- set { policy = CopySet(value); }
- }
-
- public DateTimeObject PrivateKeyValid
- {
- get { return privateKeyValid; }
- set { privateKeyValid = value; }
- }
-
- public BigInteger SerialNumber
- {
- get { return serialNumber; }
- set { serialNumber = value; }
- }
-
- public X509Name Subject
- {
- get { return subject; }
- set { subject = value; }
- }
-
- public string SubjectAsString
- {
- get { return subject != null ? subject.ToString() : null; }
- }
-
- public byte[] SubjectKeyIdentifier
- {
- get { return Arrays.Clone(subjectKeyIdentifier); }
- set { subjectKeyIdentifier = Arrays.Clone(value); }
- }
-
- public SubjectPublicKeyInfo SubjectPublicKey
- {
- get { return subjectPublicKey; }
- set { subjectPublicKey = value; }
- }
-
- public DerObjectIdentifier SubjectPublicKeyAlgID
- {
- get { return subjectPublicKeyAlgID; }
- set { subjectPublicKeyAlgID = value; }
- }
-
- public virtual bool Match(
- object obj)
- {
- X509Certificate c = obj as X509Certificate;
-
- if (c == null)
- return false;
-
- if (!MatchExtension(authorityKeyIdentifier, c, X509Extensions.AuthorityKeyIdentifier))
- return false;
-
- if (basicConstraints != -1)
- {
- int bc = c.GetBasicConstraints();
-
- if (basicConstraints == -2)
- {
- if (bc != -1)
- return false;
- }
- else
- {
- if (bc < basicConstraints)
- return false;
- }
- }
-
- if (certificate != null && !certificate.Equals(c))
- return false;
-
- if (certificateValid != null && !c.IsValid(certificateValid.Value))
- return false;
-
- if (extendedKeyUsage != null)
- {
- IList eku = c.GetExtendedKeyUsage();
-
- // Note: if no extended key usage set, all key purposes are implicitly allowed
-
- if (eku != null)
- {
- foreach (DerObjectIdentifier oid in extendedKeyUsage)
- {
- if (!eku.Contains(oid.Id))
- return false;
- }
- }
- }
-
- if (issuer != null && !issuer.Equivalent(c.IssuerDN))
- return false;
-
- if (keyUsage != null)
- {
- bool[] ku = c.GetKeyUsage();
-
- // Note: if no key usage set, all key purposes are implicitly allowed
-
- if (ku != null)
- {
- for (int i = 0; i < 9; ++i)
- {
- if (keyUsage[i] && !ku[i])
- return false;
- }
- }
- }
-
- if (policy != null)
- {
- Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.CertificatePolicies);
- if (extVal == null)
- return false;
-
- Asn1Sequence certPolicies = Asn1Sequence.GetInstance(
- X509ExtensionUtilities.FromExtensionValue(extVal));
-
- if (policy.Count < 1 && certPolicies.Count < 1)
- return false;
-
- bool found = false;
- foreach (PolicyInformation pi in certPolicies)
- {
- if (policy.Contains(pi.PolicyIdentifier))
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- return false;
- }
-
- if (privateKeyValid != null)
- {
- Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.PrivateKeyUsagePeriod);
- if (extVal == null)
- return false;
-
- PrivateKeyUsagePeriod pkup = PrivateKeyUsagePeriod.GetInstance(
- X509ExtensionUtilities.FromExtensionValue(extVal));
-
- DateTime dt = privateKeyValid.Value;
- DateTime notAfter = pkup.NotAfter.ToDateTime();
- DateTime notBefore = pkup.NotBefore.ToDateTime();
-
- if (dt.CompareTo(notAfter) > 0 || dt.CompareTo(notBefore) < 0)
- return false;
- }
-
- if (serialNumber != null && !serialNumber.Equals(c.SerialNumber))
- return false;
-
- if (subject != null && !subject.Equivalent(c.SubjectDN))
- return false;
-
- if (!MatchExtension(subjectKeyIdentifier, c, X509Extensions.SubjectKeyIdentifier))
- return false;
-
- if (subjectPublicKey != null && !subjectPublicKey.Equals(GetSubjectPublicKey(c)))
- return false;
-
- if (subjectPublicKeyAlgID != null
- && !subjectPublicKeyAlgID.Equals(GetSubjectPublicKey(c).AlgorithmID))
- return false;
-
- return true;
- }
-
- internal static bool IssuersMatch(
- X509Name a,
- X509Name b)
- {
- return a == null ? b == null : a.Equivalent(b);
- }
-
- private static bool[] CopyBoolArray(
- bool[] b)
- {
- return b == null ? null : (bool[]) b.Clone();
- }
-
- private static ISet CopySet(
- ISet s)
- {
- return s == null ? null : new HashSet(s);
- }
-
- private static SubjectPublicKeyInfo GetSubjectPublicKey(
- X509Certificate c)
- {
- return SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(c.GetPublicKey());
- }
-
- private static bool MatchExtension(
- byte[] b,
- X509Certificate c,
- DerObjectIdentifier oid)
- {
- if (b == null)
- return true;
-
- Asn1OctetString extVal = c.GetExtensionValue(oid);
-
- if (extVal == null)
- return false;
-
- return extVal != null && Arrays.AreEqual(b, extVal.GetEncoded());
- }
- }
-}
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.X509.Store
+{
+ public class X509CertStoreSelector
+ : IX509Selector
+ {
+ // TODO Missing criteria?
+
+ private byte[] authorityKeyIdentifier;
+ private int basicConstraints = -1;
+ private X509Certificate certificate;
+ private DateTimeObject certificateValid;
+ private ISet extendedKeyUsage;
+ private X509Name issuer;
+ private bool[] keyUsage;
+ private ISet policy;
+ private DateTimeObject privateKeyValid;
+ private BigInteger serialNumber;
+ private X509Name subject;
+ private byte[] subjectKeyIdentifier;
+ private SubjectPublicKeyInfo subjectPublicKey;
+ private DerObjectIdentifier subjectPublicKeyAlgID;
+
+ public X509CertStoreSelector()
+ {
+ }
+
+ public X509CertStoreSelector(
+ X509CertStoreSelector o)
+ {
+ this.authorityKeyIdentifier = o.AuthorityKeyIdentifier;
+ this.basicConstraints = o.BasicConstraints;
+ this.certificate = o.Certificate;
+ this.certificateValid = o.CertificateValid;
+ this.extendedKeyUsage = o.ExtendedKeyUsage;
+ this.issuer = o.Issuer;
+ this.keyUsage = o.KeyUsage;
+ this.policy = o.Policy;
+ this.privateKeyValid = o.PrivateKeyValid;
+ this.serialNumber = o.SerialNumber;
+ this.subject = o.Subject;
+ this.subjectKeyIdentifier = o.SubjectKeyIdentifier;
+ this.subjectPublicKey = o.SubjectPublicKey;
+ this.subjectPublicKeyAlgID = o.SubjectPublicKeyAlgID;
+ }
+
+ public virtual object Clone()
+ {
+ return new X509CertStoreSelector(this);
+ }
+
+ public byte[] AuthorityKeyIdentifier
+ {
+ get { return Arrays.Clone(authorityKeyIdentifier); }
+ set { authorityKeyIdentifier = Arrays.Clone(value); }
+ }
+
+ public int BasicConstraints
+ {
+ get { return basicConstraints; }
+ set
+ {
+ if (value < -2)
+ throw new ArgumentException("value can't be less than -2", "value");
+
+ basicConstraints = value;
+ }
+ }
+
+ public X509Certificate Certificate
+ {
+ get { return certificate; }
+ set { this.certificate = value; }
+ }
+
+ public DateTimeObject CertificateValid
+ {
+ get { return certificateValid; }
+ set { certificateValid = value; }
+ }
+
+ public ISet ExtendedKeyUsage
+ {
+ get { return CopySet(extendedKeyUsage); }
+ set { extendedKeyUsage = CopySet(value); }
+ }
+
+ public X509Name Issuer
+ {
+ get { return issuer; }
+ set { issuer = value; }
+ }
+
+ [Obsolete("Avoid working with X509Name objects in string form")]
+ public string IssuerAsString
+ {
+ get { return issuer != null ? issuer.ToString() : null; }
+ }
+
+ public bool[] KeyUsage
+ {
+ get { return CopyBoolArray(keyUsage); }
+ set { keyUsage = CopyBoolArray(value); }
+ }
+
+ ///
+ /// An ISet
of DerObjectIdentifier
objects.
+ ///
+ public ISet Policy
+ {
+ get { return CopySet(policy); }
+ set { policy = CopySet(value); }
+ }
+
+ public DateTimeObject PrivateKeyValid
+ {
+ get { return privateKeyValid; }
+ set { privateKeyValid = value; }
+ }
+
+ public BigInteger SerialNumber
+ {
+ get { return serialNumber; }
+ set { serialNumber = value; }
+ }
+
+ public X509Name Subject
+ {
+ get { return subject; }
+ set { subject = value; }
+ }
+
+ public string SubjectAsString
+ {
+ get { return subject != null ? subject.ToString() : null; }
+ }
+
+ public byte[] SubjectKeyIdentifier
+ {
+ get { return Arrays.Clone(subjectKeyIdentifier); }
+ set { subjectKeyIdentifier = Arrays.Clone(value); }
+ }
+
+ public SubjectPublicKeyInfo SubjectPublicKey
+ {
+ get { return subjectPublicKey; }
+ set { subjectPublicKey = value; }
+ }
+
+ public DerObjectIdentifier SubjectPublicKeyAlgID
+ {
+ get { return subjectPublicKeyAlgID; }
+ set { subjectPublicKeyAlgID = value; }
+ }
+
+ public virtual bool Match(
+ object obj)
+ {
+ X509Certificate c = obj as X509Certificate;
+
+ if (c == null)
+ return false;
+
+ if (!MatchExtension(authorityKeyIdentifier, c, X509Extensions.AuthorityKeyIdentifier))
+ return false;
+
+ if (basicConstraints != -1)
+ {
+ int bc = c.GetBasicConstraints();
+
+ if (basicConstraints == -2)
+ {
+ if (bc != -1)
+ return false;
+ }
+ else
+ {
+ if (bc < basicConstraints)
+ return false;
+ }
+ }
+
+ if (certificate != null && !certificate.Equals(c))
+ return false;
+
+ if (certificateValid != null && !c.IsValid(certificateValid.Value))
+ return false;
+
+ if (extendedKeyUsage != null)
+ {
+ IList eku = c.GetExtendedKeyUsage();
+
+ // Note: if no extended key usage set, all key purposes are implicitly allowed
+
+ if (eku != null)
+ {
+ foreach (DerObjectIdentifier oid in extendedKeyUsage)
+ {
+ if (!eku.Contains(oid.Id))
+ return false;
+ }
+ }
+ }
+
+ if (issuer != null && !issuer.Equivalent(c.IssuerDN, true))
+ return false;
+
+ if (keyUsage != null)
+ {
+ bool[] ku = c.GetKeyUsage();
+
+ // Note: if no key usage set, all key purposes are implicitly allowed
+
+ if (ku != null)
+ {
+ for (int i = 0; i < 9; ++i)
+ {
+ if (keyUsage[i] && !ku[i])
+ return false;
+ }
+ }
+ }
+
+ if (policy != null)
+ {
+ Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.CertificatePolicies);
+ if (extVal == null)
+ return false;
+
+ Asn1Sequence certPolicies = Asn1Sequence.GetInstance(
+ X509ExtensionUtilities.FromExtensionValue(extVal));
+
+ if (policy.Count < 1 && certPolicies.Count < 1)
+ return false;
+
+ bool found = false;
+ foreach (PolicyInformation pi in certPolicies)
+ {
+ if (policy.Contains(pi.PolicyIdentifier))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ return false;
+ }
+
+ if (privateKeyValid != null)
+ {
+ Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.PrivateKeyUsagePeriod);
+ if (extVal == null)
+ return false;
+
+ PrivateKeyUsagePeriod pkup = PrivateKeyUsagePeriod.GetInstance(
+ X509ExtensionUtilities.FromExtensionValue(extVal));
+
+ DateTime dt = privateKeyValid.Value;
+ DateTime notAfter = pkup.NotAfter.ToDateTime();
+ DateTime notBefore = pkup.NotBefore.ToDateTime();
+
+ if (dt.CompareTo(notAfter) > 0 || dt.CompareTo(notBefore) < 0)
+ return false;
+ }
+
+ if (serialNumber != null && !serialNumber.Equals(c.SerialNumber))
+ return false;
+
+ if (subject != null && !subject.Equivalent(c.SubjectDN, true))
+ return false;
+
+ if (!MatchExtension(subjectKeyIdentifier, c, X509Extensions.SubjectKeyIdentifier))
+ return false;
+
+ if (subjectPublicKey != null && !subjectPublicKey.Equals(GetSubjectPublicKey(c)))
+ return false;
+
+ if (subjectPublicKeyAlgID != null
+ && !subjectPublicKeyAlgID.Equals(GetSubjectPublicKey(c).AlgorithmID))
+ return false;
+
+ return true;
+ }
+
+ internal static bool IssuersMatch(
+ X509Name a,
+ X509Name b)
+ {
+ return a == null ? b == null : a.Equivalent(b, true);
+ }
+
+ private static bool[] CopyBoolArray(
+ bool[] b)
+ {
+ return b == null ? null : (bool[]) b.Clone();
+ }
+
+ private static ISet CopySet(
+ ISet s)
+ {
+ return s == null ? null : new HashSet(s);
+ }
+
+ private static SubjectPublicKeyInfo GetSubjectPublicKey(
+ X509Certificate c)
+ {
+ return SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(c.GetPublicKey());
+ }
+
+ private static bool MatchExtension(
+ byte[] b,
+ X509Certificate c,
+ DerObjectIdentifier oid)
+ {
+ if (b == null)
+ return true;
+
+ Asn1OctetString extVal = c.GetExtensionValue(oid);
+
+ if (extVal == null)
+ return false;
+
+ return Arrays.AreEqual(b, extVal.GetOctets());
+ }
+ }
+}
diff --git a/src/core/srcbc/x509/store/X509CrlStoreSelector.cs b/src/core/srcbc/x509/store/X509CrlStoreSelector.cs
index a09229e..21d61b4 100644
--- a/src/core/srcbc/x509/store/X509CrlStoreSelector.cs
+++ b/src/core/srcbc/x509/store/X509CrlStoreSelector.cs
@@ -1,283 +1,283 @@
-using System;
-using System.Collections;
-
-using Org.BouncyCastle.Asn1;
-using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Math;
-using Org.BouncyCastle.Utilities;
-using Org.BouncyCastle.Utilities.Date;
-using Org.BouncyCastle.X509;
-using Org.BouncyCastle.X509.Extension;
-
-namespace Org.BouncyCastle.X509.Store
-{
- public class X509CrlStoreSelector
- : IX509Selector
- {
- // TODO Missing criteria?
-
- private X509Certificate certificateChecking;
- private DateTimeObject dateAndTime;
- private ICollection issuers;
- private BigInteger maxCrlNumber;
- private BigInteger minCrlNumber;
-
- private IX509AttributeCertificate attrCertChecking;
- private bool completeCrlEnabled;
- private bool deltaCrlIndicatorEnabled;
- private byte[] issuingDistributionPoint;
- private bool issuingDistributionPointEnabled;
- private BigInteger maxBaseCrlNumber;
-
- public X509CrlStoreSelector()
- {
- }
-
- public X509CrlStoreSelector(
- X509CrlStoreSelector o)
- {
- this.certificateChecking = o.CertificateChecking;
- this.dateAndTime = o.DateAndTime;
- this.issuers = o.Issuers;
- this.maxCrlNumber = o.MaxCrlNumber;
- this.minCrlNumber = o.MinCrlNumber;
-
- this.deltaCrlIndicatorEnabled = o.DeltaCrlIndicatorEnabled;
- this.completeCrlEnabled = o.CompleteCrlEnabled;
- this.maxBaseCrlNumber = o.MaxBaseCrlNumber;
- this.attrCertChecking = o.AttrCertChecking;
- this.issuingDistributionPointEnabled = o.IssuingDistributionPointEnabled;
- this.issuingDistributionPoint = o.IssuingDistributionPoint;
- }
-
- public virtual object Clone()
- {
- return new X509CrlStoreSelector(this);
- }
-
- public X509Certificate CertificateChecking
- {
- get { return certificateChecking; }
- set { certificateChecking = value; }
- }
-
- public DateTimeObject DateAndTime
- {
- get { return dateAndTime; }
- set { dateAndTime = value; }
- }
-
- ///
- /// An ICollection
of X509Name
objects
- ///
- public ICollection Issuers
- {
- get { return new ArrayList(issuers); }
- set { issuers = new ArrayList(value); }
- }
-
- public BigInteger MaxCrlNumber
- {
- get { return maxCrlNumber; }
- set { maxCrlNumber = value; }
- }
-
- public BigInteger MinCrlNumber
- {
- get { return minCrlNumber; }
- set { minCrlNumber = value; }
- }
-
- /**
- * The attribute certificate being checked. This is not a criterion.
- * Rather, it is optional information that may help a {@link X509Store} find
- * CRLs that would be relevant when checking revocation for the specified
- * attribute certificate. If null
is specified, then no such
- * optional information is provided.
- *
- * @param attrCert the IX509AttributeCertificate
being checked (or
- * null
)
- * @see #getAttrCertificateChecking()
- */
- public IX509AttributeCertificate AttrCertChecking
- {
- get { return attrCertChecking; }
- set { this.attrCertChecking = value; }
- }
-
- /**
- * If true
only complete CRLs are returned. Defaults to
- * false
.
- *
- * @return true
if only complete CRLs are returned.
- */
- public bool CompleteCrlEnabled
- {
- get { return completeCrlEnabled; }
- set { this.completeCrlEnabled = value; }
- }
-
- /**
- * Returns if this selector must match CRLs with the delta CRL indicator
- * extension set. Defaults to false
.
- *
- * @return Returns true
if only CRLs with the delta CRL
- * indicator extension are selected.
- */
- public bool DeltaCrlIndicatorEnabled
- {
- get { return deltaCrlIndicatorEnabled; }
- set { this.deltaCrlIndicatorEnabled = value; }
- }
-
- /**
- * The issuing distribution point.
- *
- * The issuing distribution point extension is a CRL extension which
- * identifies the scope and the distribution point of a CRL. The scope
- * contains among others information about revocation reasons contained in
- * the CRL. Delta CRLs and complete CRLs must have matching issuing
- * distribution points.
- *
- * The byte array is cloned to protect against subsequent modifications.
- *
- * You must also enable or disable this criteria with
- * {@link #setIssuingDistributionPointEnabled(bool)}.
- *
- * @param issuingDistributionPoint The issuing distribution point to set.
- * This is the DER encoded OCTET STRING extension value.
- * @see #getIssuingDistributionPoint()
- */
- public byte[] IssuingDistributionPoint
- {
- get { return Arrays.Clone(issuingDistributionPoint); }
- set { this.issuingDistributionPoint = Arrays.Clone(value); }
- }
-
- /**
- * Whether the issuing distribution point criteria should be applied.
- * Defaults to false
.
- *
- * You may also set the issuing distribution point criteria if not a missing
- * issuing distribution point should be assumed.
- *
- * @return Returns if the issuing distribution point check is enabled.
- */
- public bool IssuingDistributionPointEnabled
- {
- get { return issuingDistributionPointEnabled; }
- set { this.issuingDistributionPointEnabled = value; }
- }
-
- /**
- * The maximum base CRL number. Defaults to null
.
- *
- * @return Returns the maximum base CRL number.
- * @see #setMaxBaseCRLNumber(BigInteger)
- */
- public BigInteger MaxBaseCrlNumber
- {
- get { return maxBaseCrlNumber; }
- set { this.maxBaseCrlNumber = value; }
- }
-
- public virtual bool Match(
- object obj)
- {
- X509Crl c = obj as X509Crl;
-
- if (c == null)
- return false;
-
- if (dateAndTime != null)
- {
- DateTime dt = dateAndTime.Value;
- DateTime tu = c.ThisUpdate;
- DateTimeObject nu = c.NextUpdate;
-
- if (dt.CompareTo(tu) < 0 || nu == null || dt.CompareTo(nu.Value) >= 0)
- return false;
- }
-
- if (issuers != null)
- {
- X509Name i = c.IssuerDN;
-
- bool found = false;
-
- foreach (X509Name issuer in issuers)
- {
- if (issuer.Equivalent(i))
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- return false;
- }
-
- if (maxCrlNumber != null || minCrlNumber != null)
- {
- Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.CrlNumber);
- if (extVal == null)
- return false;
-
- BigInteger cn = CrlNumber.GetInstance(
- X509ExtensionUtilities.FromExtensionValue(extVal)).PositiveValue;
-
- if (maxCrlNumber != null && cn.CompareTo(maxCrlNumber) > 0)
- return false;
-
- if (minCrlNumber != null && cn.CompareTo(minCrlNumber) < 0)
- return false;
- }
-
- DerInteger dci = null;
- try
- {
- Asn1OctetString bytes = c.GetExtensionValue(X509Extensions.DeltaCrlIndicator);
- if (bytes != null)
- {
- dci = DerInteger.GetInstance(X509ExtensionUtilities.FromExtensionValue(bytes));
- }
- }
- catch (Exception)
- {
- return false;
- }
-
- if (dci == null)
- {
- if (DeltaCrlIndicatorEnabled)
- return false;
- }
- else
- {
- if (CompleteCrlEnabled)
- return false;
-
- if (maxBaseCrlNumber != null && dci.PositiveValue.CompareTo(maxBaseCrlNumber) > 0)
- return false;
- }
-
- if (issuingDistributionPointEnabled)
- {
- Asn1OctetString idp = c.GetExtensionValue(X509Extensions.IssuingDistributionPoint);
- if (issuingDistributionPoint == null)
- {
- if (idp != null)
- return false;
- }
- else
- {
- if (!Arrays.AreEqual(idp.GetOctets(), issuingDistributionPoint))
- return false;
- }
- }
-
- return true;
- }
- }
-}
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.X509.Store
+{
+ public class X509CrlStoreSelector
+ : IX509Selector
+ {
+ // TODO Missing criteria?
+
+ private X509Certificate certificateChecking;
+ private DateTimeObject dateAndTime;
+ private ICollection issuers;
+ private BigInteger maxCrlNumber;
+ private BigInteger minCrlNumber;
+
+ private IX509AttributeCertificate attrCertChecking;
+ private bool completeCrlEnabled;
+ private bool deltaCrlIndicatorEnabled;
+ private byte[] issuingDistributionPoint;
+ private bool issuingDistributionPointEnabled;
+ private BigInteger maxBaseCrlNumber;
+
+ public X509CrlStoreSelector()
+ {
+ }
+
+ public X509CrlStoreSelector(
+ X509CrlStoreSelector o)
+ {
+ this.certificateChecking = o.CertificateChecking;
+ this.dateAndTime = o.DateAndTime;
+ this.issuers = o.Issuers;
+ this.maxCrlNumber = o.MaxCrlNumber;
+ this.minCrlNumber = o.MinCrlNumber;
+
+ this.deltaCrlIndicatorEnabled = o.DeltaCrlIndicatorEnabled;
+ this.completeCrlEnabled = o.CompleteCrlEnabled;
+ this.maxBaseCrlNumber = o.MaxBaseCrlNumber;
+ this.attrCertChecking = o.AttrCertChecking;
+ this.issuingDistributionPointEnabled = o.IssuingDistributionPointEnabled;
+ this.issuingDistributionPoint = o.IssuingDistributionPoint;
+ }
+
+ public virtual object Clone()
+ {
+ return new X509CrlStoreSelector(this);
+ }
+
+ public X509Certificate CertificateChecking
+ {
+ get { return certificateChecking; }
+ set { certificateChecking = value; }
+ }
+
+ public DateTimeObject DateAndTime
+ {
+ get { return dateAndTime; }
+ set { dateAndTime = value; }
+ }
+
+ ///
+ /// An ICollection
of X509Name
objects
+ ///
+ public ICollection Issuers
+ {
+ get { return new ArrayList(issuers); }
+ set { issuers = new ArrayList(value); }
+ }
+
+ public BigInteger MaxCrlNumber
+ {
+ get { return maxCrlNumber; }
+ set { maxCrlNumber = value; }
+ }
+
+ public BigInteger MinCrlNumber
+ {
+ get { return minCrlNumber; }
+ set { minCrlNumber = value; }
+ }
+
+ /**
+ * The attribute certificate being checked. This is not a criterion.
+ * Rather, it is optional information that may help a {@link X509Store} find
+ * CRLs that would be relevant when checking revocation for the specified
+ * attribute certificate. If null
is specified, then no such
+ * optional information is provided.
+ *
+ * @param attrCert the IX509AttributeCertificate
being checked (or
+ * null
)
+ * @see #getAttrCertificateChecking()
+ */
+ public IX509AttributeCertificate AttrCertChecking
+ {
+ get { return attrCertChecking; }
+ set { this.attrCertChecking = value; }
+ }
+
+ /**
+ * If true
only complete CRLs are returned. Defaults to
+ * false
.
+ *
+ * @return true
if only complete CRLs are returned.
+ */
+ public bool CompleteCrlEnabled
+ {
+ get { return completeCrlEnabled; }
+ set { this.completeCrlEnabled = value; }
+ }
+
+ /**
+ * Returns if this selector must match CRLs with the delta CRL indicator
+ * extension set. Defaults to false
.
+ *
+ * @return Returns true
if only CRLs with the delta CRL
+ * indicator extension are selected.
+ */
+ public bool DeltaCrlIndicatorEnabled
+ {
+ get { return deltaCrlIndicatorEnabled; }
+ set { this.deltaCrlIndicatorEnabled = value; }
+ }
+
+ /**
+ * The issuing distribution point.
+ *
+ * The issuing distribution point extension is a CRL extension which
+ * identifies the scope and the distribution point of a CRL. The scope
+ * contains among others information about revocation reasons contained in
+ * the CRL. Delta CRLs and complete CRLs must have matching issuing
+ * distribution points.
+ *
+ * The byte array is cloned to protect against subsequent modifications.
+ *
+ * You must also enable or disable this criteria with
+ * {@link #setIssuingDistributionPointEnabled(bool)}.
+ *
+ * @param issuingDistributionPoint The issuing distribution point to set.
+ * This is the DER encoded OCTET STRING extension value.
+ * @see #getIssuingDistributionPoint()
+ */
+ public byte[] IssuingDistributionPoint
+ {
+ get { return Arrays.Clone(issuingDistributionPoint); }
+ set { this.issuingDistributionPoint = Arrays.Clone(value); }
+ }
+
+ /**
+ * Whether the issuing distribution point criteria should be applied.
+ * Defaults to false
.
+ *
+ * You may also set the issuing distribution point criteria if not a missing
+ * issuing distribution point should be assumed.
+ *
+ * @return Returns if the issuing distribution point check is enabled.
+ */
+ public bool IssuingDistributionPointEnabled
+ {
+ get { return issuingDistributionPointEnabled; }
+ set { this.issuingDistributionPointEnabled = value; }
+ }
+
+ /**
+ * The maximum base CRL number. Defaults to null
.
+ *
+ * @return Returns the maximum base CRL number.
+ * @see #setMaxBaseCRLNumber(BigInteger)
+ */
+ public BigInteger MaxBaseCrlNumber
+ {
+ get { return maxBaseCrlNumber; }
+ set { this.maxBaseCrlNumber = value; }
+ }
+
+ public virtual bool Match(
+ object obj)
+ {
+ X509Crl c = obj as X509Crl;
+
+ if (c == null)
+ return false;
+
+ if (dateAndTime != null)
+ {
+ DateTime dt = dateAndTime.Value;
+ DateTime tu = c.ThisUpdate;
+ DateTimeObject nu = c.NextUpdate;
+
+ if (dt.CompareTo(tu) < 0 || nu == null || dt.CompareTo(nu.Value) >= 0)
+ return false;
+ }
+
+ if (issuers != null)
+ {
+ X509Name i = c.IssuerDN;
+
+ bool found = false;
+
+ foreach (X509Name issuer in issuers)
+ {
+ if (issuer.Equivalent(i, true))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ return false;
+ }
+
+ if (maxCrlNumber != null || minCrlNumber != null)
+ {
+ Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.CrlNumber);
+ if (extVal == null)
+ return false;
+
+ BigInteger cn = CrlNumber.GetInstance(
+ X509ExtensionUtilities.FromExtensionValue(extVal)).PositiveValue;
+
+ if (maxCrlNumber != null && cn.CompareTo(maxCrlNumber) > 0)
+ return false;
+
+ if (minCrlNumber != null && cn.CompareTo(minCrlNumber) < 0)
+ return false;
+ }
+
+ DerInteger dci = null;
+ try
+ {
+ Asn1OctetString bytes = c.GetExtensionValue(X509Extensions.DeltaCrlIndicator);
+ if (bytes != null)
+ {
+ dci = DerInteger.GetInstance(X509ExtensionUtilities.FromExtensionValue(bytes));
+ }
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+
+ if (dci == null)
+ {
+ if (DeltaCrlIndicatorEnabled)
+ return false;
+ }
+ else
+ {
+ if (CompleteCrlEnabled)
+ return false;
+
+ if (maxBaseCrlNumber != null && dci.PositiveValue.CompareTo(maxBaseCrlNumber) > 0)
+ return false;
+ }
+
+ if (issuingDistributionPointEnabled)
+ {
+ Asn1OctetString idp = c.GetExtensionValue(X509Extensions.IssuingDistributionPoint);
+ if (issuingDistributionPoint == null)
+ {
+ if (idp != null)
+ return false;
+ }
+ else
+ {
+ if (!Arrays.AreEqual(idp.GetOctets(), issuingDistributionPoint))
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/core/srcbc/x509/store/X509StoreFactory.cs b/src/core/srcbc/x509/store/X509StoreFactory.cs
index 2a2c818..69ea300 100644
--- a/src/core/srcbc/x509/store/X509StoreFactory.cs
+++ b/src/core/srcbc/x509/store/X509StoreFactory.cs
@@ -1,44 +1,61 @@
-using System;
-using System.Globalization;
-
-namespace Org.BouncyCastle.X509.Store
-{
- public sealed class X509StoreFactory
- {
- private X509StoreFactory()
- {
- }
-
- public static IX509Store Create(
- string type,
- IX509StoreParameters parameters)
- {
- if (type == null)
- throw new ArgumentNullException("type");
-
- string[] parts = type.ToUpper(CultureInfo.InvariantCulture).Split('/');
-
- if (parts.Length < 2)
- throw new ArgumentException("type");
-
-
- switch (parts[0])
- {
- case "ATTRIBUTECERTIFICATE":
- case "CERTIFICATE":
- case "CERTIFICATEPAIR":
- case "CRL":
- {
- if (parts[1] == "COLLECTION")
- {
- X509CollectionStoreParameters p = (X509CollectionStoreParameters) parameters;
- return new X509CollectionStore(p.GetCollection());
- }
- break;
- }
- }
-
- throw new NoSuchStoreException("X.509 store type '" + type + "' not available.");
- }
- }
-}
+using System;
+using System.Collections;
+using System.Globalization;
+
+namespace Org.BouncyCastle.X509.Store
+{
+ public sealed class X509StoreFactory
+ {
+ private X509StoreFactory()
+ {
+ }
+
+ public static IX509Store Create(
+ string type,
+ IX509StoreParameters parameters)
+ {
+ if (type == null)
+ throw new ArgumentNullException("type");
+
+ string[] parts = type.ToUpper(CultureInfo.InvariantCulture).Split('/');
+
+ if (parts.Length < 2)
+ throw new ArgumentException("type");
+
+ if (parts[1] != "COLLECTION")
+ throw new NoSuchStoreException("X.509 store type '" + type + "' not available.");
+
+ X509CollectionStoreParameters p = (X509CollectionStoreParameters) parameters;
+ ICollection coll = p.GetCollection();
+
+ switch (parts[0])
+ {
+ case "ATTRIBUTECERTIFICATE":
+ checkCorrectType(coll, typeof(IX509AttributeCertificate));
+ break;
+ case "CERTIFICATE":
+ checkCorrectType(coll, typeof(X509Certificate));
+ break;
+ case "CERTIFICATEPAIR":
+ checkCorrectType(coll, typeof(X509CertificatePair));
+ break;
+ case "CRL":
+ checkCorrectType(coll, typeof(X509Crl));
+ break;
+ default:
+ throw new NoSuchStoreException("X.509 store type '" + type + "' not available.");
+ }
+
+ return new X509CollectionStore(coll);
+ }
+
+ private static void checkCorrectType(ICollection coll, Type t)
+ {
+ foreach (object o in coll)
+ {
+ if (!t.IsInstanceOfType(o))
+ throw new InvalidCastException("Can't cast object to type: " + t.FullName);
+ }
+ }
+ }
+}