BouncyCastle update.
git-svn-id: svn://svn.code.sf.net/p/itextsharp/code/trunk@18 820d3149-562b-4f88-9aa4-a8e61a3485cfmaster
parent
c12d0aa854
commit
f00f5ff42a
|
@ -1,7 +1,7 @@
|
|||
<VisualStudioProject>
|
||||
<CSHARP
|
||||
ProjectType = "Local"
|
||||
ProductVersion = "7.10.3077"
|
||||
ProductVersion = "7.10.6030"
|
||||
SchemaVersion = "2.0"
|
||||
ProjectGuid = "{84C4FDD9-3ED7-453B-B9DA-B3ED52CB071C}"
|
||||
>
|
||||
|
@ -2517,6 +2517,11 @@
|
|||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "srcbc\asn1\IAsn1Choice.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "srcbc\asn1\IAsn1Convertible.cs"
|
||||
SubType = "Code"
|
||||
|
@ -2897,6 +2902,11 @@
|
|||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "srcbc\asn1\esf\SignerAttribute.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "srcbc\asn1\esf\SignerLocation.cs"
|
||||
SubType = "Code"
|
||||
|
@ -4122,6 +4132,11 @@
|
|||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "srcbc\bcpg\sig\EmbeddedSignature.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "srcbc\bcpg\sig\Exportable.cs"
|
||||
SubType = "Code"
|
||||
|
@ -4727,6 +4742,11 @@
|
|||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "srcbc\crypto\engines\CamelliaLightEngine.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "srcbc\crypto\engines\CamelliaWrapEngine.cs"
|
||||
SubType = "Code"
|
||||
|
|
|
@ -1,177 +1,178 @@
|
|||
using System;
|
||||
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1
|
||||
{
|
||||
/**
|
||||
* ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
|
||||
* a [n] where n is some number - these are assumed to follow the construction
|
||||
* rules (as with sequences).
|
||||
*/
|
||||
public abstract class Asn1TaggedObject
|
||||
: Asn1Object, Asn1TaggedObjectParser
|
||||
{
|
||||
internal int tagNo;
|
||||
// internal bool empty;
|
||||
internal bool explicitly = true;
|
||||
internal Asn1Encodable obj;
|
||||
|
||||
static public Asn1TaggedObject GetInstance(
|
||||
Asn1TaggedObject obj,
|
||||
bool explicitly)
|
||||
{
|
||||
if (explicitly)
|
||||
{
|
||||
return (Asn1TaggedObject) obj.GetObject();
|
||||
}
|
||||
|
||||
throw new ArgumentException("implicitly tagged tagged object");
|
||||
}
|
||||
|
||||
static public Asn1TaggedObject GetInstance(
|
||||
object obj)
|
||||
{
|
||||
if (obj == null || obj is Asn1TaggedObject)
|
||||
{
|
||||
return (Asn1TaggedObject) obj;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tagNo the tag number for this object.
|
||||
* @param obj the tagged object.
|
||||
*/
|
||||
protected Asn1TaggedObject(
|
||||
int tagNo,
|
||||
Asn1Encodable obj)
|
||||
{
|
||||
this.explicitly = true;
|
||||
this.tagNo = tagNo;
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param explicitly true if the object is explicitly tagged.
|
||||
* @param tagNo the tag number for this object.
|
||||
* @param obj the tagged object.
|
||||
*/
|
||||
protected Asn1TaggedObject(
|
||||
bool explicitly,
|
||||
int tagNo,
|
||||
Asn1Encodable obj)
|
||||
{
|
||||
this.explicitly = explicitly;
|
||||
this.tagNo = tagNo;
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
protected override bool Asn1Equals(
|
||||
Asn1Object asn1Object)
|
||||
{
|
||||
Asn1TaggedObject other = asn1Object as Asn1TaggedObject;
|
||||
|
||||
if (other == null)
|
||||
return false;
|
||||
|
||||
return this.tagNo == other.tagNo
|
||||
// && this.empty == other.empty
|
||||
&& this.explicitly == other.explicitly // TODO Should this be part of equality?
|
||||
&& Platform.Equals(GetObject(), other.GetObject());
|
||||
}
|
||||
|
||||
protected override int Asn1GetHashCode()
|
||||
{
|
||||
int code = tagNo.GetHashCode();
|
||||
|
||||
// TODO: actually this is wrong - the problem is that a re-encoded
|
||||
// object may end up with a different hashCode due to implicit
|
||||
// tagging. As implicit tagging is ambiguous if a sequence is involved
|
||||
// it seems the only correct method for both equals and hashCode is to
|
||||
// compare the encodings...
|
||||
// code ^= explicitly.GetHashCode();
|
||||
|
||||
if (obj != null)
|
||||
{
|
||||
code ^= obj.GetHashCode();
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
public int TagNo
|
||||
{
|
||||
get { return tagNo; }
|
||||
}
|
||||
|
||||
/**
|
||||
* return whether or not the object may be explicitly tagged.
|
||||
* <p>
|
||||
* Note: if the object has been read from an input stream, the only
|
||||
* time you can be sure if isExplicit is returning the true state of
|
||||
* affairs is if it returns false. An implicitly tagged object may appear
|
||||
* to be explicitly tagged, so you need to understand the context under
|
||||
* which the reading was done as well, see GetObject below.</p>
|
||||
*/
|
||||
public bool IsExplicit()
|
||||
{
|
||||
return explicitly;
|
||||
}
|
||||
|
||||
public bool IsEmpty()
|
||||
{
|
||||
return false; //empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* return whatever was following the tag.
|
||||
* <p>
|
||||
* Note: tagged objects are generally context dependent if you're
|
||||
* trying to extract a tagged object you should be going via the
|
||||
* appropriate GetInstance method.</p>
|
||||
*/
|
||||
public Asn1Object GetObject()
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
return obj.ToAsn1Object();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the object held in this tagged object as a parser assuming it has
|
||||
* the type of the passed in tag. If the object doesn't have a parser
|
||||
* associated with it, the base object is returned.
|
||||
*/
|
||||
public IAsn1Convertible GetObjectParser(
|
||||
int tag,
|
||||
bool isExplicit)
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case Asn1Tags.Set:
|
||||
return Asn1Set.GetInstance(this, isExplicit).Parser;
|
||||
case Asn1Tags.Sequence:
|
||||
return Asn1Sequence.GetInstance(this, isExplicit).Parser;
|
||||
case Asn1Tags.OctetString:
|
||||
return Asn1OctetString.GetInstance(this, isExplicit).Parser;
|
||||
}
|
||||
|
||||
if (isExplicit)
|
||||
{
|
||||
return GetObject();
|
||||
}
|
||||
|
||||
throw Platform.CreateNotImplementedException("implicit tagging for tag: " + tag);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "[" + tagNo + "]" + obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
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.
|
||||
* <p>
|
||||
* Note: if the object has been read from an input stream, the only
|
||||
* time you can be sure if isExplicit is returning the true state of
|
||||
* affairs is if it returns false. An implicitly tagged object may appear
|
||||
* to be explicitly tagged, so you need to understand the context under
|
||||
* which the reading was done as well, see GetObject below.</p>
|
||||
*/
|
||||
public bool IsExplicit()
|
||||
{
|
||||
return explicitly;
|
||||
}
|
||||
|
||||
public bool IsEmpty()
|
||||
{
|
||||
return false; //empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* return whatever was following the tag.
|
||||
* <p>
|
||||
* Note: tagged objects are generally context dependent if you're
|
||||
* trying to extract a tagged object you should be going via the
|
||||
* appropriate GetInstance method.</p>
|
||||
*/
|
||||
public Asn1Object GetObject()
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
return obj.ToAsn1Object();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the object held in this tagged object as a parser assuming it has
|
||||
* the type of the passed in tag. If the object doesn't have a parser
|
||||
* associated with it, the base object is returned.
|
||||
*/
|
||||
public IAsn1Convertible GetObjectParser(
|
||||
int tag,
|
||||
bool isExplicit)
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case Asn1Tags.Set:
|
||||
return Asn1Set.GetInstance(this, isExplicit).Parser;
|
||||
case Asn1Tags.Sequence:
|
||||
return Asn1Sequence.GetInstance(this, isExplicit).Parser;
|
||||
case Asn1Tags.OctetString:
|
||||
return Asn1OctetString.GetInstance(this, isExplicit).Parser;
|
||||
}
|
||||
|
||||
if (isExplicit)
|
||||
{
|
||||
return GetObject();
|
||||
}
|
||||
|
||||
throw Platform.CreateNotImplementedException("implicit tagging for tag: " + tag);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "[" + tagNo + "]" + obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* <p>
|
||||
* If you use this interface your class should also implement the getInstance
|
||||
* pattern which takes a tag object and the tagging mode used.
|
||||
* </p>
|
||||
*/
|
||||
public interface IAsn1Choice
|
||||
{
|
||||
// marker interface
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,89 +1,88 @@
|
|||
using System;
|
||||
|
||||
using Org.BouncyCastle.Asn1.Oiw;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.Esf
|
||||
{
|
||||
/// <remarks>
|
||||
/// <code>
|
||||
/// OtherHash ::= CHOICE {
|
||||
/// sha1Hash OtherHashValue, -- This contains a SHA-1 hash
|
||||
/// otherHash OtherHashAlgAndValue
|
||||
/// }
|
||||
///
|
||||
/// OtherHashValue ::= OCTET STRING
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
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
|
||||
{
|
||||
/// <remarks>
|
||||
/// <code>
|
||||
/// OtherHash ::= CHOICE {
|
||||
/// sha1Hash OtherHashValue, -- This contains a SHA-1 hash
|
||||
/// otherHash OtherHashAlgAndValue
|
||||
/// }
|
||||
///
|
||||
/// OtherHashValue ::= OCTET STRING
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,65 +1,64 @@
|
|||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.Esf
|
||||
{
|
||||
/// <remarks>
|
||||
/// <code>
|
||||
/// SignaturePolicyIdentifier ::= CHOICE {
|
||||
/// SignaturePolicyId SignaturePolicyId,
|
||||
/// SignaturePolicyImplied SignaturePolicyImplied
|
||||
/// }
|
||||
///
|
||||
/// SignaturePolicyImplied ::= NULL
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
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
|
||||
{
|
||||
/// <remarks>
|
||||
/// <code>
|
||||
/// SignaturePolicyIdentifier ::= CHOICE {
|
||||
/// SignaturePolicyId SignaturePolicyId,
|
||||
/// SignaturePolicyImplied SignaturePolicyImplied
|
||||
/// }
|
||||
///
|
||||
/// SignaturePolicyImplied ::= NULL
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* <pre>
|
||||
* 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.
|
||||
* </pre>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* EssCertIDv2 ::= SEQUENCE {
|
||||
* hashAlgorithm AlgorithmIdentifier
|
||||
* DEFAULT {algorithm id-sha256 parameters NULL},
|
||||
* certHash Hash,
|
||||
* issuerSerial IssuerSerial OPTIONAL
|
||||
* }
|
||||
*
|
||||
* Hash ::= OCTET STRING
|
||||
*
|
||||
* IssuerSerial ::= SEQUENCE {
|
||||
* issuer GeneralNames,
|
||||
* serialNumber CertificateSerialNumber
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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; }
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* EssCertIDv2 ::= SEQUENCE {
|
||||
* hashAlgorithm AlgorithmIdentifier
|
||||
* DEFAULT {algorithm id-sha256},
|
||||
* certHash Hash,
|
||||
* issuerSerial IssuerSerial OPTIONAL
|
||||
* }
|
||||
*
|
||||
* Hash ::= OCTET STRING
|
||||
*
|
||||
* IssuerSerial ::= SEQUENCE {
|
||||
* issuer GeneralNames,
|
||||
* serialNumber CertificateSerialNumber
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* <p/>
|
||||
* ISIS-MTT-SigG: The signature act allows publishing certificates only then,
|
||||
* when the certificate owner gives his isExplicit permission. Accordingly, there
|
||||
* may be <EFBFBD>nondownloadable<EFBFBD> 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:
|
||||
* <ul>
|
||||
* <li> a) the responder supports the extension and is allowed to publish the
|
||||
* certificate: RequestedCertificate returned including the requested
|
||||
* certificate</li>
|
||||
* <li>b) the responder supports the extension but is NOT allowed to publish
|
||||
* the certificate: RequestedCertificate returned including an empty OCTET
|
||||
* STRING</li>
|
||||
* <li>c) the responder does not support the extension: RequestedCertificate is
|
||||
* not included in the response</li>
|
||||
* </ul>
|
||||
* 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.
|
||||
* <p/>
|
||||
* <pre>
|
||||
* RequestedCertificate ::= CHOICE {
|
||||
* Certificate Certificate,
|
||||
* publicKeyCertificate [0] EXPLICIT OCTET STRING,
|
||||
* attributeCertificate [1] EXPLICIT OCTET STRING
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <p/>
|
||||
* Only one parameter can be given. All other must be <code>null</code>.
|
||||
*
|
||||
* @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.
|
||||
* <p/>
|
||||
* Returns:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* RequestedCertificate ::= CHOICE {
|
||||
* Certificate Certificate,
|
||||
* publicKeyCertificate [0] EXPLICIT OCTET STRING,
|
||||
* attributeCertificate [1] EXPLICIT OCTET STRING
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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.
|
||||
* <p/>
|
||||
* ISIS-MTT-SigG: The signature act allows publishing certificates only then,
|
||||
* when the certificate owner gives his isExplicit permission. Accordingly, there
|
||||
* may be <EFBFBD>nondownloadable<EFBFBD> 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:
|
||||
* <ul>
|
||||
* <li> a) the responder supports the extension and is allowed to publish the
|
||||
* certificate: RequestedCertificate returned including the requested
|
||||
* certificate</li>
|
||||
* <li>b) the responder supports the extension but is NOT allowed to publish
|
||||
* the certificate: RequestedCertificate returned including an empty OCTET
|
||||
* STRING</li>
|
||||
* <li>c) the responder does not support the extension: RequestedCertificate is
|
||||
* not included in the response</li>
|
||||
* </ul>
|
||||
* 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.
|
||||
* <p/>
|
||||
* <pre>
|
||||
* RequestedCertificate ::= CHOICE {
|
||||
* Certificate Certificate,
|
||||
* publicKeyCertificate [0] EXPLICIT OCTET STRING,
|
||||
* attributeCertificate [1] EXPLICIT OCTET STRING
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <p/>
|
||||
* Only one parameter can be given. All other must be <code>null</code>.
|
||||
*
|
||||
* @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.
|
||||
* <p/>
|
||||
* Returns:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* RequestedCertificate ::= CHOICE {
|
||||
* Certificate Certificate,
|
||||
* publicKeyCertificate [0] EXPLICIT OCTET STRING,
|
||||
* attributeCertificate [1] EXPLICIT OCTET STRING
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,171 +1,170 @@
|
|||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.IsisMtt.X509
|
||||
{
|
||||
/**
|
||||
* A declaration of majority.
|
||||
* <p/>
|
||||
* <pre>
|
||||
* DeclarationOfMajoritySyntax ::= CHOICE
|
||||
* {
|
||||
* notYoungerThan [0] IMPLICIT INTEGER,
|
||||
* fullAgeAtCountry [1] IMPLICIT SEQUENCE
|
||||
* {
|
||||
* fullAge BOOLEAN DEFAULT TRUE,
|
||||
* country PrintableString (SIZE(2))
|
||||
* }
|
||||
* dateOfBirth [2] IMPLICIT GeneralizedTime
|
||||
* }
|
||||
* </pre>
|
||||
* <p/>
|
||||
* 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.
|
||||
* <p/>
|
||||
* Returns:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* DeclarationOfMajoritySyntax ::= CHOICE
|
||||
* {
|
||||
* notYoungerThan [0] IMPLICIT INTEGER,
|
||||
* fullAgeAtCountry [1] IMPLICIT SEQUENCE
|
||||
* {
|
||||
* fullAge BOOLEAN DEFAULT TRUE,
|
||||
* country PrintableString (SIZE(2))
|
||||
* }
|
||||
* dateOfBirth [2] IMPLICIT GeneralizedTime
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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.
|
||||
* <p/>
|
||||
* <pre>
|
||||
* DeclarationOfMajoritySyntax ::= CHOICE
|
||||
* {
|
||||
* notYoungerThan [0] IMPLICIT INTEGER,
|
||||
* fullAgeAtCountry [1] IMPLICIT SEQUENCE
|
||||
* {
|
||||
* fullAge BOOLEAN DEFAULT TRUE,
|
||||
* country PrintableString (SIZE(2))
|
||||
* }
|
||||
* dateOfBirth [2] IMPLICIT GeneralizedTime
|
||||
* }
|
||||
* </pre>
|
||||
* <p/>
|
||||
* 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.
|
||||
* <p/>
|
||||
* Returns:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* DeclarationOfMajoritySyntax ::= CHOICE
|
||||
* {
|
||||
* notYoungerThan [0] IMPLICIT INTEGER,
|
||||
* fullAgeAtCountry [1] IMPLICIT SEQUENCE
|
||||
* {
|
||||
* fullAge BOOLEAN DEFAULT TRUE,
|
||||
* country PrintableString (SIZE(2))
|
||||
* }
|
||||
* dateOfBirth [2] IMPLICIT GeneralizedTime
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* <pre>
|
||||
* CertStatus ::= CHOICE {
|
||||
* good [0] IMPLICIT Null,
|
||||
* revoked [1] IMPLICIT RevokedInfo,
|
||||
* unknown [2] IMPLICIT UnknownInfo }
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <pre>
|
||||
* CertStatus ::= CHOICE {
|
||||
* good [0] IMPLICIT Null,
|
||||
* revoked [1] IMPLICIT RevokedInfo,
|
||||
* unknown [2] IMPLICIT UnknownInfo }
|
||||
* </pre>
|
||||
*/
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
return new DerTaggedObject(false, tagNo, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* <pre>
|
||||
* ResponderID ::= CHOICE {
|
||||
* byName [1] Name,
|
||||
* byKey [2] KeyHash }
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <pre>
|
||||
* ResponderID ::= CHOICE {
|
||||
* byName [1] Name,
|
||||
* byKey [2] KeyHash }
|
||||
* </pre>
|
||||
*/
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
if (id is Asn1OctetString)
|
||||
{
|
||||
return new DerTaggedObject(true, 2, id);
|
||||
}
|
||||
|
||||
return new DerTaggedObject(true, 1, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* <pre>
|
||||
* TBSRequest ::= Sequence {
|
||||
* version [0] EXPLICIT Version DEFAULT v1,
|
||||
* requestorName [1] EXPLICIT GeneralName OPTIONAL,
|
||||
* requestList Sequence OF Request,
|
||||
* requestExtensions [2] EXPLICIT Extensions OPTIONAL }
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <pre>
|
||||
* TBSRequest ::= Sequence {
|
||||
* version [0] EXPLICIT Version DEFAULT v1,
|
||||
* requestorName [1] EXPLICIT GeneralName OPTIONAL,
|
||||
* requestList Sequence OF Request,
|
||||
* requestExtensions [2] EXPLICIT Extensions OPTIONAL }
|
||||
* </pre>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 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)) }
|
||||
* </pre>
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 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)) }
|
||||
* </pre>
|
||||
*/
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
return str.ToAsn1Object();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,88 +1,83 @@
|
|||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509
|
||||
{
|
||||
/**
|
||||
* The AccessDescription object.
|
||||
* <pre>
|
||||
* AccessDescription ::= SEQUENCE {
|
||||
* accessMethod OBJECT IDENTIFIER,
|
||||
* accessLocation GeneralName }
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <pre>
|
||||
* AccessDescription ::= SEQUENCE {
|
||||
* accessMethod OBJECT IDENTIFIER,
|
||||
* accessLocation GeneralName }
|
||||
* </pre>
|
||||
*/
|
||||
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 + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Don't use this one if you are trying to be RFC 3281 compliant.
|
||||
/// Use it for v1 attribute certificates only.
|
||||
/// </summary>
|
||||
/// <param name="names">Our GeneralNames structure</param>
|
||||
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.
|
||||
* <pre>
|
||||
* AttCertIssuer ::= CHOICE {
|
||||
* v1Form GeneralNames, -- MUST NOT be used in this
|
||||
* -- profile
|
||||
* v2Form [0] V2Form -- v2 only
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Don't use this one if you are trying to be RFC 3281 compliant.
|
||||
/// Use it for v1 attribute certificates only.
|
||||
/// </summary>
|
||||
/// <param name="names">Our GeneralNames structure</param>
|
||||
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.
|
||||
* <pre>
|
||||
* AttCertIssuer ::= CHOICE {
|
||||
* v1Form GeneralNames, -- MUST NOT be used in this
|
||||
* -- profile
|
||||
* v2Form [0] V2Form -- v2 only
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
return choiceObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,87 +1,105 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509
|
||||
{
|
||||
/**
|
||||
* The AuthorityInformationAccess object.
|
||||
* <pre>
|
||||
* 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 }
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <pre>
|
||||
* 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 }
|
||||
* </pre>
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,172 +1,172 @@
|
|||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509
|
||||
{
|
||||
/**
|
||||
* <code>DisplayText</code> class, used in
|
||||
* <code>CertificatePolicies</code> X509 V3 extensions (in policy qualifiers).
|
||||
*
|
||||
* <p>It stores a string in a chosen encoding.
|
||||
* <pre>
|
||||
* DisplayText ::= CHOICE {
|
||||
* ia5String IA5String (SIZE (1..200)),
|
||||
* visibleString VisibleString (SIZE (1..200)),
|
||||
* bmpString BMPString (SIZE (1..200)),
|
||||
* utf8String UTF8String (SIZE (1..200)) }
|
||||
* </pre></p>
|
||||
* @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 <code>DisplayTextMaximumSize</code> here.
|
||||
*
|
||||
*/
|
||||
public const int DisplayTextMaximumSize = 200;
|
||||
|
||||
internal readonly int contentType;
|
||||
internal readonly IAsn1String contents;
|
||||
|
||||
/**
|
||||
* Creates a new <code>DisplayText</code> 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 <code>DisplayText</code> 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 <code>DisplayText</code> instance.
|
||||
* <p>Useful when reading back a <code>DisplayText</code> class
|
||||
* from it's Asn1Encodable form.</p>
|
||||
*
|
||||
* @param contents an <code>Asn1Encodable</code> 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 <code>string</code> object.
|
||||
*
|
||||
* @return the stored text as a <code>string</code>.
|
||||
*/
|
||||
public string GetString()
|
||||
{
|
||||
return contents.GetString();
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509
|
||||
{
|
||||
/**
|
||||
* <code>DisplayText</code> class, used in
|
||||
* <code>CertificatePolicies</code> X509 V3 extensions (in policy qualifiers).
|
||||
*
|
||||
* <p>It stores a string in a chosen encoding.
|
||||
* <pre>
|
||||
* DisplayText ::= CHOICE {
|
||||
* ia5String IA5String (SIZE (1..200)),
|
||||
* visibleString VisibleString (SIZE (1..200)),
|
||||
* bmpString BMPString (SIZE (1..200)),
|
||||
* utf8String UTF8String (SIZE (1..200)) }
|
||||
* </pre></p>
|
||||
* @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 <code>DisplayTextMaximumSize</code> here.
|
||||
*
|
||||
*/
|
||||
public const int DisplayTextMaximumSize = 200;
|
||||
|
||||
internal readonly int contentType;
|
||||
internal readonly IAsn1String contents;
|
||||
|
||||
/**
|
||||
* Creates a new <code>DisplayText</code> 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 <code>DisplayText</code> 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 <code>DisplayText</code> instance.
|
||||
* <p>Useful when reading back a <code>DisplayText</code> class
|
||||
* from it's Asn1Encodable form.</p>
|
||||
*
|
||||
* @param contents an <code>Asn1Encodable</code> 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 <code>string</code> object.
|
||||
*
|
||||
* @return the stored text as a <code>string</code>.
|
||||
*/
|
||||
public string GetString()
|
||||
{
|
||||
return contents.GetString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,130 +1,130 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509
|
||||
{
|
||||
/**
|
||||
* The DistributionPointName object.
|
||||
* <pre>
|
||||
* DistributionPointName ::= CHOICE {
|
||||
* fullName [0] GeneralNames,
|
||||
* nameRelativeToCRLIssuer [1] RelativeDistinguishedName
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <pre>
|
||||
* DistributionPointName ::= CHOICE {
|
||||
* fullName [0] GeneralNames,
|
||||
* nameRelativeToCRLIssuer [1] RelativeDistinguishedName
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* <pre>
|
||||
* 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 }
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* This constructor can handle:
|
||||
* <ul>
|
||||
* <li>rfc822Name</li>
|
||||
* <li>iPAddress</li>
|
||||
* <li>directoryName</li>
|
||||
* <li>dNSName</li>
|
||||
* <li>uniformResourceIdentifier</li>
|
||||
* <li>registeredID</li>
|
||||
* </ul>
|
||||
* For x400Address, otherName and ediPartyName there is no common string
|
||||
* format defined.
|
||||
* </p><p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* @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.
|
||||
* <pre>
|
||||
* 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 }
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* This constructor can handle:
|
||||
* <ul>
|
||||
* <li>rfc822Name</li>
|
||||
* <li>iPAddress</li>
|
||||
* <li>directoryName</li>
|
||||
* <li>dNSName</li>
|
||||
* <li>uniformResourceIdentifier</li>
|
||||
* <li>registeredID</li>
|
||||
* </ul>
|
||||
* For x400Address, otherName and ediPartyName there is no common string
|
||||
* format defined.
|
||||
* </p><p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
/// <summary>Construct a GeneralNames object containing one GeneralName.</summary>
|
||||
/// <param name="name">The name to be contained.</param>
|
||||
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.
|
||||
* <pre>
|
||||
* GeneralNames ::= Sequence SIZE {1..MAX} OF GeneralName
|
||||
* </pre>
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>Construct a GeneralNames object containing one GeneralName.</summary>
|
||||
/// <param name="name">The name to be contained.</param>
|
||||
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.
|
||||
* <pre>
|
||||
* GeneralNames ::= Sequence SIZE {1..MAX} OF GeneralName
|
||||
* </pre>
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,234 +1,234 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509
|
||||
{
|
||||
/**
|
||||
* Implementation of the RoleSyntax object as specified by the RFC3281.
|
||||
*
|
||||
* <pre>
|
||||
* RoleSyntax ::= SEQUENCE {
|
||||
* roleAuthority [0] GeneralNames OPTIONAL,
|
||||
* roleName [1] GeneralName
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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 <code>
|
||||
* RoleSyntax</code>. It must be an instance of <code>RoleSyntax
|
||||
* </code> or <code>Asn1Sequence</code>.
|
||||
* @return the instance of <code>RoleSyntax</code> built from the
|
||||
* supplied object.
|
||||
* @throws java.lang.ArgumentException if the object passed
|
||||
* to the factory is not an instance of <code>RoleSyntax</code> or
|
||||
* <code>Asn1Sequence</code>.
|
||||
*/
|
||||
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
|
||||
* <code>new RoleSyntax(null, roleName)</code>.
|
||||
* @param roleName the role name of this RoleSyntax.
|
||||
*/
|
||||
public RoleSyntax(
|
||||
GeneralName roleName)
|
||||
: this(null, roleName)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility constructor. Takes a <code>string</code> argument representing
|
||||
* the role name, builds a <code>GeneralName</code> to hold the role name
|
||||
* and calls the constructor that takes a <code>GeneralName</code>.
|
||||
* @param roleName
|
||||
*/
|
||||
public RoleSyntax(
|
||||
string roleName)
|
||||
: this(new GeneralName(GeneralName.UniformResourceIdentifier,
|
||||
(roleName == null)? "": roleName))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that builds an instance of <code>RoleSyntax</code> by
|
||||
* extracting the encoded elements from the <code>Asn1Sequence</code>
|
||||
* object supplied.
|
||||
* @param seq an instance of <code>Asn1Sequence</code> that holds
|
||||
* the encoded elements used to build this <code>RoleSyntax</code>.
|
||||
*/
|
||||
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 <code>GeneralNames</code> 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 <code>GeneralName</code> holding the
|
||||
* role name of this RoleSyntax.
|
||||
*/
|
||||
public GeneralName RoleName
|
||||
{
|
||||
get { return this.roleName; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the role name as a <code>java.lang.string</code> object.
|
||||
* @return the role name of this RoleSyntax represented as a
|
||||
* <code>string</code> object.
|
||||
*/
|
||||
public string GetRoleNameAsString()
|
||||
{
|
||||
return ((IAsn1String) this.roleName.Name).GetString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the role authority as a <code>string[]</code> object.
|
||||
* @return the role authority of this RoleSyntax represented as a
|
||||
* <code>string[]</code> 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 <code>ToAsn1Object</code> as
|
||||
* required by the superclass <code>ASN1Encodable</code>.
|
||||
*
|
||||
* <pre>
|
||||
* RoleSyntax ::= SEQUENCE {
|
||||
* roleAuthority [0] GeneralNames OPTIONAL,
|
||||
* roleName [1] GeneralName
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* <pre>
|
||||
* RoleSyntax ::= SEQUENCE {
|
||||
* roleAuthority [0] GeneralNames OPTIONAL,
|
||||
* roleName [1] GeneralName
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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 <code>
|
||||
* RoleSyntax</code>. It must be an instance of <code>RoleSyntax
|
||||
* </code> or <code>Asn1Sequence</code>.
|
||||
* @return the instance of <code>RoleSyntax</code> built from the
|
||||
* supplied object.
|
||||
* @throws java.lang.ArgumentException if the object passed
|
||||
* to the factory is not an instance of <code>RoleSyntax</code> or
|
||||
* <code>Asn1Sequence</code>.
|
||||
*/
|
||||
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
|
||||
* <code>new RoleSyntax(null, roleName)</code>.
|
||||
* @param roleName the role name of this RoleSyntax.
|
||||
*/
|
||||
public RoleSyntax(
|
||||
GeneralName roleName)
|
||||
: this(null, roleName)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility constructor. Takes a <code>string</code> argument representing
|
||||
* the role name, builds a <code>GeneralName</code> to hold the role name
|
||||
* and calls the constructor that takes a <code>GeneralName</code>.
|
||||
* @param roleName
|
||||
*/
|
||||
public RoleSyntax(
|
||||
string roleName)
|
||||
: this(new GeneralName(GeneralName.UniformResourceIdentifier,
|
||||
(roleName == null)? "": roleName))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that builds an instance of <code>RoleSyntax</code> by
|
||||
* extracting the encoded elements from the <code>Asn1Sequence</code>
|
||||
* object supplied.
|
||||
* @param seq an instance of <code>Asn1Sequence</code> that holds
|
||||
* the encoded elements used to build this <code>RoleSyntax</code>.
|
||||
*/
|
||||
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 <code>GeneralNames</code> 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 <code>GeneralName</code> holding the
|
||||
* role name of this RoleSyntax.
|
||||
*/
|
||||
public GeneralName RoleName
|
||||
{
|
||||
get { return this.roleName; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the role name as a <code>java.lang.string</code> object.
|
||||
* @return the role name of this RoleSyntax represented as a
|
||||
* <code>string</code> object.
|
||||
*/
|
||||
public string GetRoleNameAsString()
|
||||
{
|
||||
return ((IAsn1String) this.roleName.Name).GetString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the role authority as a <code>string[]</code> object.
|
||||
* @return the role authority of this RoleSyntax represented as a
|
||||
* <code>string[]</code> 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 <code>ToAsn1Object</code> as
|
||||
* required by the superclass <code>ASN1Encodable</code>.
|
||||
*
|
||||
* <pre>
|
||||
* RoleSyntax ::= SEQUENCE {
|
||||
* roleAuthority [0] GeneralNames OPTIONAL,
|
||||
* roleName [1] GeneralName
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,140 +1,139 @@
|
|||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509
|
||||
{
|
||||
/**
|
||||
* Target structure used in target information extension for attribute
|
||||
* certificates from RFC 3281.
|
||||
*
|
||||
* <pre>
|
||||
* Target ::= CHOICE {
|
||||
* targetName [0] GeneralName,
|
||||
* targetGroup [1] GeneralName,
|
||||
* targetCert [2] TargetCert
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* The targetCert field is currently not supported and must not be used
|
||||
* according to RFC 3281.</p>
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* <code>obj</code> can be a Target or a {@link Asn1TaggedObject}</p>
|
||||
*
|
||||
* @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.
|
||||
* <p>
|
||||
* Exactly one of the parameters must be not <code>null</code>.</p>
|
||||
*
|
||||
* @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:
|
||||
*
|
||||
* <pre>
|
||||
* Target ::= CHOICE {
|
||||
* targetName [0] GeneralName,
|
||||
* targetGroup [1] GeneralName,
|
||||
* targetCert [2] TargetCert
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* <pre>
|
||||
* Target ::= CHOICE {
|
||||
* targetName [0] GeneralName,
|
||||
* targetGroup [1] GeneralName,
|
||||
* targetCert [2] TargetCert
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* The targetCert field is currently not supported and must not be used
|
||||
* according to RFC 3281.</p>
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* <code>obj</code> can be a Target or a {@link Asn1TaggedObject}</p>
|
||||
*
|
||||
* @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.
|
||||
* <p>
|
||||
* Exactly one of the parameters must be not <code>null</code>.</p>
|
||||
*
|
||||
* @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:
|
||||
*
|
||||
* <pre>
|
||||
* Target ::= CHOICE {
|
||||
* targetName [0] GeneralName,
|
||||
* targetGroup [1] GeneralName,
|
||||
* targetCert [2] TargetCert
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return our time as DateTime.
|
||||
/// </summary>
|
||||
/// <returns>A date time.</returns>
|
||||
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.
|
||||
* <pre>
|
||||
* Time ::= CHOICE {
|
||||
* utcTime UTCTime,
|
||||
* generalTime GeneralizedTime }
|
||||
* </pre>
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return our time as DateTime.
|
||||
/// </summary>
|
||||
/// <returns>A date time.</returns>
|
||||
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.
|
||||
* <pre>
|
||||
* Time ::= CHOICE {
|
||||
* utcTime UTCTime,
|
||||
* generalTime GeneralizedTime }
|
||||
* </pre>
|
||||
*/
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
return time;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return GetTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,84 +1,84 @@
|
|||
using System;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509.Qualified
|
||||
{
|
||||
/**
|
||||
* The Iso4217CurrencyCode object.
|
||||
* <pre>
|
||||
* 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
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <pre>
|
||||
* 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
|
||||
* </pre>
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,91 +1,91 @@
|
|||
using System;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509.Qualified
|
||||
{
|
||||
/**
|
||||
* The TypeOfBiometricData object.
|
||||
* <pre>
|
||||
* TypeOfBiometricData ::= CHOICE {
|
||||
* predefinedBiometricType PredefinedBiometricType,
|
||||
* biometricDataOid OBJECT IDENTIFIER }
|
||||
*
|
||||
* PredefinedBiometricType ::= INTEGER {
|
||||
* picture(0),handwritten-signature(1)}
|
||||
* (picture|handwritten-signature)
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <pre>
|
||||
* TypeOfBiometricData ::= CHOICE {
|
||||
* predefinedBiometricType PredefinedBiometricType,
|
||||
* biometricDataOid OBJECT IDENTIFIER }
|
||||
*
|
||||
* PredefinedBiometricType ::= INTEGER {
|
||||
* picture(0),handwritten-signature(1)}
|
||||
* (picture|handwritten-signature)
|
||||
* </pre>
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
* NameOrPseudonym ::= CHOICE {
|
||||
* surAndGivenName SEQUENCE {
|
||||
* surName DirectoryString,
|
||||
* givenName SEQUENCE OF DirectoryString
|
||||
* },
|
||||
* pseudonym DirectoryString
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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.
|
||||
* <p/>
|
||||
* The sequence is of type NameOrPseudonym:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* NameOrPseudonym ::= CHOICE {
|
||||
* surAndGivenName SEQUENCE {
|
||||
* surName DirectoryString,
|
||||
* givenName SEQUENCE OF DirectoryString
|
||||
* },
|
||||
* pseudonym DirectoryString
|
||||
* }
|
||||
* </pre>
|
||||
* @param pseudonym pseudonym value to use.
|
||||
*/
|
||||
public NameOrPseudonym(
|
||||
DirectoryString pseudonym)
|
||||
{
|
||||
this.pseudonym = pseudonym;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor from Asn1Sequence.
|
||||
* <p/>
|
||||
* The sequence is of type NameOrPseudonym:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* NameOrPseudonym ::= CHOICE {
|
||||
* surAndGivenName SEQUENCE {
|
||||
* surName DirectoryString,
|
||||
* givenName SEQUENCE OF DirectoryString
|
||||
* },
|
||||
* pseudonym DirectoryString
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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.
|
||||
* <p/>
|
||||
* Returns:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* NameOrPseudonym ::= CHOICE {
|
||||
* surAndGivenName SEQUENCE {
|
||||
* surName DirectoryString,
|
||||
* givenName SEQUENCE OF DirectoryString
|
||||
* },
|
||||
* pseudonym DirectoryString
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* <pre>
|
||||
* NameOrPseudonym ::= CHOICE {
|
||||
* surAndGivenName SEQUENCE {
|
||||
* surName DirectoryString,
|
||||
* givenName SEQUENCE OF DirectoryString
|
||||
* },
|
||||
* pseudonym DirectoryString
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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.
|
||||
* <p/>
|
||||
* The sequence is of type NameOrPseudonym:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* NameOrPseudonym ::= CHOICE {
|
||||
* surAndGivenName SEQUENCE {
|
||||
* surName DirectoryString,
|
||||
* givenName SEQUENCE OF DirectoryString
|
||||
* },
|
||||
* pseudonym DirectoryString
|
||||
* }
|
||||
* </pre>
|
||||
* @param pseudonym pseudonym value to use.
|
||||
*/
|
||||
public NameOrPseudonym(
|
||||
DirectoryString pseudonym)
|
||||
{
|
||||
this.pseudonym = pseudonym;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor from Asn1Sequence.
|
||||
* <p/>
|
||||
* The sequence is of type NameOrPseudonym:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* NameOrPseudonym ::= CHOICE {
|
||||
* surAndGivenName SEQUENCE {
|
||||
* surName DirectoryString,
|
||||
* givenName SEQUENCE OF DirectoryString
|
||||
* },
|
||||
* pseudonym DirectoryString
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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.
|
||||
* <p/>
|
||||
* Returns:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* NameOrPseudonym ::= CHOICE {
|
||||
* surAndGivenName SEQUENCE {
|
||||
* surName DirectoryString,
|
||||
* givenName SEQUENCE OF DirectoryString
|
||||
* },
|
||||
* pseudonym DirectoryString
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @return an Asn1Object
|
||||
*/
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
if (pseudonym != null)
|
||||
{
|
||||
return pseudonym.ToAsn1Object();
|
||||
}
|
||||
|
||||
return new DerSequence(surname, givenName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* <pre>
|
||||
* Parameters ::= CHOICE {
|
||||
* ecParameters ECParameters,
|
||||
* namedCurve CURVES.&id({CurveNames}),
|
||||
* implicitlyCA Null
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <pre>
|
||||
* Parameters ::= CHOICE {
|
||||
* ecParameters ECParameters,
|
||||
* namedCurve CURVES.&id({CurveNames}),
|
||||
* implicitlyCA Null
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
return _params;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* <pre>
|
||||
* ECParameters ::= Sequence {
|
||||
* version Integer { ecpVer1(1) } (ecpVer1),
|
||||
* fieldID FieldID {{FieldTypes}},
|
||||
* curve X9Curve,
|
||||
* base X9ECPoint,
|
||||
* order Integer,
|
||||
* cofactor Integer OPTIONAL
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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.
|
||||
* <pre>
|
||||
* ECParameters ::= Sequence {
|
||||
* version Integer { ecpVer1(1) } (ecpVer1),
|
||||
* fieldID FieldID {{FieldTypes}},
|
||||
* curve X9Curve,
|
||||
* base X9ECPoint,
|
||||
* order Integer,
|
||||
* cofactor Integer OPTIONAL
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Note</b>: 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Note</b>: 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,38 +1,47 @@
|
|||
using System;
|
||||
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Generators;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Org.BouncyCastle.Cms
|
||||
{
|
||||
/// <summary>
|
||||
/// PKCS5 scheme-2 - password converted to bytes assuming ASCII.
|
||||
/// </summary>
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// PKCS5 scheme-2 - password converted to bytes assuming ASCII.
|
||||
/// </summary>
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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.
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
* <p>
|
||||
* The static property is checked during construction of the encoding object, it is set to
|
||||
* true by default.
|
||||
* </p>
|
||||
*/
|
||||
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
|
||||
* <p>
|
||||
* The static property is checked during construction of the encoding object, it is set to
|
||||
* true by default.
|
||||
* </p>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* <p>
|
||||
* Internal access to the digest is syncrhonized so a single one of these can be shared.
|
||||
* </p>
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* Internal access to the digest is synchronized so a single one of these can be shared.
|
||||
* </p>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,196 +1,196 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Org.BouncyCastle.Crypto.Digests;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls
|
||||
{
|
||||
/// <remarks>A generic TLS 1.0 block cipher suite. This can be used for AES or 3DES for example.</remarks>
|
||||
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
|
||||
{
|
||||
/// <remarks>A generic TLS 1.0 block cipher suite. This can be used for AES or 3DES for example.</remarks>
|
||||
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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,166 +1,166 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace Org.BouncyCastle.Bcpg.OpenPgp
|
||||
{
|
||||
/// <remarks>
|
||||
/// Generator for a PGP master and subkey ring.
|
||||
/// This class will generate both the secret and public key rings
|
||||
/// </remarks>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new key ring generator using old style checksumming. It is recommended to use
|
||||
/// SHA1 checksumming where possible.
|
||||
/// </summary>
|
||||
/// <param name="certificationLevel">The certification level for keys on this ring.</param>
|
||||
/// <param name="masterKey">The master key pair.</param>
|
||||
/// <param name="id">The id to be associated with the ring.</param>
|
||||
/// <param name="encAlgorithm">The algorithm to be used to protect secret keys.</param>
|
||||
/// <param name="passPhrase">The passPhrase to be used to protect secret keys.</param>
|
||||
/// <param name="hashedPackets">Packets to be included in the certification hash.</param>
|
||||
/// <param name="unhashedPackets">Packets to be attached unhashed to the certification.</param>
|
||||
/// <param name="rand">input secured random.</param>
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new key ring generator.
|
||||
/// </summary>
|
||||
/// <param name="certificationLevel">The certification level for keys on this ring.</param>
|
||||
/// <param name="masterKey">The master key pair.</param>
|
||||
/// <param name="id">The id to be associated with the ring.</param>
|
||||
/// <param name="encAlgorithm">The algorithm to be used to protect secret keys.</param>
|
||||
/// <param name="passPhrase">The passPhrase to be used to protect secret keys.</param>
|
||||
/// <param name="useSha1">Checksum the secret keys with SHA1 rather than the older 16 bit checksum.</param>
|
||||
/// <param name="hashedPackets">Packets to be included in the certification hash.</param>
|
||||
/// <param name="unhashedPackets">Packets to be attached unhashed to the certification.</param>
|
||||
/// <param name="rand">input secured random.</param>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>Add a subkey to the key ring to be generated with default certification.</summary>
|
||||
public void AddSubKey(
|
||||
PgpKeyPair keyPair)
|
||||
{
|
||||
AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a subkey with specific hashed and unhashed packets associated with it and
|
||||
/// default certification.
|
||||
/// </summary>
|
||||
/// <param name="keyPair">Public/private key pair.</param>
|
||||
/// <param name="hashedPackets">Hashed packet values to be included in certification.</param>
|
||||
/// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param>
|
||||
/// <exception cref="PgpException"></exception>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Return the secret key ring.</summary>
|
||||
public PgpSecretKeyRing GenerateSecretKeyRing()
|
||||
{
|
||||
return new PgpSecretKeyRing(keys);
|
||||
}
|
||||
|
||||
/// <summary>Return the public key ring that corresponds to the secret key ring.</summary>
|
||||
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
|
||||
{
|
||||
/// <remarks>
|
||||
/// Generator for a PGP master and subkey ring.
|
||||
/// This class will generate both the secret and public key rings
|
||||
/// </remarks>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new key ring generator using old style checksumming. It is recommended to use
|
||||
/// SHA1 checksumming where possible.
|
||||
/// </summary>
|
||||
/// <param name="certificationLevel">The certification level for keys on this ring.</param>
|
||||
/// <param name="masterKey">The master key pair.</param>
|
||||
/// <param name="id">The id to be associated with the ring.</param>
|
||||
/// <param name="encAlgorithm">The algorithm to be used to protect secret keys.</param>
|
||||
/// <param name="passPhrase">The passPhrase to be used to protect secret keys.</param>
|
||||
/// <param name="hashedPackets">Packets to be included in the certification hash.</param>
|
||||
/// <param name="unhashedPackets">Packets to be attached unhashed to the certification.</param>
|
||||
/// <param name="rand">input secured random.</param>
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new key ring generator.
|
||||
/// </summary>
|
||||
/// <param name="certificationLevel">The certification level for keys on this ring.</param>
|
||||
/// <param name="masterKey">The master key pair.</param>
|
||||
/// <param name="id">The id to be associated with the ring.</param>
|
||||
/// <param name="encAlgorithm">The algorithm to be used to protect secret keys.</param>
|
||||
/// <param name="passPhrase">The passPhrase to be used to protect secret keys.</param>
|
||||
/// <param name="useSha1">Checksum the secret keys with SHA1 rather than the older 16 bit checksum.</param>
|
||||
/// <param name="hashedPackets">Packets to be included in the certification hash.</param>
|
||||
/// <param name="unhashedPackets">Packets to be attached unhashed to the certification.</param>
|
||||
/// <param name="rand">input secured random.</param>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>Add a subkey to the key ring to be generated with default certification.</summary>
|
||||
public void AddSubKey(
|
||||
PgpKeyPair keyPair)
|
||||
{
|
||||
AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a subkey with specific hashed and unhashed packets associated with it and
|
||||
/// default certification.
|
||||
/// </summary>
|
||||
/// <param name="keyPair">Public/private key pair.</param>
|
||||
/// <param name="hashedPackets">Hashed packet values to be included in certification.</param>
|
||||
/// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param>
|
||||
/// <exception cref="PgpException"></exception>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Return the secret key ring.</summary>
|
||||
public PgpSecretKeyRing GenerateSecretKeyRing()
|
||||
{
|
||||
return new PgpSecretKeyRing(keys);
|
||||
}
|
||||
|
||||
/// <summary>Return the public key ring that corresponds to the secret key ring.</summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,179 +1,179 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace Org.BouncyCastle.Bcpg.OpenPgp
|
||||
{
|
||||
/// <remarks>A one pass signature object.</remarks>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Initialise the signature object for verification.</summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verify the calculated signature against the passed in PgpSignature.</summary>
|
||||
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
|
||||
{
|
||||
/// <remarks>A one pass signature object.</remarks>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>Initialise the signature object for verification.</summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verify the calculated signature against the passed in PgpSignature.</summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,187 +1,194 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
|
||||
using Org.BouncyCastle.Utilities.Collections;
|
||||
|
||||
namespace Org.BouncyCastle.Bcpg.OpenPgp
|
||||
{
|
||||
/// <remarks>
|
||||
/// Class to hold a single master public key and its subkeys.
|
||||
/// <p>
|
||||
/// Often PGP keyring files consist of multiple master keys, if you are trying to process
|
||||
/// or construct one of these you should use the <c>PgpPublicKeyRingBundle</c> class.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Return the first public key in the ring.</summary>
|
||||
public PgpPublicKey GetPublicKey()
|
||||
{
|
||||
return (PgpPublicKey) keys[0];
|
||||
}
|
||||
|
||||
/// <summary>Return the public key referred to by the passed in key ID if it is present.</summary>
|
||||
public PgpPublicKey GetPublicKey(
|
||||
long keyId)
|
||||
{
|
||||
foreach (PgpPublicKey k in keys)
|
||||
{
|
||||
if (keyId == k.KeyId)
|
||||
{
|
||||
return k;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>Allows enumeration of all the public keys.</summary>
|
||||
/// <returns>An <c>IEnumerable</c> of <c>PgpPublicKey</c> objects.</returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new key ring with the public key passed in either added or
|
||||
/// replacing an existing one.
|
||||
/// </summary>
|
||||
/// <param name="pubRing">The public key ring to be modified.</param>
|
||||
/// <param name="pubKey">The public key to be inserted.</param>
|
||||
/// <returns>A new <c>PgpPublicKeyRing</c></returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>Returns a new key ring with the public key passed in removed from the key ring.</summary>
|
||||
/// <param name="pubRing">The public key ring to be modified.</param>
|
||||
/// <param name="pubKey">The public key to be removed.</param>
|
||||
/// <returns>A new <c>PgpPublicKeyRing</c>, or null if pubKey is not found.</returns>
|
||||
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
|
||||
{
|
||||
/// <remarks>
|
||||
/// Class to hold a single master public key and its subkeys.
|
||||
/// <p>
|
||||
/// Often PGP keyring files consist of multiple master keys, if you are trying to process
|
||||
/// or construct one of these you should use the <c>PgpPublicKeyRingBundle</c> class.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Return the first public key in the ring.</summary>
|
||||
public PgpPublicKey GetPublicKey()
|
||||
{
|
||||
return (PgpPublicKey) keys[0];
|
||||
}
|
||||
|
||||
/// <summary>Return the public key referred to by the passed in key ID if it is present.</summary>
|
||||
public PgpPublicKey GetPublicKey(
|
||||
long keyId)
|
||||
{
|
||||
foreach (PgpPublicKey k in keys)
|
||||
{
|
||||
if (keyId == k.KeyId)
|
||||
{
|
||||
return k;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>Allows enumeration of all the public keys.</summary>
|
||||
/// <returns>An <c>IEnumerable</c> of <c>PgpPublicKey</c> objects.</returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new key ring with the public key passed in either added or
|
||||
/// replacing an existing one.
|
||||
/// </summary>
|
||||
/// <param name="pubRing">The public key ring to be modified.</param>
|
||||
/// <param name="pubKey">The public key to be inserted.</param>
|
||||
/// <returns>A new <c>PgpPublicKeyRing</c></returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>Returns a new key ring with the public key passed in removed from the key ring.</summary>
|
||||
/// <param name="pubRing">The public key ring to be modified.</param>
|
||||
/// <param name="pubKey">The public key to be removed.</param>
|
||||
/// <returns>A new <c>PgpPublicKeyRing</c>, or null if pubKey is not found.</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,208 +1,308 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
|
||||
using Org.BouncyCastle.Utilities.Collections;
|
||||
|
||||
namespace Org.BouncyCastle.Bcpg.OpenPgp
|
||||
{
|
||||
/// <remarks>
|
||||
/// Class to hold a single master secret key and its subkeys.
|
||||
/// <p>
|
||||
/// Often PGP keyring files consist of multiple master keys, if you are trying to process
|
||||
/// or construct one of these you should use the <c>PgpSecretKeyRingBundle</c> class.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Return the public key for the master key.</summary>
|
||||
public PgpPublicKey GetPublicKey()
|
||||
{
|
||||
return ((PgpSecretKey) keys[0]).PublicKey;
|
||||
}
|
||||
|
||||
/// <summary>Return the master private key.</summary>
|
||||
public PgpSecretKey GetSecretKey()
|
||||
{
|
||||
return (PgpSecretKey) keys[0];
|
||||
}
|
||||
|
||||
/// <summary>Allows enumeration of the secret keys.</summary>
|
||||
/// <returns>An <c>IEnumerable</c> of <c>PgpSecretKey</c> objects.</returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new key ring with the secret key passed in either added or
|
||||
/// replacing an existing one with the same key ID.
|
||||
/// </summary>
|
||||
/// <param name="secRing">The secret key ring to be modified.</param>
|
||||
/// <param name="secKey">The secret key to be inserted.</param>
|
||||
/// <returns>A new <c>PgpSecretKeyRing</c></returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>Returns a new key ring with the secret key passed in removed from the key ring.</summary>
|
||||
/// <param name="secRing">The secret key ring to be modified.</param>
|
||||
/// <param name="secKey">The secret key to be removed.</param>
|
||||
/// <returns>A new <c>PgpSecretKeyRing</c>, or null if secKey is not found.</returns>
|
||||
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
|
||||
{
|
||||
/// <remarks>
|
||||
/// Class to hold a single master secret key and its subkeys.
|
||||
/// <p>
|
||||
/// Often PGP keyring files consist of multiple master keys, if you are trying to process
|
||||
/// or construct one of these you should use the <c>PgpSecretKeyRingBundle</c> class.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Return the public key for the master key.</summary>
|
||||
public PgpPublicKey GetPublicKey()
|
||||
{
|
||||
return ((PgpSecretKey) keys[0]).PublicKey;
|
||||
}
|
||||
|
||||
/// <summary>Return the master private key.</summary>
|
||||
public PgpSecretKey GetSecretKey()
|
||||
{
|
||||
return (PgpSecretKey) keys[0];
|
||||
}
|
||||
|
||||
/// <summary>Allows enumeration of the secret keys.</summary>
|
||||
/// <returns>An <c>IEnumerable</c> of <c>PgpSecretKey</c> objects.</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <returns>An <c>IEnumerable</c> of unattached, or extra, public keys.</returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace the public key set on the secret ring with the corresponding key off the public ring.
|
||||
/// </summary>
|
||||
/// <param name="secretRing">Secret ring to be changed.</param>
|
||||
/// <param name="publicRing">Public ring containing the new public key set.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="ring">The <c>PgpSecretKeyRing</c> to be copied.</param>
|
||||
/// <param name="oldPassPhrase">The current password for key.</param>
|
||||
/// <param name="newPassPhrase">The new password for the key.</param>
|
||||
/// <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param>
|
||||
/// <param name="rand">Source of randomness.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new key ring with the secret key passed in either added or
|
||||
/// replacing an existing one with the same key ID.
|
||||
/// </summary>
|
||||
/// <param name="secRing">The secret key ring to be modified.</param>
|
||||
/// <param name="secKey">The secret key to be inserted.</param>
|
||||
/// <returns>A new <c>PgpSecretKeyRing</c></returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>Returns a new key ring with the secret key passed in removed from the key ring.</summary>
|
||||
/// <param name="secRing">The secret key ring to be modified.</param>
|
||||
/// <param name="secKey">The secret key to be removed.</param>
|
||||
/// <returns>A new <c>PgpSecretKeyRing</c>, or null if secKey is not found.</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
/// <remarks>A PGP signature object.</remarks>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>The OpenPGP version number for this signature.</summary>
|
||||
public int Version
|
||||
{
|
||||
get { return sigPck.Version; }
|
||||
}
|
||||
|
||||
/// <summary>The key algorithm associated with this signature.</summary>
|
||||
public PublicKeyAlgorithmTag KeyAlgorithm
|
||||
{
|
||||
get { return sigPck.KeyAlgorithm; }
|
||||
}
|
||||
|
||||
/// <summary>The hash algorithm associated with this signature.</summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify the signature as certifying the passed in public key as associated
|
||||
/// with the passed in user attributes.
|
||||
/// </summary>
|
||||
/// <param name="userAttributes">User attributes the key was stored under.</param>
|
||||
/// <param name="key">The key to be verified.</param>
|
||||
/// <returns>True, if the signature matches, false otherwise.</returns>
|
||||
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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify the signature as certifying the passed in public key as associated
|
||||
/// with the passed in ID.
|
||||
/// </summary>
|
||||
/// <param name="id">ID the key was stored under.</param>
|
||||
/// <param name="key">The key to be verified.</param>
|
||||
/// <returns>True, if the signature matches, false otherwise.</returns>
|
||||
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());
|
||||
}
|
||||
|
||||
/// <summary>Verify a certification for the passed in key against the passed in master key.</summary>
|
||||
/// <param name="masterKey">The key we are verifying against.</param>
|
||||
/// <param name="pubKey">The key we are verifying.</param>
|
||||
/// <returns>True, if the certification is valid, false otherwise.</returns>
|
||||
public bool VerifyCertification(
|
||||
PgpPublicKey masterKey,
|
||||
PgpPublicKey pubKey)
|
||||
{
|
||||
UpdateWithPublicKey(masterKey);
|
||||
UpdateWithPublicKey(pubKey);
|
||||
|
||||
Update(sigPck.GetSignatureTrailer());
|
||||
|
||||
return sig.VerifySignature(GetSignature());
|
||||
}
|
||||
|
||||
/// <summary>Verify a key certification, such as revocation, for the passed in key.</summary>
|
||||
/// <param name="pubKey">The key we are checking.</param>
|
||||
/// <returns>True, if the certification is valid, false otherwise.</returns>
|
||||
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; }
|
||||
}
|
||||
|
||||
/// <summary>The ID of the key that created the signature.</summary>
|
||||
public long KeyId
|
||||
{
|
||||
get { return sigPck.KeyId; }
|
||||
}
|
||||
|
||||
[Obsolete("Use 'CreationTime' property instead")]
|
||||
public DateTime GetCreationTime()
|
||||
{
|
||||
return CreationTime;
|
||||
}
|
||||
|
||||
/// <summary>The creation time of this signature.</summary>
|
||||
public DateTime CreationTime
|
||||
{
|
||||
get { return DateTimeUtilities.UnixMsToDateTime(sigPck.CreationTime); }
|
||||
}
|
||||
|
||||
public byte[] GetSignatureTrailer()
|
||||
{
|
||||
return sigPck.GetSignatureTrailer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return true if the signature has either hashed or unhashed subpackets.
|
||||
/// </summary>
|
||||
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
|
||||
{
|
||||
/// <remarks>A PGP signature object.</remarks>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>The OpenPGP version number for this signature.</summary>
|
||||
public int Version
|
||||
{
|
||||
get { return sigPck.Version; }
|
||||
}
|
||||
|
||||
/// <summary>The key algorithm associated with this signature.</summary>
|
||||
public PublicKeyAlgorithmTag KeyAlgorithm
|
||||
{
|
||||
get { return sigPck.KeyAlgorithm; }
|
||||
}
|
||||
|
||||
/// <summary>The hash algorithm associated with this signature.</summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify the signature as certifying the passed in public key as associated
|
||||
/// with the passed in user attributes.
|
||||
/// </summary>
|
||||
/// <param name="userAttributes">User attributes the key was stored under.</param>
|
||||
/// <param name="key">The key to be verified.</param>
|
||||
/// <returns>True, if the signature matches, false otherwise.</returns>
|
||||
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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify the signature as certifying the passed in public key as associated
|
||||
/// with the passed in ID.
|
||||
/// </summary>
|
||||
/// <param name="id">ID the key was stored under.</param>
|
||||
/// <param name="key">The key to be verified.</param>
|
||||
/// <returns>True, if the signature matches, false otherwise.</returns>
|
||||
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());
|
||||
}
|
||||
|
||||
/// <summary>Verify a certification for the passed in key against the passed in master key.</summary>
|
||||
/// <param name="masterKey">The key we are verifying against.</param>
|
||||
/// <param name="pubKey">The key we are verifying.</param>
|
||||
/// <returns>True, if the certification is valid, false otherwise.</returns>
|
||||
public bool VerifyCertification(
|
||||
PgpPublicKey masterKey,
|
||||
PgpPublicKey pubKey)
|
||||
{
|
||||
UpdateWithPublicKey(masterKey);
|
||||
UpdateWithPublicKey(pubKey);
|
||||
|
||||
Update(sigPck.GetSignatureTrailer());
|
||||
|
||||
return sig.VerifySignature(GetSignature());
|
||||
}
|
||||
|
||||
/// <summary>Verify a key certification, such as revocation, for the passed in key.</summary>
|
||||
/// <param name="pubKey">The key we are checking.</param>
|
||||
/// <returns>True, if the certification is valid, false otherwise.</returns>
|
||||
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; }
|
||||
}
|
||||
|
||||
/// <summary>The ID of the key that created the signature.</summary>
|
||||
public long KeyId
|
||||
{
|
||||
get { return sigPck.KeyId; }
|
||||
}
|
||||
|
||||
[Obsolete("Use 'CreationTime' property instead")]
|
||||
public DateTime GetCreationTime()
|
||||
{
|
||||
return CreationTime;
|
||||
}
|
||||
|
||||
/// <summary>The creation time of this signature.</summary>
|
||||
public DateTime CreationTime
|
||||
{
|
||||
get { return DateTimeUtilities.UnixMsToDateTime(sigPck.CreationTime); }
|
||||
}
|
||||
|
||||
public byte[] GetSignatureTrailer()
|
||||
{
|
||||
return sigPck.GetSignatureTrailer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return true if the signature has either hashed or unhashed subpackets.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,141 +1,163 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using Org.BouncyCastle.Bcpg.Sig;
|
||||
|
||||
namespace Org.BouncyCastle.Bcpg.OpenPgp
|
||||
{
|
||||
/// <remarks>Generator for signature subpackets.</remarks>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="isCritical">true if the packet is critical.</param>
|
||||
/// <param name="depth">depth level.</param>
|
||||
/// <param name="trustAmount">trust amount.</param>
|
||||
public void SetTrust(
|
||||
bool isCritical,
|
||||
int depth,
|
||||
int trustAmount)
|
||||
{
|
||||
list.Add(new TrustSignature(isCritical, depth, trustAmount));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="isCritical">True, if should be treated as critical, false otherwise.</param>
|
||||
/// <param name="seconds">The number of seconds the key is valid, or zero if no expiry.</param>
|
||||
public void SetKeyExpirationTime(
|
||||
bool isCritical,
|
||||
long seconds)
|
||||
{
|
||||
list.Add(new KeyExpirationTime(isCritical, seconds));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="isCritical">True, if should be treated as critical, false otherwise.</param>
|
||||
/// <param name="seconds">The number of seconds the signature is valid, or zero if no expiry.</param>
|
||||
public void SetSignatureExpirationTime(
|
||||
bool isCritical,
|
||||
long seconds)
|
||||
{
|
||||
list.Add(new SignatureExpirationTime(isCritical, seconds));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the creation time for the signature.
|
||||
/// <p>
|
||||
/// Note: this overrides the generation of a creation time when the signature
|
||||
/// is generated.</p>
|
||||
/// </summary>
|
||||
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
|
||||
{
|
||||
/// <remarks>Generator for signature subpackets.</remarks>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="isCritical">true if the packet is critical.</param>
|
||||
/// <param name="depth">depth level.</param>
|
||||
/// <param name="trustAmount">trust amount.</param>
|
||||
public void SetTrust(
|
||||
bool isCritical,
|
||||
int depth,
|
||||
int trustAmount)
|
||||
{
|
||||
list.Add(new TrustSignature(isCritical, depth, trustAmount));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="isCritical">True, if should be treated as critical, false otherwise.</param>
|
||||
/// <param name="seconds">The number of seconds the key is valid, or zero if no expiry.</param>
|
||||
public void SetKeyExpirationTime(
|
||||
bool isCritical,
|
||||
long seconds)
|
||||
{
|
||||
list.Add(new KeyExpirationTime(isCritical, seconds));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="isCritical">True, if should be treated as critical, false otherwise.</param>
|
||||
/// <param name="seconds">The number of seconds the signature is valid, or zero if no expiry.</param>
|
||||
public void SetSignatureExpirationTime(
|
||||
bool isCritical,
|
||||
long seconds)
|
||||
{
|
||||
list.Add(new SignatureExpirationTime(isCritical, seconds));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the creation time for the signature.
|
||||
/// <p>
|
||||
/// Note: this overrides the generation of a creation time when the signature
|
||||
/// is generated.</p>
|
||||
/// </summary>
|
||||
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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
/// <remarks>
|
||||
/// Utility class for creating IBasicAgreement objects from their names/Oids
|
||||
/// </remarks>
|
||||
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
|
||||
{
|
||||
/// <remarks>
|
||||
/// Utility class for creating IBasicAgreement objects from their names/Oids
|
||||
/// </remarks>
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An <code>ISet</code> of <code>DerObjectIdentifier</code> objects.
|
||||
/// </summary>
|
||||
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); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An <code>ISet</code> of <code>DerObjectIdentifier</code> objects.
|
||||
/// </summary>
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An <code>ICollection</code> of <code>X509Name</code> objects
|
||||
/// </summary>
|
||||
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 <code>null</code> is specified, then no such
|
||||
* optional information is provided.
|
||||
*
|
||||
* @param attrCert the <code>IX509AttributeCertificate</code> being checked (or
|
||||
* <code>null</code>)
|
||||
* @see #getAttrCertificateChecking()
|
||||
*/
|
||||
public IX509AttributeCertificate AttrCertChecking
|
||||
{
|
||||
get { return attrCertChecking; }
|
||||
set { this.attrCertChecking = value; }
|
||||
}
|
||||
|
||||
/**
|
||||
* If <code>true</code> only complete CRLs are returned. Defaults to
|
||||
* <code>false</code>.
|
||||
*
|
||||
* @return <code>true</code> 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 <code>false</code>.
|
||||
*
|
||||
* @return Returns <code>true</code> 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.
|
||||
* <p>
|
||||
* 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.</p>
|
||||
* <p>
|
||||
* The byte array is cloned to protect against subsequent modifications.</p>
|
||||
* <p>
|
||||
* You must also enable or disable this criteria with
|
||||
* {@link #setIssuingDistributionPointEnabled(bool)}.</p>
|
||||
*
|
||||
* @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 <code>false</code>.
|
||||
* <p>
|
||||
* You may also set the issuing distribution point criteria if not a missing
|
||||
* issuing distribution point should be assumed.</p>
|
||||
*
|
||||
* @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 <code>null</code>.
|
||||
*
|
||||
* @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; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An <code>ICollection</code> of <code>X509Name</code> objects
|
||||
/// </summary>
|
||||
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 <code>null</code> is specified, then no such
|
||||
* optional information is provided.
|
||||
*
|
||||
* @param attrCert the <code>IX509AttributeCertificate</code> being checked (or
|
||||
* <code>null</code>)
|
||||
* @see #getAttrCertificateChecking()
|
||||
*/
|
||||
public IX509AttributeCertificate AttrCertChecking
|
||||
{
|
||||
get { return attrCertChecking; }
|
||||
set { this.attrCertChecking = value; }
|
||||
}
|
||||
|
||||
/**
|
||||
* If <code>true</code> only complete CRLs are returned. Defaults to
|
||||
* <code>false</code>.
|
||||
*
|
||||
* @return <code>true</code> 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 <code>false</code>.
|
||||
*
|
||||
* @return Returns <code>true</code> 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.
|
||||
* <p>
|
||||
* 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.</p>
|
||||
* <p>
|
||||
* The byte array is cloned to protect against subsequent modifications.</p>
|
||||
* <p>
|
||||
* You must also enable or disable this criteria with
|
||||
* {@link #setIssuingDistributionPointEnabled(bool)}.</p>
|
||||
*
|
||||
* @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 <code>false</code>.
|
||||
* <p>
|
||||
* You may also set the issuing distribution point criteria if not a missing
|
||||
* issuing distribution point should be assumed.</p>
|
||||
*
|
||||
* @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 <code>null</code>.
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue