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"
|
||||
|
|
|
@ -63,7 +63,8 @@ namespace Org.BouncyCastle.Asn1
|
|||
int tagNo,
|
||||
Asn1Encodable obj)
|
||||
{
|
||||
this.explicitly = explicitly;
|
||||
// IAsn1Choice marker interface 'insists' on explicit tagging
|
||||
this.explicitly = explicitly || (obj is IAsn1Choice);
|
||||
this.tagNo = tagNo;
|
||||
this.obj = obj;
|
||||
}
|
||||
|
|
|
@ -21,24 +21,29 @@ namespace Org.BouncyCastle.Asn1
|
|||
throw new ArgumentException("negative lengths not allowed", "length");
|
||||
|
||||
this._length = length;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
SetParentEofDetect(true);
|
||||
}
|
||||
}
|
||||
|
||||
public override int ReadByte()
|
||||
{
|
||||
if (_length > 0)
|
||||
{
|
||||
if (_length == 0)
|
||||
return -1;
|
||||
|
||||
int b = _in.ReadByte();
|
||||
|
||||
if (b < 0)
|
||||
throw new EndOfStreamException();
|
||||
|
||||
--_length;
|
||||
return b;
|
||||
if (--_length == 0)
|
||||
{
|
||||
SetParentEofDetect(true);
|
||||
}
|
||||
|
||||
SetParentEofDetect(true);
|
||||
|
||||
return -1;
|
||||
return b;
|
||||
}
|
||||
|
||||
public override int Read(
|
||||
|
@ -46,40 +51,33 @@ namespace Org.BouncyCastle.Asn1
|
|||
int off,
|
||||
int len)
|
||||
{
|
||||
if (_length > 0)
|
||||
{
|
||||
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();
|
||||
|
||||
_length -= numRead;
|
||||
return numRead;
|
||||
if ((_length -= numRead) == 0)
|
||||
{
|
||||
SetParentEofDetect(true);
|
||||
}
|
||||
|
||||
SetParentEofDetect(true);
|
||||
|
||||
return 0;
|
||||
return numRead;
|
||||
}
|
||||
|
||||
internal byte[] ToArray()
|
||||
{
|
||||
byte[] bytes;
|
||||
if (_length > 0)
|
||||
{
|
||||
bytes = new byte[_length];
|
||||
if (_length == 0)
|
||||
return EmptyBytes;
|
||||
|
||||
byte[] bytes = new byte[_length];
|
||||
if (Streams.ReadFully(_in, bytes) < _length)
|
||||
throw new EndOfStreamException();
|
||||
_length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes = EmptyBytes;
|
||||
}
|
||||
|
||||
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,3 +1,4 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1
|
||||
|
@ -16,18 +17,26 @@ namespace Org.BouncyCastle.Asn1
|
|||
{
|
||||
_b1 = inStream.ReadByte();
|
||||
_b2 = inStream.ReadByte();
|
||||
_eofReached = (_b2 < 0);
|
||||
|
||||
if (_b2 < 0)
|
||||
{
|
||||
// Corrupted stream
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
CheckForEof();
|
||||
}
|
||||
|
||||
internal void SetEofOn00(
|
||||
bool eofOn00)
|
||||
{
|
||||
_eofOn00 = eofOn00;
|
||||
CheckForEof();
|
||||
}
|
||||
|
||||
internal bool CheckForEof()
|
||||
private bool CheckForEof()
|
||||
{
|
||||
if (_eofOn00 && (_b1 == 0x00 && _b2 == 0x00))
|
||||
if (!_eofReached && _eofOn00 && (_b1 == 0x00 && _b2 == 0x00))
|
||||
{
|
||||
_eofReached = true;
|
||||
SetParentEofDetect(true);
|
||||
|
|
|
@ -16,8 +16,7 @@ namespace Org.BouncyCastle.Asn1.Esf
|
|||
/// </code>
|
||||
/// </remarks>
|
||||
public class OtherHash
|
||||
: Asn1Encodable
|
||||
//, Asn1Choice
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
private readonly Asn1OctetString sha1Hash;
|
||||
private readonly OtherHashAlgAndValue otherHash;
|
||||
|
|
|
@ -13,8 +13,7 @@ namespace Org.BouncyCastle.Asn1.Esf
|
|||
/// </code>
|
||||
/// </remarks>
|
||||
public class SignaturePolicyIdentifier
|
||||
: Asn1Encodable
|
||||
//, Asn1Choice
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
private readonly SignaturePolicyId sigPolicy;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ namespace Org.BouncyCastle.Asn1.Ess
|
|||
private readonly IssuerSerial issuerSerial;
|
||||
|
||||
private static readonly AlgorithmIdentifier DefaultAlgID = new AlgorithmIdentifier(
|
||||
NistObjectIdentifiers.IdSha256, DerNull.Instance);
|
||||
NistObjectIdentifiers.IdSha256);
|
||||
|
||||
public static EssCertIDv2 GetInstance(
|
||||
object o)
|
||||
|
@ -102,7 +102,7 @@ namespace Org.BouncyCastle.Asn1.Ess
|
|||
* <pre>
|
||||
* EssCertIDv2 ::= SEQUENCE {
|
||||
* hashAlgorithm AlgorithmIdentifier
|
||||
* DEFAULT {algorithm id-sha256 parameters NULL},
|
||||
* DEFAULT {algorithm id-sha256},
|
||||
* certHash Hash,
|
||||
* issuerSerial IssuerSerial OPTIONAL
|
||||
* }
|
||||
|
|
|
@ -38,8 +38,7 @@ namespace Org.BouncyCastle.Asn1.IsisMtt.Ocsp
|
|||
* </pre>
|
||||
*/
|
||||
public class RequestedCertificate
|
||||
: Asn1Encodable
|
||||
//, ASN1Choice
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
public enum Choice
|
||||
{
|
||||
|
|
|
@ -22,8 +22,7 @@ namespace Org.BouncyCastle.Asn1.IsisMtt.X509
|
|||
* of a specific country.
|
||||
*/
|
||||
public class DeclarationOfMajority
|
||||
: Asn1Encodable
|
||||
//, ASN1Choice
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
public enum Choice
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@ using Org.BouncyCastle.Asn1;
|
|||
namespace Org.BouncyCastle.Asn1.Ocsp
|
||||
{
|
||||
public class CertStatus
|
||||
: Asn1Encodable
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
private readonly int tagNo;
|
||||
private readonly Asn1Encodable value;
|
||||
|
|
|
@ -6,7 +6,7 @@ using Org.BouncyCastle.Asn1.X509;
|
|||
namespace Org.BouncyCastle.Asn1.Ocsp
|
||||
{
|
||||
public class ResponderID
|
||||
: Asn1Encodable
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
private readonly Asn1Encodable id;
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ namespace Org.BouncyCastle.Asn1.Ocsp
|
|||
private readonly Asn1Sequence requestList;
|
||||
private readonly X509Extensions requestExtensions;
|
||||
|
||||
private bool versionSet;
|
||||
|
||||
public static TbsRequest GetInstance(
|
||||
Asn1TaggedObject obj,
|
||||
bool explicitly)
|
||||
|
@ -61,6 +63,7 @@ namespace Org.BouncyCastle.Asn1.Ocsp
|
|||
|
||||
if (o.TagNo == 0)
|
||||
{
|
||||
versionSet = true;
|
||||
version = DerInteger.GetInstance(o, true);
|
||||
index++;
|
||||
}
|
||||
|
@ -122,9 +125,10 @@ namespace Org.BouncyCastle.Asn1.Ocsp
|
|||
Asn1EncodableVector v = new Asn1EncodableVector();
|
||||
|
||||
//
|
||||
// if default don't include.
|
||||
// if default don't include - unless explicitly provided. Not strictly correct
|
||||
// but required for some requests
|
||||
//
|
||||
if (!version.Equals(V1))
|
||||
if (!version.Equals(V1) || versionSet)
|
||||
{
|
||||
v.Add(new DerTaggedObject(true, 0, version));
|
||||
}
|
||||
|
|
|
@ -6,7 +6,12 @@ namespace Org.BouncyCastle.Asn1.Oiw
|
|||
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 } //
|
||||
|
|
|
@ -9,25 +9,38 @@ namespace Org.BouncyCastle.Asn1.Pkcs
|
|||
private readonly KeyDerivationFunc func;
|
||||
private readonly EncryptionScheme scheme;
|
||||
|
||||
public PbeS2Parameters(
|
||||
Asn1Sequence obj)
|
||||
public static PbeS2Parameters GetInstance(
|
||||
object obj)
|
||||
{
|
||||
IEnumerator e = obj.GetEnumerator();
|
||||
if (obj == null || obj is PbeS2Parameters)
|
||||
return (PbeS2Parameters) obj;
|
||||
|
||||
e.MoveNext();
|
||||
Asn1Sequence funcSeq = (Asn1Sequence) e.Current;
|
||||
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, funcSeq[1]);
|
||||
func = new KeyDerivationFunc(PkcsObjectIdentifiers.IdPbkdf2,
|
||||
Pbkdf2Params.GetInstance(funcSeq[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
func = new KeyDerivationFunc(funcSeq);
|
||||
}
|
||||
|
||||
e.MoveNext();
|
||||
scheme = new EncryptionScheme((Asn1Sequence) e.Current);
|
||||
scheme = new EncryptionScheme((Asn1Sequence) seq[1]);
|
||||
}
|
||||
|
||||
public KeyDerivationFunc KeyDerivationFunc
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Math;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.Pkcs
|
||||
|
@ -9,22 +7,18 @@ namespace Org.BouncyCastle.Asn1.Pkcs
|
|||
public class Pbkdf2Params
|
||||
: Asn1Encodable
|
||||
{
|
||||
internal Asn1OctetString octStr;
|
||||
internal DerInteger iterationCount;
|
||||
internal DerInteger keyLength;
|
||||
private readonly Asn1OctetString octStr;
|
||||
private readonly DerInteger iterationCount;
|
||||
private readonly DerInteger keyLength;
|
||||
|
||||
public static Pbkdf2Params GetInstance(
|
||||
object obj)
|
||||
{
|
||||
if (obj is Pbkdf2Params || obj == null)
|
||||
{
|
||||
return (Pbkdf2Params) obj;
|
||||
}
|
||||
if (obj == null || obj is Pbkdf2Params)
|
||||
return (Pbkdf2Params)obj;
|
||||
|
||||
if (obj is Asn1Sequence)
|
||||
{
|
||||
return new Pbkdf2Params((Asn1Sequence) obj);
|
||||
}
|
||||
return new Pbkdf2Params((Asn1Sequence)obj);
|
||||
|
||||
throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
|
||||
}
|
||||
|
@ -32,17 +26,15 @@ namespace Org.BouncyCastle.Asn1.Pkcs
|
|||
public Pbkdf2Params(
|
||||
Asn1Sequence seq)
|
||||
{
|
||||
IEnumerator e = seq.GetEnumerator();
|
||||
if (seq.Count < 2 || seq.Count > 3)
|
||||
throw new ArgumentException("Wrong number of elements in sequence", "seq");
|
||||
|
||||
e.MoveNext();
|
||||
octStr = (Asn1OctetString) e.Current;
|
||||
octStr = (Asn1OctetString)seq[0];
|
||||
iterationCount = (DerInteger)seq[1];
|
||||
|
||||
e.MoveNext();
|
||||
iterationCount = (DerInteger) e.Current;
|
||||
|
||||
if (e.MoveNext())
|
||||
if (seq.Count > 2)
|
||||
{
|
||||
keyLength = (DerInteger) e.Current;
|
||||
keyLength = (DerInteger)seq[2];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,7 @@ using System;
|
|||
namespace Org.BouncyCastle.Asn1.X500
|
||||
{
|
||||
public class DirectoryString
|
||||
: Asn1Encodable, IAsn1String
|
||||
//, Asn1Choice
|
||||
: Asn1Encodable, IAsn1Choice, IAsn1String
|
||||
{
|
||||
private readonly DerStringBase str;
|
||||
|
||||
|
|
|
@ -14,24 +14,19 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
: 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;
|
||||
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");
|
||||
}
|
||||
|
@ -40,7 +35,7 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
Asn1Sequence seq)
|
||||
{
|
||||
if (seq.Count != 2)
|
||||
throw new ArgumentException("wrong number of elements in inner sequence");
|
||||
throw new ArgumentException("wrong number of elements in sequence");
|
||||
|
||||
accessMethod = DerObjectIdentifier.GetInstance(seq[0]);
|
||||
accessLocation = GeneralName.GetInstance(seq[1]);
|
||||
|
@ -82,7 +77,7 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
|
||||
public override string ToString()
|
||||
{
|
||||
return ("AccessDescription: Oid(" + this.accessMethod.Id + ")");
|
||||
return "AccessDescription: Oid(" + this.accessMethod.Id + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ using Org.BouncyCastle.Asn1;
|
|||
namespace Org.BouncyCastle.Asn1.X509
|
||||
{
|
||||
public class AttCertIssuer
|
||||
: Asn1Encodable
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
internal readonly Asn1Encodable obj;
|
||||
internal readonly Asn1Object choiceObj;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1.X509
|
||||
{
|
||||
|
@ -24,26 +26,19 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
public class AuthorityInformationAccess
|
||||
: Asn1Encodable
|
||||
{
|
||||
internal readonly DerObjectIdentifier accessMethod;
|
||||
internal readonly GeneralName accessLocation;
|
||||
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");
|
||||
}
|
||||
|
@ -51,37 +46,60 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
private AuthorityInformationAccess(
|
||||
Asn1Sequence seq)
|
||||
{
|
||||
foreach (DerSequence vec in seq)
|
||||
{
|
||||
if (vec.Count != 2)
|
||||
{
|
||||
throw new ArgumentException("wrong number of elements in inner sequence");
|
||||
}
|
||||
if (seq.Count < 1)
|
||||
throw new ArgumentException("sequence may not be empty");
|
||||
|
||||
accessMethod = (DerObjectIdentifier) vec[0];
|
||||
accessLocation = (GeneralName) vec[1];
|
||||
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)
|
||||
{
|
||||
accessMethod = oid;
|
||||
accessLocation = 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(new DerSequence(accessMethod, accessLocation));
|
||||
return new DerSequence(descriptions);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ("AuthorityInformationAccess: Oid(" + this.accessMethod.Id + ")");
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
* @see PolicyInformation
|
||||
*/
|
||||
public class DisplayText
|
||||
: Asn1Encodable
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
/**
|
||||
* Constant corresponding to ia5String encoding.
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
* </pre>
|
||||
*/
|
||||
public class DistributionPointName
|
||||
: Asn1Encodable
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
internal readonly Asn1Encodable name;
|
||||
internal readonly int type;
|
||||
|
@ -27,7 +27,7 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
Asn1TaggedObject obj,
|
||||
bool explicitly)
|
||||
{
|
||||
return GetInstance(Asn1TaggedObject.GetInstance(obj, explicitly));
|
||||
return GetInstance(Asn1TaggedObject.GetInstance(obj, true));
|
||||
}
|
||||
|
||||
public static DistributionPointName GetInstance(
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
* </pre>
|
||||
*/
|
||||
public class GeneralName
|
||||
: Asn1Encodable
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
public const int OtherName = 0;
|
||||
public const int Rfc822Name = 1;
|
||||
|
@ -197,7 +197,7 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
Asn1TaggedObject tagObj,
|
||||
bool explicitly)
|
||||
{
|
||||
return GetInstance(Asn1TaggedObject.GetInstance(tagObj, explicitly));
|
||||
return GetInstance(Asn1TaggedObject.GetInstance(tagObj, true));
|
||||
}
|
||||
|
||||
public int TagNo
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
public class GeneralNames
|
||||
: Asn1Encodable
|
||||
{
|
||||
private readonly Asn1Sequence seq;
|
||||
private readonly GeneralName[] names;
|
||||
|
||||
public static GeneralNames GetInstance(
|
||||
object obj)
|
||||
|
@ -38,25 +38,23 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
public GeneralNames(
|
||||
GeneralName name)
|
||||
{
|
||||
this.seq = new DerSequence(name);
|
||||
names = new GeneralName[]{ name };
|
||||
}
|
||||
|
||||
private GeneralNames(
|
||||
Asn1Sequence seq)
|
||||
{
|
||||
this.seq = seq;
|
||||
}
|
||||
|
||||
public GeneralName[] GetNames()
|
||||
{
|
||||
GeneralName[] names = new GeneralName[seq.Count];
|
||||
this.names = new GeneralName[seq.Count];
|
||||
|
||||
for (int i = 0; i != seq.Count; i++)
|
||||
{
|
||||
names[i] = GeneralName.GetInstance(seq[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
public GeneralName[] GetNames()
|
||||
{
|
||||
return (GeneralName[]) names.Clone();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,24 +65,24 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
*/
|
||||
public override Asn1Object ToAsn1Object()
|
||||
{
|
||||
return seq;
|
||||
return new DerSequence(names);
|
||||
}
|
||||
|
||||
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++)
|
||||
foreach (GeneralName name in names)
|
||||
{
|
||||
buf.Append(" ");
|
||||
buf.Append(names[i]);
|
||||
buf.Append(name);
|
||||
buf.Append(sep);
|
||||
}
|
||||
|
||||
return buf.ToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
roleAuthority = GeneralNames.GetInstance(taggedObject, false);
|
||||
break;
|
||||
case 1:
|
||||
roleName = GeneralName.GetInstance(taggedObject, false);
|
||||
roleName = GeneralName.GetInstance(taggedObject, true);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Unknown tag in RoleSyntax");
|
||||
|
@ -203,7 +203,7 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
v.Add(new DerTaggedObject(false, 0, roleAuthority));
|
||||
}
|
||||
|
||||
v.Add(new DerTaggedObject(false, 1, roleName));
|
||||
v.Add(new DerTaggedObject(true, 1, roleName));
|
||||
|
||||
return new DerSequence(v);
|
||||
}
|
||||
|
|
|
@ -19,8 +19,7 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
* according to RFC 3281.</p>
|
||||
*/
|
||||
public class Target
|
||||
: Asn1Encodable
|
||||
//, ASN1Choice
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
public enum Choice
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@ using System;
|
|||
namespace Org.BouncyCastle.Asn1.X509
|
||||
{
|
||||
public class Time
|
||||
: Asn1Encodable
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
internal Asn1Object time;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using Org.BouncyCastle.Asn1.Pkcs;
|
||||
|
@ -878,19 +879,19 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
return true;
|
||||
}
|
||||
|
||||
private bool equivalentStrings(
|
||||
private static bool equivalentStrings(
|
||||
string s1,
|
||||
string s2)
|
||||
{
|
||||
string value = s1.ToLower(CultureInfo.InvariantCulture).Trim();
|
||||
string oValue = s2.ToLower(CultureInfo.InvariantCulture).Trim();
|
||||
string v1 = canonicalize(s1);
|
||||
string v2 = canonicalize(s2);
|
||||
|
||||
if (!value.Equals(oValue))
|
||||
if (!v1.Equals(v2))
|
||||
{
|
||||
value = stripInternalSpaces(value);
|
||||
oValue = stripInternalSpaces(oValue);
|
||||
v1 = stripInternalSpaces(v1);
|
||||
v2 = stripInternalSpaces(v2);
|
||||
|
||||
if (!value.Equals(oValue))
|
||||
if (!v1.Equals(v2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -899,7 +900,38 @@ namespace Org.BouncyCastle.Asn1.X509
|
|||
return true;
|
||||
}
|
||||
|
||||
private string stripInternalSpaces(
|
||||
private static string canonicalize(
|
||||
string s)
|
||||
{
|
||||
string v = s.ToLower(CultureInfo.InvariantCulture).Trim();
|
||||
|
||||
if (v.StartsWith("#"))
|
||||
{
|
||||
Asn1Object obj = decodeObject(v);
|
||||
|
||||
if (obj is IAsn1String)
|
||||
{
|
||||
v = ((IAsn1String)obj).GetString().ToLower(CultureInfo.InvariantCulture).Trim();
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
private static Asn1Object decodeObject(
|
||||
string v)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Asn1Object.FromByteArray(Hex.Decode(v.Substring(1)));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new InvalidOperationException("unknown encoding in name: " + e.Message, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static string stripInternalSpaces(
|
||||
string str)
|
||||
{
|
||||
StringBuilder res = new StringBuilder();
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Org.BouncyCastle.Asn1.X509.Qualified
|
|||
* </pre>
|
||||
*/
|
||||
public class Iso4217CurrencyCode
|
||||
: Asn1Encodable
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
internal const int AlphabeticMaxSize = 3;
|
||||
internal const int NumericMinSize = 1;
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Org.BouncyCastle.Asn1.X509.Qualified
|
|||
* </pre>
|
||||
*/
|
||||
public class TypeOfBiometricData
|
||||
: Asn1Encodable
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
public const int Picture = 0;
|
||||
public const int HandwrittenSignature = 1;
|
||||
|
|
|
@ -22,8 +22,7 @@ namespace Org.BouncyCastle.Asn1.X509.SigI
|
|||
*
|
||||
*/
|
||||
public class NameOrPseudonym
|
||||
: Asn1Encodable
|
||||
//, Asn1Choice
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
private readonly DirectoryString pseudonym;
|
||||
private readonly DirectoryString surname;
|
||||
|
|
|
@ -3,7 +3,7 @@ using Org.BouncyCastle.Asn1;
|
|||
namespace Org.BouncyCastle.Asn1.X9
|
||||
{
|
||||
public class X962Parameters
|
||||
: Asn1Encodable
|
||||
: Asn1Encodable, IAsn1Choice
|
||||
{
|
||||
private readonly Asn1Object _params;
|
||||
|
||||
|
|
|
@ -59,10 +59,6 @@ namespace Org.BouncyCastle.Asn1.X9
|
|||
{
|
||||
this.h = ((DerInteger) seq[5]).Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.h = BigInteger.One;
|
||||
}
|
||||
}
|
||||
|
||||
public X9ECParameters(
|
||||
|
@ -124,7 +120,16 @@ namespace Org.BouncyCastle.Asn1.X9
|
|||
|
||||
public BigInteger H
|
||||
{
|
||||
get { return 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()
|
||||
|
@ -154,7 +159,7 @@ namespace Org.BouncyCastle.Asn1.X9
|
|||
new X9ECPoint(g),
|
||||
new DerInteger(n));
|
||||
|
||||
if (!h.Equals(BigInteger.One))
|
||||
if (h != null)
|
||||
{
|
||||
v.Add(new DerInteger(h));
|
||||
}
|
||||
|
|
|
@ -98,6 +98,7 @@ namespace Org.BouncyCastle.Bcpg
|
|||
bool restart = false;
|
||||
ArrayList headerList= new ArrayList();
|
||||
int lastC = 0;
|
||||
bool isEndOfStream;
|
||||
|
||||
/**
|
||||
* Create a stream for reading a PGP armoured message, parsing up to a header
|
||||
|
@ -241,6 +242,14 @@ namespace Org.BouncyCastle.Bcpg
|
|||
return clearText;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the stream is actually at end of file.
|
||||
*/
|
||||
public bool IsEndOfStream()
|
||||
{
|
||||
return isEndOfStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the armor header line (if there is one)
|
||||
* @return the armor header line, null if none present.
|
||||
|
@ -327,6 +336,11 @@ namespace Org.BouncyCastle.Bcpg
|
|||
|
||||
lastC = c;
|
||||
|
||||
if (c < 0)
|
||||
{
|
||||
isEndOfStream = true;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -404,12 +418,18 @@ namespace Org.BouncyCastle.Bcpg
|
|||
start = true;
|
||||
bufPtr = 3;
|
||||
|
||||
if (c < 0)
|
||||
{
|
||||
isEndOfStream = true;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (c < 0)
|
||||
{
|
||||
isEndOfStream = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
@ -88,15 +89,16 @@ namespace Org.BouncyCastle.Bcpg
|
|||
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 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;
|
||||
|
||||
|
|
|
@ -25,6 +25,9 @@ namespace Org.BouncyCastle.Bcpg
|
|||
PolicyUrl = 26, // policy URL
|
||||
KeyFlags = 27, // key flags
|
||||
SignerUserId = 28, // signer's user id
|
||||
RevocationReason = 29 // reason for revocation
|
||||
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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -97,5 +97,16 @@ namespace Org.BouncyCastle.Bcpg.Sig
|
|||
|
||||
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,11 +1,9 @@
|
|||
using System;
|
||||
|
||||
|
||||
|
||||
namespace Org.BouncyCastle.Bcpg.Sig
|
||||
{
|
||||
/**
|
||||
* packet giving signature creation time.
|
||||
* packet giving trust.
|
||||
*/
|
||||
public class TrustSignature
|
||||
: SignatureSubpacket
|
||||
|
@ -14,12 +12,7 @@ namespace Org.BouncyCastle.Bcpg.Sig
|
|||
int v1,
|
||||
int v2)
|
||||
{
|
||||
byte[] data = new byte[2];
|
||||
|
||||
data[0] = (byte)v1;
|
||||
data[1] = (byte)v2;
|
||||
|
||||
return data;
|
||||
return new byte[]{ (byte)v1, (byte)v2 };
|
||||
}
|
||||
|
||||
public TrustSignature(
|
||||
|
@ -39,18 +32,12 @@ namespace Org.BouncyCastle.Bcpg.Sig
|
|||
|
||||
public int Depth
|
||||
{
|
||||
get
|
||||
{
|
||||
return data[0] & 0xff;
|
||||
}
|
||||
get { return data[0] & 0xff; }
|
||||
}
|
||||
|
||||
public int TrustAmount
|
||||
{
|
||||
get
|
||||
{
|
||||
return data[1] & 0xff;
|
||||
}
|
||||
get { return data[1] & 0xff; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
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;
|
||||
|
@ -27,6 +29,22 @@ namespace Org.BouncyCastle.Cms
|
|||
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; }
|
||||
|
|
|
@ -108,14 +108,15 @@ namespace Org.BouncyCastle.Cms
|
|||
|
||||
private class SignerInf
|
||||
{
|
||||
CmsSignedGenerator outer;
|
||||
AsymmetricKeyParameter key;
|
||||
X509Certificate cert;
|
||||
string digestOID;
|
||||
string encOID;
|
||||
CmsAttributeTableGenerator sAttr;
|
||||
CmsAttributeTableGenerator unsAttr;
|
||||
Asn1.Cms.AttributeTable baseSignedTable;
|
||||
private CmsSignedGenerator outer;
|
||||
private AsymmetricKeyParameter key;
|
||||
private X509Certificate cert;
|
||||
private string digestOID;
|
||||
private string encOID;
|
||||
private CmsAttributeTableGenerator sAttr;
|
||||
private CmsAttributeTableGenerator unsAttr;
|
||||
private Asn1.Cms.AttributeTable baseSignedTable;
|
||||
private byte[] keyIdentifier;
|
||||
|
||||
internal SignerInf(
|
||||
CmsSignedGenerator outer,
|
||||
|
@ -123,12 +124,18 @@ namespace Org.BouncyCastle.Cms
|
|||
X509Certificate cert,
|
||||
string digestOID,
|
||||
string encOID)
|
||||
: this(outer, key, cert, digestOID, encOID, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
internal SignerInf(
|
||||
CmsSignedGenerator outer,
|
||||
AsymmetricKeyParameter key,
|
||||
byte[] keyIdentifier,
|
||||
string digestOID,
|
||||
string encOID)
|
||||
: this(outer, key, keyIdentifier, digestOID, encOID, null, null, null)
|
||||
{
|
||||
this.outer = outer;
|
||||
this.key = key;
|
||||
this.cert = cert;
|
||||
this.digestOID = digestOID;
|
||||
this.encOID = encOID;
|
||||
}
|
||||
|
||||
internal SignerInf(
|
||||
|
@ -151,6 +158,26 @@ namespace Org.BouncyCastle.Cms
|
|||
this.baseSignedTable = baseSignedTable;
|
||||
}
|
||||
|
||||
internal SignerInf(
|
||||
CmsSignedGenerator outer,
|
||||
AsymmetricKeyParameter key,
|
||||
byte[] keyIdentifier,
|
||||
string digestOID,
|
||||
string encOID,
|
||||
CmsAttributeTableGenerator sAttr,
|
||||
CmsAttributeTableGenerator unsAttr,
|
||||
Asn1.Cms.AttributeTable baseSignedTable)
|
||||
{
|
||||
this.outer = outer;
|
||||
this.key = key;
|
||||
this.keyIdentifier = keyIdentifier;
|
||||
this.digestOID = digestOID;
|
||||
this.encOID = encOID;
|
||||
this.sAttr = sAttr;
|
||||
this.unsAttr = unsAttr;
|
||||
this.baseSignedTable = baseSignedTable;
|
||||
}
|
||||
|
||||
internal AsymmetricKeyParameter GetKey()
|
||||
{
|
||||
return key;
|
||||
|
@ -270,12 +297,21 @@ namespace Org.BouncyCastle.Cms
|
|||
Asn1Set unsignedAttr = outer.GetAttributeSet(unsigned);
|
||||
|
||||
X509Certificate cert = this.GetCertificate();
|
||||
SignerIdentifier identifier;
|
||||
if (cert != null)
|
||||
{
|
||||
TbsCertificateStructure tbs = TbsCertificateStructure.GetInstance(
|
||||
Asn1Object.FromByteArray(cert.GetTbsCertificate()));
|
||||
Asn1.Cms.IssuerAndSerialNumber encSid = new Asn1.Cms.IssuerAndSerialNumber(
|
||||
tbs.Issuer, tbs.SerialNumber.Value);
|
||||
identifier = new SignerIdentifier(encSid);
|
||||
}
|
||||
else
|
||||
{
|
||||
identifier = new SignerIdentifier(new DerOctetString(keyIdentifier));
|
||||
}
|
||||
|
||||
return new Asn1.Cms.SignerInfo(new SignerIdentifier(encSid), digAlgId,
|
||||
return new Asn1.Cms.SignerInfo(identifier, digAlgId,
|
||||
signedAttr, encAlgId, encDigest, unsignedAttr);
|
||||
}
|
||||
}
|
||||
|
@ -307,6 +343,21 @@ namespace Org.BouncyCastle.Cms
|
|||
new DefaultSignedAttributeTableGenerator(), null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer - no attributes other than the default ones will be
|
||||
* provided here.
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string digestOID)
|
||||
{
|
||||
string encOID = GetEncOid(privateKey, digestOID);
|
||||
|
||||
signerInfs.Add(new SignerInf(this, privateKey, subjectKeyID, digestOID, encOID,
|
||||
new DefaultSignedAttributeTableGenerator(), null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer with extra signed/unsigned attributes.
|
||||
*/
|
||||
|
@ -325,6 +376,24 @@ namespace Org.BouncyCastle.Cms
|
|||
signedAttr));
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer with extra signed/unsigned attributes.
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string digestOID,
|
||||
Asn1.Cms.AttributeTable signedAttr,
|
||||
Asn1.Cms.AttributeTable unsignedAttr)
|
||||
{
|
||||
string encOID = GetEncOid(privateKey, digestOID);
|
||||
|
||||
signerInfs.Add(new SignerInf(this, privateKey, subjectKeyID, digestOID, encOID,
|
||||
new DefaultSignedAttributeTableGenerator(signedAttr),
|
||||
new SimpleAttributeTableGenerator(unsignedAttr),
|
||||
signedAttr));
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer with extra signed/unsigned attributes based on generators.
|
||||
*/
|
||||
|
@ -342,6 +411,22 @@ namespace Org.BouncyCastle.Cms
|
|||
}
|
||||
|
||||
/**
|
||||
* add a signer with extra signed/unsigned attributes based on generators.
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string digestOID,
|
||||
CmsAttributeTableGenerator signedAttrGen,
|
||||
CmsAttributeTableGenerator unsignedAttrGen)
|
||||
{
|
||||
string encOID = GetEncOid(privateKey, digestOID);
|
||||
|
||||
signerInfs.Add(new SignerInf(this, privateKey, subjectKeyID, digestOID, encOID,
|
||||
signedAttrGen, unsignedAttrGen, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a signed object that for a CMS Signed Data object
|
||||
*/
|
||||
public CmsSignedData Generate(
|
||||
|
|
|
@ -10,6 +10,7 @@ using Org.BouncyCastle.Crypto.IO;
|
|||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Security.Certificates;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
using Org.BouncyCastle.Utilities.Collections;
|
||||
using Org.BouncyCastle.Utilities.IO;
|
||||
using Org.BouncyCastle.X509;
|
||||
using Org.BouncyCastle.X509.Store;
|
||||
|
@ -60,8 +61,10 @@ namespace Org.BouncyCastle.Cms
|
|||
private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
|
||||
|
||||
private SignedDataParser _signedData;
|
||||
private DerObjectIdentifier _signedContentType;
|
||||
private CmsTypedStream _signedContent;
|
||||
private IDictionary _digests;
|
||||
private ISet _digestOids;
|
||||
|
||||
private SignerInformationStore _signerInfoStore;
|
||||
private Asn1Set _certSet, _crlSet;
|
||||
|
@ -108,6 +111,7 @@ namespace Org.BouncyCastle.Cms
|
|||
this._signedContent = signedContent;
|
||||
this._signedData = SignedDataParser.GetInstance(this.contentInfo.GetContent(Asn1Tags.Sequence));
|
||||
this._digests = new Hashtable();
|
||||
this._digestOids = new HashSet();
|
||||
|
||||
Asn1SetParser digAlgs = _signedData.GetDigestAlgorithms();
|
||||
IAsn1Convertible o;
|
||||
|
@ -118,14 +122,18 @@ namespace Org.BouncyCastle.Cms
|
|||
|
||||
try
|
||||
{
|
||||
string digestName = Helper.GetDigestAlgName(id.ObjectID.Id);
|
||||
IDigest dig = Helper.GetDigestInstance(digestName);
|
||||
string digestOid = id.ObjectID.Id;
|
||||
string digestName = Helper.GetDigestAlgName(digestOid);
|
||||
|
||||
this._digests[digestName] = dig;
|
||||
if (!this._digests.Contains(digestName))
|
||||
{
|
||||
this._digests[digestName] = Helper.GetDigestInstance(digestName);
|
||||
this._digestOids.Add(digestOid);
|
||||
}
|
||||
}
|
||||
catch (SecurityUtilityException)
|
||||
{
|
||||
// ignore
|
||||
// TODO Should do something other than ignore it
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,6 +161,10 @@ namespace Org.BouncyCastle.Cms
|
|||
ctStr.Drain();
|
||||
}
|
||||
}
|
||||
|
||||
_signedContentType = _signedContent == null
|
||||
? cont.ContentType
|
||||
: new DerObjectIdentifier(_signedContent.ContentType);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
@ -175,6 +187,11 @@ namespace Org.BouncyCastle.Cms
|
|||
get { return _signedData.Version.Value.IntValue; }
|
||||
}
|
||||
|
||||
public ISet DigestOids
|
||||
{
|
||||
get { return new HashSet(_digestOids); }
|
||||
}
|
||||
|
||||
/**
|
||||
* return the collection of signers that are associated with the
|
||||
* signatures for the message.
|
||||
|
@ -207,9 +224,8 @@ namespace Org.BouncyCastle.Cms
|
|||
info.DigestAlgorithm.ObjectID.Id);
|
||||
|
||||
byte[] hash = (byte[]) hashes[digestName];
|
||||
DerObjectIdentifier oid = new DerObjectIdentifier(_signedContent.ContentType);
|
||||
|
||||
signerInfos.Add(new SignerInformation(info, oid, null, new BaseDigestCalculator(hash)));
|
||||
signerInfos.Add(new SignerInformation(info, _signedContentType, null, new BaseDigestCalculator(hash)));
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
|
@ -308,6 +324,15 @@ namespace Org.BouncyCastle.Cms
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the <c>DerObjectIdentifier</c> associated with the encapsulated
|
||||
/// content info structure carried in the signed data.
|
||||
/// </summary>
|
||||
public DerObjectIdentifier SignedContentType
|
||||
{
|
||||
get { return _signedContentType; }
|
||||
}
|
||||
|
||||
public CmsTypedStream GetSignedContent()
|
||||
{
|
||||
if (_signedContent == null)
|
||||
|
@ -343,63 +368,28 @@ namespace Org.BouncyCastle.Cms
|
|||
SignerInformationStore signerInformationStore,
|
||||
Stream outStr)
|
||||
{
|
||||
Asn1StreamParser inStr = new Asn1StreamParser(original, CmsUtilities.MaximumMemory);
|
||||
ContentInfoParser contentInfo = new ContentInfoParser((Asn1SequenceParser)inStr.ReadObject());
|
||||
SignedDataParser signedData = SignedDataParser.GetInstance(contentInfo.GetContent(Asn1Tags.Sequence));
|
||||
// NB: SecureRandom would be ignored since using existing signatures only
|
||||
CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
|
||||
CmsSignedDataParser parser = new CmsSignedDataParser(original);
|
||||
|
||||
BerSequenceGenerator sGen = new BerSequenceGenerator(outStr);
|
||||
// gen.AddDigests(parser.DigestOids);
|
||||
gen.AddSigners(signerInformationStore);
|
||||
|
||||
sGen.AddObject(CmsObjectIdentifiers.SignedData);
|
||||
|
||||
BerSequenceGenerator sigGen = new BerSequenceGenerator(sGen.GetRawOutputStream(), 0, true);
|
||||
|
||||
// version number
|
||||
sigGen.AddObject(signedData.Version);
|
||||
|
||||
// digests
|
||||
signedData.GetDigestAlgorithms().ToAsn1Object(); // skip old ones
|
||||
|
||||
Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
|
||||
|
||||
foreach (SignerInformation signer in signerInformationStore.GetSigners())
|
||||
CmsTypedStream signedContent = parser.GetSignedContent();
|
||||
bool encapsulate = (signedContent != null);
|
||||
Stream contentOut = gen.Open(outStr, parser.SignedContentType.Id, encapsulate);
|
||||
if (encapsulate)
|
||||
{
|
||||
digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
|
||||
Streams.PipeAll(signedContent.ContentStream, contentOut);
|
||||
}
|
||||
|
||||
WriteToGenerator(sigGen, new DerSet(digestAlgs));
|
||||
gen.AddAttributeCertificates(parser.GetAttributeCertificates("Collection"));
|
||||
gen.AddCertificates(parser.GetCertificates("Collection"));
|
||||
gen.AddCrls(parser.GetCrls("Collection"));
|
||||
|
||||
// encap content info
|
||||
ContentInfoParser encapContentInfo = signedData.GetEncapContentInfo();
|
||||
// gen.AddSigners(parser.GetSignerInfos());
|
||||
|
||||
BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());
|
||||
|
||||
eiGen.AddObject(encapContentInfo.ContentType);
|
||||
|
||||
Asn1OctetStringParser octs = (Asn1OctetStringParser)encapContentInfo.GetContent(Asn1Tags.OctetString);
|
||||
|
||||
if (octs != null)
|
||||
{
|
||||
PipeOctetString(octs, eiGen.GetRawOutputStream());
|
||||
}
|
||||
|
||||
eiGen.Close();
|
||||
|
||||
|
||||
WriteSetToGeneratorTagged(sigGen, signedData.GetCertificates(), 0);
|
||||
WriteSetToGeneratorTagged(sigGen, signedData.GetCrls(), 1);
|
||||
|
||||
|
||||
Asn1EncodableVector signerInfos = new Asn1EncodableVector();
|
||||
foreach (SignerInformation signer in signerInformationStore.GetSigners())
|
||||
{
|
||||
signerInfos.Add(signer.ToSignerInfo());
|
||||
}
|
||||
|
||||
WriteToGenerator(sigGen, new DerSet(signerInfos));
|
||||
|
||||
sigGen.Close();
|
||||
|
||||
sGen.Close();
|
||||
contentOut.Close();
|
||||
|
||||
return outStr;
|
||||
}
|
||||
|
@ -423,109 +413,37 @@ namespace Org.BouncyCastle.Cms
|
|||
IX509Store x509AttrCerts,
|
||||
Stream outStr)
|
||||
{
|
||||
// NB: SecureRandom would be ignored since using existing signatures only
|
||||
CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
|
||||
CmsSignedDataParser parser = new CmsSignedDataParser(original);
|
||||
|
||||
gen.AddDigests(parser.DigestOids);
|
||||
|
||||
CmsTypedStream signedContent = parser.GetSignedContent();
|
||||
bool encapsulate = (signedContent != null);
|
||||
Stream contentOut = gen.Open(outStr, parser.SignedContentType.Id, encapsulate);
|
||||
if (encapsulate)
|
||||
{
|
||||
Streams.PipeAll(signedContent.ContentStream, contentOut);
|
||||
}
|
||||
|
||||
// gen.AddAttributeCertificates(parser.GetAttributeCertificates("Collection"));
|
||||
// gen.AddCertificates(parser.GetCertificates("Collection"));
|
||||
// gen.AddCrls(parser.GetCrls("Collection"));
|
||||
if (x509AttrCerts != null)
|
||||
throw Platform.CreateNotImplementedException("Currently can't replace attribute certificates");
|
||||
gen.AddAttributeCertificates(x509AttrCerts);
|
||||
if (x509Certs != null)
|
||||
gen.AddCertificates(x509Certs);
|
||||
if (x509Crls != null)
|
||||
gen.AddCrls(x509Crls);
|
||||
|
||||
Asn1StreamParser inStr = new Asn1StreamParser(original, CmsUtilities.MaximumMemory);
|
||||
ContentInfoParser contentInfo = new ContentInfoParser((Asn1SequenceParser)inStr.ReadObject());
|
||||
SignedDataParser signedData = SignedDataParser.GetInstance(contentInfo.GetContent(Asn1Tags.Sequence));
|
||||
gen.AddSigners(parser.GetSignerInfos());
|
||||
|
||||
BerSequenceGenerator sGen = new BerSequenceGenerator(outStr);
|
||||
|
||||
sGen.AddObject(CmsObjectIdentifiers.SignedData);
|
||||
|
||||
BerSequenceGenerator sigGen = new BerSequenceGenerator(sGen.GetRawOutputStream(), 0, true);
|
||||
|
||||
// version number
|
||||
sigGen.AddObject(signedData.Version);
|
||||
|
||||
// digests
|
||||
WriteToGenerator(sigGen, signedData.GetDigestAlgorithms().ToAsn1Object());
|
||||
|
||||
// encap content info
|
||||
ContentInfoParser encapContentInfo = signedData.GetEncapContentInfo();
|
||||
|
||||
BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());
|
||||
|
||||
eiGen.AddObject(encapContentInfo.ContentType);
|
||||
|
||||
Asn1OctetStringParser octs = (Asn1OctetStringParser)
|
||||
encapContentInfo.GetContent(Asn1Tags.OctetString);
|
||||
|
||||
if (octs != null)
|
||||
{
|
||||
PipeOctetString(octs, eiGen.GetRawOutputStream());
|
||||
}
|
||||
|
||||
eiGen.Close();
|
||||
|
||||
//
|
||||
// skip existing certs and CRLs
|
||||
//
|
||||
GetAsn1Set(signedData.GetCertificates());
|
||||
GetAsn1Set(signedData.GetCrls());
|
||||
|
||||
//
|
||||
// replace the certs and crls in the SignedData object
|
||||
//
|
||||
Asn1Set certs;
|
||||
try
|
||||
{
|
||||
certs = CmsUtilities.CreateBerSetFromList(
|
||||
CmsUtilities.GetCertificatesFromStore(x509Certs));
|
||||
}
|
||||
catch (X509StoreException e)
|
||||
{
|
||||
throw new CmsException("error getting certs from certStore", e);
|
||||
}
|
||||
|
||||
if (certs.Count > 0)
|
||||
{
|
||||
WriteToGenerator(sigGen, new DerTaggedObject(false, 0, certs));
|
||||
}
|
||||
|
||||
Asn1Set crls;
|
||||
try
|
||||
{
|
||||
crls = CmsUtilities.CreateBerSetFromList(
|
||||
CmsUtilities.GetCrlsFromStore(x509Crls));
|
||||
}
|
||||
catch (X509StoreException e)
|
||||
{
|
||||
throw new CmsException("error getting crls from certStore", e);
|
||||
}
|
||||
|
||||
if (crls.Count > 0)
|
||||
{
|
||||
WriteToGenerator(sigGen, new DerTaggedObject(false, 1, crls));
|
||||
}
|
||||
|
||||
WriteToGenerator(sigGen, signedData.GetSignerInfos().ToAsn1Object());
|
||||
|
||||
sigGen.Close();
|
||||
|
||||
sGen.Close();
|
||||
contentOut.Close();
|
||||
|
||||
return outStr;
|
||||
}
|
||||
|
||||
private static void WriteSetToGeneratorTagged(
|
||||
Asn1Generator asn1Gen,
|
||||
Asn1SetParser asn1SetParser,
|
||||
int tagNo)
|
||||
{
|
||||
Asn1Set asn1Set = GetAsn1Set(asn1SetParser);
|
||||
|
||||
if (asn1Set != null)
|
||||
{
|
||||
Asn1TaggedObject taggedObj = (asn1SetParser is BerSetParser)
|
||||
? new BerTaggedObject(false, tagNo, asn1Set)
|
||||
: new DerTaggedObject(false, tagNo, asn1Set);
|
||||
|
||||
WriteToGenerator(asn1Gen, taggedObj);
|
||||
}
|
||||
}
|
||||
|
||||
private static Asn1Set GetAsn1Set(
|
||||
Asn1SetParser asn1SetParser)
|
||||
{
|
||||
|
@ -533,24 +451,5 @@ namespace Org.BouncyCastle.Cms
|
|||
? null
|
||||
: Asn1Set.GetInstance(asn1SetParser.ToAsn1Object());
|
||||
}
|
||||
|
||||
private static void WriteToGenerator(
|
||||
Asn1Generator ag,
|
||||
Asn1Encodable ae)
|
||||
{
|
||||
byte[] encoded = ae.GetEncoded();
|
||||
ag.GetRawOutputStream().Write(encoded, 0, encoded.Length);
|
||||
}
|
||||
|
||||
private static void PipeOctetString(
|
||||
Asn1OctetStringParser octs,
|
||||
Stream output)
|
||||
{
|
||||
BerOctetStringGenerator octGen = new BerOctetStringGenerator(output, 0, true);
|
||||
// TODO Allow specification of a specific fragment size?
|
||||
Stream outOctets = octGen.GetOctetOutputStream();
|
||||
Streams.PipeAll(octs.GetOctetStream(), outOctets);
|
||||
outOctets.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ using Org.BouncyCastle.Crypto.IO;
|
|||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Security.Certificates;
|
||||
using Org.BouncyCastle.Utilities.Collections;
|
||||
using Org.BouncyCastle.Utilities.IO;
|
||||
using Org.BouncyCastle.X509;
|
||||
|
||||
|
@ -42,21 +43,24 @@ namespace Org.BouncyCastle.Cms
|
|||
private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
|
||||
|
||||
private readonly ArrayList _signerInfs = new ArrayList();
|
||||
private readonly ArrayList _messageDigests = new ArrayList();
|
||||
private readonly ISet _messageDigestOids = new HashSet();
|
||||
private readonly Hashtable _messageDigests = new Hashtable();
|
||||
private readonly Hashtable _messageHashes = new Hashtable();
|
||||
private bool _messageDigestsLocked;
|
||||
private int _bufferSize;
|
||||
|
||||
private class SignerInf
|
||||
{
|
||||
private readonly CmsSignedDataStreamGenerator outer;
|
||||
|
||||
AsymmetricKeyParameter _key;
|
||||
X509Certificate _cert;
|
||||
string _digestOID;
|
||||
string _encOID;
|
||||
CmsAttributeTableGenerator _sAttr;
|
||||
CmsAttributeTableGenerator _unsAttr;
|
||||
IDigest _digest;
|
||||
ISigner _signature;
|
||||
private AsymmetricKeyParameter _key;
|
||||
private X509Certificate _cert;
|
||||
private string _digestOID;
|
||||
private string _encOID;
|
||||
private CmsAttributeTableGenerator _sAttr;
|
||||
private CmsAttributeTableGenerator _unsAttr;
|
||||
private ISigner _signature;
|
||||
private byte[] _subjectKeyID;
|
||||
|
||||
internal SignerInf(
|
||||
CmsSignedDataStreamGenerator outer,
|
||||
|
@ -66,7 +70,6 @@ namespace Org.BouncyCastle.Cms
|
|||
string encOID,
|
||||
CmsAttributeTableGenerator sAttr,
|
||||
CmsAttributeTableGenerator unsAttr,
|
||||
IDigest digest,
|
||||
ISigner signature)
|
||||
{
|
||||
this.outer = outer;
|
||||
|
@ -77,7 +80,27 @@ namespace Org.BouncyCastle.Cms
|
|||
_encOID = encOID;
|
||||
_sAttr = sAttr;
|
||||
_unsAttr = unsAttr;
|
||||
_digest = digest;
|
||||
_signature = signature;
|
||||
}
|
||||
|
||||
internal SignerInf(
|
||||
CmsSignedDataStreamGenerator outer,
|
||||
AsymmetricKeyParameter key,
|
||||
byte[] subjectKeyID,
|
||||
string digestOID,
|
||||
string encOID,
|
||||
CmsAttributeTableGenerator sAttr,
|
||||
CmsAttributeTableGenerator unsAttr,
|
||||
ISigner signature)
|
||||
{
|
||||
this.outer = outer;
|
||||
|
||||
_key = key;
|
||||
_subjectKeyID = subjectKeyID;
|
||||
_digestOID = digestOID;
|
||||
_encOID = encOID;
|
||||
_sAttr = sAttr;
|
||||
_unsAttr = unsAttr;
|
||||
_signature = signature;
|
||||
}
|
||||
|
||||
|
@ -91,46 +114,21 @@ namespace Org.BouncyCastle.Cms
|
|||
get { return _cert; }
|
||||
}
|
||||
|
||||
internal AlgorithmIdentifier DigestAlgorithmID
|
||||
{
|
||||
get { return new AlgorithmIdentifier(new DerObjectIdentifier(_digestOID), null); }
|
||||
}
|
||||
|
||||
internal string DigestAlgOid
|
||||
{
|
||||
get { return _digestOID; }
|
||||
}
|
||||
|
||||
internal Asn1Object DigestAlgParams
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
internal string EncryptionAlgOid
|
||||
{
|
||||
get { return _encOID; }
|
||||
}
|
||||
|
||||
// internal Asn1.Cms.AttributeTable SignedAttributes
|
||||
// {
|
||||
// get { return _sAttr; }
|
||||
// }
|
||||
//
|
||||
// internal Asn1.Cms.AttributeTable UnsignedAttributes
|
||||
// {
|
||||
// get { return _unsAttr; }
|
||||
// }
|
||||
|
||||
internal SignerInfo ToSignerInfo(
|
||||
DerObjectIdentifier contentType)
|
||||
{
|
||||
AlgorithmIdentifier digAlgId = new AlgorithmIdentifier(
|
||||
new DerObjectIdentifier(this.DigestAlgOid), DerNull.Instance);
|
||||
new DerObjectIdentifier(this._digestOID), DerNull.Instance);
|
||||
AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(this.EncryptionAlgOid);
|
||||
|
||||
byte[] hash = DigestUtilities.DoFinal(_digest);
|
||||
byte[] hash = (byte[])outer._messageHashes[Helper.GetDigestAlgName(this._digestOID)];
|
||||
|
||||
outer._digests.Add(_digestOID, hash.Clone());
|
||||
outer._digests[_digestOID] = hash.Clone();
|
||||
|
||||
IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);
|
||||
|
||||
|
@ -169,12 +167,22 @@ namespace Org.BouncyCastle.Cms
|
|||
Asn1Set unsignedAttr = outer.GetAttributeSet(unsigned);
|
||||
|
||||
X509Certificate cert = this.Certificate;
|
||||
SignerIdentifier signerIdentifier;
|
||||
if (cert != null)
|
||||
{
|
||||
TbsCertificateStructure tbs = TbsCertificateStructure.GetInstance(
|
||||
Asn1Object.FromByteArray(cert.GetTbsCertificate()));
|
||||
IssuerAndSerialNumber encSid = new IssuerAndSerialNumber(
|
||||
tbs.Issuer, tbs.SerialNumber.Value);
|
||||
|
||||
return new SignerInfo(new SignerIdentifier(encSid), digAlgId,
|
||||
signerIdentifier = new SignerIdentifier(encSid);
|
||||
}
|
||||
else
|
||||
{
|
||||
signerIdentifier = new SignerIdentifier(new DerOctetString(_subjectKeyID));
|
||||
}
|
||||
|
||||
return new SignerInfo(signerIdentifier, digAlgId,
|
||||
signedAttr, encAlgId, encDigest, unsignedAttr);
|
||||
}
|
||||
|
||||
|
@ -203,6 +211,21 @@ namespace Org.BouncyCastle.Cms
|
|||
_bufferSize = bufferSize;
|
||||
}
|
||||
|
||||
public void AddDigests(
|
||||
params string[] digestOids)
|
||||
{
|
||||
AddDigests((IEnumerable) digestOids);
|
||||
}
|
||||
|
||||
public void AddDigests(
|
||||
IEnumerable digestOids)
|
||||
{
|
||||
foreach (string digestOid in digestOids)
|
||||
{
|
||||
ConfigureDigest(digestOid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer - no attributes other than the default ones will be
|
||||
* provided here.
|
||||
|
@ -212,9 +235,9 @@ namespace Org.BouncyCastle.Cms
|
|||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string digestOID)
|
||||
string digestOid)
|
||||
{
|
||||
AddSigner(privateKey, cert, digestOID,
|
||||
AddSigner(privateKey, cert, digestOid,
|
||||
new DefaultSignedAttributeTableGenerator(), null);
|
||||
}
|
||||
|
||||
|
@ -226,11 +249,11 @@ namespace Org.BouncyCastle.Cms
|
|||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string digestOID,
|
||||
string digestOid,
|
||||
Asn1.Cms.AttributeTable signedAttr,
|
||||
Asn1.Cms.AttributeTable unsignedAttr)
|
||||
{
|
||||
AddSigner(privateKey, cert, digestOID,
|
||||
AddSigner(privateKey, cert, digestOid,
|
||||
new DefaultSignedAttributeTableGenerator(signedAttr),
|
||||
new SimpleAttributeTableGenerator(unsignedAttr));
|
||||
}
|
||||
|
@ -238,21 +261,78 @@ namespace Org.BouncyCastle.Cms
|
|||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
X509Certificate cert,
|
||||
string digestOID,
|
||||
string digestOid,
|
||||
CmsAttributeTableGenerator signedAttrGenerator,
|
||||
CmsAttributeTableGenerator unsignedAttrGenerator)
|
||||
{
|
||||
string encOID = GetEncOid(privateKey, digestOID);
|
||||
string digestName = Helper.GetDigestAlgName(digestOID);
|
||||
ConfigureDigest(digestOid);
|
||||
|
||||
string digestName = Helper.GetDigestAlgName(digestOid);
|
||||
string encOID = GetEncOid(privateKey, digestOid);
|
||||
string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
|
||||
ISigner sig = Helper.GetSignatureInstance(signatureName);
|
||||
IDigest dig = Helper.GetDigestInstance(digestName);
|
||||
|
||||
sig.Init(true, new ParametersWithRandom(privateKey, rand));
|
||||
|
||||
_signerInfs.Add(new SignerInf(this, privateKey, cert, digestOID, encOID,
|
||||
signedAttrGenerator, unsignedAttrGenerator, dig, sig));
|
||||
_messageDigests.Add(dig);
|
||||
_signerInfs.Add(new SignerInf(this, privateKey, cert, digestOid, encOID,
|
||||
signedAttrGenerator, unsignedAttrGenerator, sig));
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer - no attributes other than the default ones will be
|
||||
* provided here.
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string digestOid)
|
||||
{
|
||||
AddSigner(privateKey, subjectKeyID, digestOid, new DefaultSignedAttributeTableGenerator(),
|
||||
(CmsAttributeTableGenerator)null);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a signer with extra signed/unsigned attributes.
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string digestOid,
|
||||
Asn1.Cms.AttributeTable signedAttr,
|
||||
Asn1.Cms.AttributeTable unsignedAttr)
|
||||
{
|
||||
AddSigner(privateKey, subjectKeyID, digestOid,
|
||||
new DefaultSignedAttributeTableGenerator(signedAttr),
|
||||
new SimpleAttributeTableGenerator(unsignedAttr));
|
||||
}
|
||||
|
||||
public void AddSigner(
|
||||
AsymmetricKeyParameter privateKey,
|
||||
byte[] subjectKeyID,
|
||||
string digestOid,
|
||||
CmsAttributeTableGenerator signedAttrGenerator,
|
||||
CmsAttributeTableGenerator unsignedAttrGenerator)
|
||||
{
|
||||
ConfigureDigest(digestOid);
|
||||
|
||||
string digestName = Helper.GetDigestAlgName(digestOid);
|
||||
string encOID = GetEncOid(privateKey, digestOid);
|
||||
string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
|
||||
ISigner sig = Helper.GetSignatureInstance(signatureName);
|
||||
sig.Init(true, new ParametersWithRandom(privateKey, rand));
|
||||
|
||||
_signerInfs.Add(new SignerInf(this, privateKey, subjectKeyID, digestOid, encOID,
|
||||
signedAttrGenerator, unsignedAttrGenerator, sig));
|
||||
}
|
||||
|
||||
internal override void AddSignerCallback(
|
||||
SignerInformation si)
|
||||
{
|
||||
// For precalculated signers, just need to register the algorithm, not configure a digest
|
||||
RegisterDigestOid(si.DigestAlgOid);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -332,6 +412,8 @@ namespace Org.BouncyCastle.Cms
|
|||
if (dataOutputStream != null && !dataOutputStream.CanWrite)
|
||||
throw new ArgumentException("Expected writeable stream", "dataOutputStream");
|
||||
|
||||
_messageDigestsLocked = true;
|
||||
|
||||
//
|
||||
// ContentInfo
|
||||
//
|
||||
|
@ -349,20 +431,10 @@ namespace Org.BouncyCastle.Cms
|
|||
|
||||
Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
|
||||
|
||||
//
|
||||
// add the precalculated SignerInfo digest algorithms.
|
||||
//
|
||||
foreach (SignerInformation signer in _signers)
|
||||
foreach (string digestOid in _messageDigestOids)
|
||||
{
|
||||
digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
|
||||
}
|
||||
|
||||
//
|
||||
// add the new digests
|
||||
//
|
||||
foreach (SignerInf signer in _signerInfs)
|
||||
{
|
||||
digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
|
||||
digestAlgs.Add(
|
||||
new AlgorithmIdentifier(new DerObjectIdentifier(digestOid), DerNull.Instance));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -399,7 +471,7 @@ namespace Org.BouncyCastle.Cms
|
|||
}
|
||||
}
|
||||
|
||||
foreach (IDigest d in _messageDigests)
|
||||
foreach (IDigest d in _messageDigests.Values)
|
||||
{
|
||||
digStream = new DigestStream(digStream, null, d);
|
||||
}
|
||||
|
@ -407,6 +479,37 @@ namespace Org.BouncyCastle.Cms
|
|||
return new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen);
|
||||
}
|
||||
|
||||
private void RegisterDigestOid(
|
||||
string digestOid)
|
||||
{
|
||||
if (_messageDigestsLocked)
|
||||
{
|
||||
if (!_messageDigestOids.Contains(digestOid))
|
||||
throw new InvalidOperationException("Cannot register new digest OIDs after the data stream is opened");
|
||||
}
|
||||
else
|
||||
{
|
||||
_messageDigestOids.Add(digestOid);
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigureDigest(
|
||||
string digestOid)
|
||||
{
|
||||
RegisterDigestOid(digestOid);
|
||||
|
||||
string digestName = Helper.GetDigestAlgName(digestOid);
|
||||
IDigest dig = (IDigest)_messageDigests[digestName];
|
||||
if (dig == null)
|
||||
{
|
||||
if (_messageDigestsLocked)
|
||||
throw new InvalidOperationException("Cannot configure new digests after the data stream is opened");
|
||||
|
||||
dig = Helper.GetDigestInstance(digestName);
|
||||
_messageDigests[digestName] = dig;
|
||||
}
|
||||
}
|
||||
|
||||
// RFC3852, section 5.1:
|
||||
// IF ((certificates is present) AND
|
||||
// (any certificates with a type of other are present)) OR
|
||||
|
@ -629,6 +732,17 @@ namespace Org.BouncyCastle.Cms
|
|||
WriteToGenerator(_sigGen, new BerTaggedObject(false, 1, crls));
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate the digest hashes
|
||||
//
|
||||
foreach (DictionaryEntry de in outer._messageDigests)
|
||||
{
|
||||
outer._messageHashes.Add(de.Key, DigestUtilities.DoFinal((IDigest)de.Value));
|
||||
}
|
||||
|
||||
// TODO If the digest OIDs for precalculated signers weren't mixed in with
|
||||
// the others, we could fill in outer._digests here, instead of SignerInf.ToSignerInfo
|
||||
|
||||
//
|
||||
// add the precalculated SignerInfo objects.
|
||||
//
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
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;
|
||||
|
@ -20,6 +22,13 @@ namespace Org.BouncyCastle.Cms
|
|||
{
|
||||
}
|
||||
|
||||
public Pkcs5Scheme2PbeKey(
|
||||
string password,
|
||||
AlgorithmIdentifier keyDerivationAlgorithm)
|
||||
: base(password, keyDerivationAlgorithm)
|
||||
{
|
||||
}
|
||||
|
||||
internal override KeyParameter GetEncoded(
|
||||
string algorithmOid)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
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;
|
||||
|
@ -20,6 +22,13 @@ namespace Org.BouncyCastle.Cms
|
|||
{
|
||||
}
|
||||
|
||||
public Pkcs5Scheme2Utf8PbeKey(
|
||||
string password,
|
||||
AlgorithmIdentifier keyDerivationAlgorithm)
|
||||
: base(password, keyDerivationAlgorithm)
|
||||
{
|
||||
}
|
||||
|
||||
internal override KeyParameter GetEncoded(
|
||||
string algorithmOid)
|
||||
{
|
||||
|
|
|
@ -39,10 +39,7 @@ namespace Org.BouncyCastle.Cms
|
|||
*/
|
||||
public virtual AlgorithmIdentifier KeyDerivationAlgorithm
|
||||
{
|
||||
get
|
||||
{
|
||||
return _info.KeyDerivationAlgorithm;
|
||||
}
|
||||
get { return _info.KeyDerivationAlgorithm; }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace Org.BouncyCastle.Cms
|
|||
{
|
||||
Asn1OctetString octs = Asn1OctetString.GetInstance(s.ID);
|
||||
|
||||
sid.SubjectKeyIdentifier = octs.GetOctets();
|
||||
sid.SubjectKeyIdentifier = octs.GetEncoded();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -278,6 +278,10 @@ namespace Org.BouncyCastle.Crypto
|
|||
outBytes = tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
return outBytes;
|
||||
}
|
||||
|
@ -311,6 +315,10 @@ namespace Org.BouncyCastle.Crypto
|
|||
outBytes = tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
return outBytes;
|
||||
}
|
||||
|
|
|
@ -129,6 +129,9 @@ namespace Org.BouncyCastle.Crypto.Encodings
|
|||
int inOff,
|
||||
int inLen)
|
||||
{
|
||||
if (inLen > GetInputBlockSize())
|
||||
throw new ArgumentException("input data too large", "inLen");
|
||||
|
||||
byte[] block = new byte[engine.GetInputBlockSize()];
|
||||
|
||||
if (forPrivateKey)
|
||||
|
|
|
@ -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,10 +1,13 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
using Org.BouncyCastle.Crypto;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.IO
|
||||
{
|
||||
public class CipherStream : Stream
|
||||
public class CipherStream
|
||||
: Stream
|
||||
{
|
||||
internal Stream stream;
|
||||
internal IBufferedCipher inCipher, outCipher;
|
||||
|
@ -44,79 +47,60 @@ namespace Org.BouncyCastle.Crypto.IO
|
|||
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)
|
||||
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 num = 0;
|
||||
while (num < count)
|
||||
{
|
||||
int c = ReadByte();
|
||||
|
||||
if (c < 0) break;
|
||||
|
||||
buffer[offset + i++] = (byte) c;
|
||||
if (mInBuf == null || mInPos >= mInBuf.Length)
|
||||
{
|
||||
if (!FillInBuf())
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
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();
|
||||
mInBuf = ReadAndProcessBlock();
|
||||
}
|
||||
while (!inStreamEnded && mInBuf == null);
|
||||
|
||||
return mInBuf != null;
|
||||
}
|
||||
private byte[] readAndProcessBlock()
|
||||
|
||||
private byte[] ReadAndProcessBlock()
|
||||
{
|
||||
int blockSize = inCipher.GetBlockSize();
|
||||
int readSize = (blockSize == 0) ? 256 : blockSize;
|
||||
|
@ -148,7 +132,11 @@ namespace Org.BouncyCastle.Crypto.IO
|
|||
|
||||
return bytes;
|
||||
}
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
|
||||
public override void Write(
|
||||
byte[] buffer,
|
||||
int offset,
|
||||
int count)
|
||||
{
|
||||
Debug.Assert(buffer != null);
|
||||
Debug.Assert(0 <= offset && offset <= buffer.Length);
|
||||
|
@ -170,39 +158,49 @@ namespace Org.BouncyCastle.Crypto.IO
|
|||
stream.Write(data, 0, data.Length);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteByte(
|
||||
byte value)
|
||||
byte b)
|
||||
{
|
||||
if (outCipher == null)
|
||||
{
|
||||
stream.WriteByte(value);
|
||||
stream.WriteByte(b);
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] data = outCipher.ProcessByte(value);
|
||||
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 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)
|
||||
|
@ -213,12 +211,24 @@ namespace Org.BouncyCastle.Crypto.IO
|
|||
}
|
||||
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(); }
|
||||
|
||||
public sealed override long Seek(
|
||||
long offset,
|
||||
SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public sealed override void SetLength(
|
||||
long length)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
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
|
||||
public class Pkcs7Padding
|
||||
: IBlockCipherPadding
|
||||
{
|
||||
/**
|
||||
* Initialise the padder.
|
||||
*
|
||||
* @param random - a SecureRandom if available.
|
||||
*/
|
||||
public void Init(SecureRandom random)
|
||||
public void Init(
|
||||
SecureRandom random)
|
||||
{
|
||||
// nothing to do.
|
||||
}
|
||||
|
|
|
@ -5,25 +5,33 @@ using Org.BouncyCastle.Crypto.Digests;
|
|||
namespace Org.BouncyCastle.Crypto.Prng
|
||||
{
|
||||
/**
|
||||
* Random generation based on the digest with counter. Calling addSeedMaterial will
|
||||
* 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.
|
||||
* Internal access to the digest is synchronized so a single one of these can be shared.
|
||||
* </p>
|
||||
*/
|
||||
public class DigestRandomGenerator
|
||||
: IRandomGenerator
|
||||
{
|
||||
private long counter;
|
||||
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.counter = 1;
|
||||
this.stateCounter = 1;
|
||||
}
|
||||
|
||||
public void AddSeedMaterial(
|
||||
|
@ -32,6 +40,8 @@ namespace Org.BouncyCastle.Crypto.Prng
|
|||
lock (this)
|
||||
{
|
||||
DigestUpdate(inSeed);
|
||||
DigestUpdate(seed);
|
||||
DigestDoFinal(seed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,12 +50,9 @@ namespace Org.BouncyCastle.Crypto.Prng
|
|||
{
|
||||
lock (this)
|
||||
{
|
||||
for (int i = 0; i != 8; i++)
|
||||
{
|
||||
DigestUpdate((byte)rSeed);
|
||||
// rSeed >>>= 8;
|
||||
rSeed >>= 8;
|
||||
}
|
||||
DigestAddCounter(rSeed);
|
||||
DigestUpdate(seed);
|
||||
DigestDoFinal(seed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,32 +71,47 @@ namespace Org.BouncyCastle.Crypto.Prng
|
|||
{
|
||||
int stateOff = 0;
|
||||
|
||||
DigestDoFinal(state);
|
||||
GenerateState();
|
||||
|
||||
int end = start + len;
|
||||
for (int i = start; i < end; ++i)
|
||||
{
|
||||
if (stateOff == state.Length)
|
||||
{
|
||||
DigestUpdate(counter++);
|
||||
DigestUpdate(state);
|
||||
DigestDoFinal(state);
|
||||
GenerateState();
|
||||
stateOff = 0;
|
||||
}
|
||||
bytes[i] = state[stateOff++];
|
||||
}
|
||||
|
||||
DigestUpdate(counter++);
|
||||
DigestUpdate(state);
|
||||
}
|
||||
}
|
||||
|
||||
private void DigestUpdate(long seed)
|
||||
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;
|
||||
seed >>= 8;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,9 +142,15 @@ namespace Org.BouncyCastle.Crypto.Signers
|
|||
BigInteger n,
|
||||
byte[] message)
|
||||
{
|
||||
int length = System.Math.Min(message.Length, n.BitLength / 8);
|
||||
int messageBitLength = message.Length * 8;
|
||||
BigInteger trunc = new BigInteger(1, message);
|
||||
|
||||
return new BigInteger(1, message, 0, length);
|
||||
if (n.BitLength < messageBitLength)
|
||||
{
|
||||
trunc = trunc.ShiftRight(messageBitLength - n.BitLength);
|
||||
}
|
||||
|
||||
return trunc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ namespace Org.BouncyCastle.Crypto.Tls
|
|||
if (offset + len - 1 - paddingsize < 0)
|
||||
{
|
||||
/*
|
||||
* This would lead to an negativ array index, so this padding
|
||||
* This would lead to a negative array index, so this padding
|
||||
* must be incorrect!
|
||||
*/
|
||||
decrypterror = true;
|
||||
|
@ -175,7 +175,7 @@ namespace Org.BouncyCastle.Crypto.Tls
|
|||
}
|
||||
|
||||
/*
|
||||
* Now, it is save to fail.
|
||||
* Now, it is safe to fail.
|
||||
*/
|
||||
if (decrypterror)
|
||||
{
|
||||
|
|
|
@ -119,7 +119,7 @@ namespace Org.BouncyCastle.Crypto.Tls
|
|||
private byte[] serverRandom;
|
||||
private byte[] ms;
|
||||
|
||||
private TlsCipherSuite choosenCipherSuite = null;
|
||||
private TlsCipherSuite chosenCipherSuite = null;
|
||||
|
||||
private BigInteger Yc;
|
||||
private byte[] pms;
|
||||
|
@ -379,7 +379,7 @@ namespace Org.BouncyCastle.Crypto.Tls
|
|||
* the TlsCipherSuiteManager will throw an
|
||||
* exception.
|
||||
*/
|
||||
this.choosenCipherSuite = TlsCipherSuiteManager.GetCipherSuite(
|
||||
this.chosenCipherSuite = TlsCipherSuiteManager.GetCipherSuite(
|
||||
TlsUtilities.ReadUint16(inStr), this);
|
||||
|
||||
/*
|
||||
|
@ -415,7 +415,7 @@ namespace Org.BouncyCastle.Crypto.Tls
|
|||
* There was no server key exchange message, check
|
||||
* that we are doing RSA key exchange.
|
||||
*/
|
||||
if (this.choosenCipherSuite.KeyExchangeAlgorithm != TlsCipherSuite.KE_RSA)
|
||||
if (this.chosenCipherSuite.KeyExchangeAlgorithm != TlsCipherSuite.KE_RSA)
|
||||
{
|
||||
this.FailWithError(AL_fatal, AP_unexpected_message);
|
||||
}
|
||||
|
@ -435,7 +435,7 @@ namespace Org.BouncyCastle.Crypto.Tls
|
|||
* on the key exchange we are using in our
|
||||
* ciphersuite.
|
||||
*/
|
||||
short ke = this.choosenCipherSuite.KeyExchangeAlgorithm;
|
||||
short ke = this.chosenCipherSuite.KeyExchangeAlgorithm;
|
||||
|
||||
switch (ke)
|
||||
{
|
||||
|
@ -535,7 +535,7 @@ namespace Org.BouncyCastle.Crypto.Tls
|
|||
/*
|
||||
* Initialize our cipher suite
|
||||
*/
|
||||
rs.writeSuite = this.choosenCipherSuite;
|
||||
rs.writeSuite = this.chosenCipherSuite;
|
||||
rs.writeSuite.Init(this.ms, clientRandom, serverRandom);
|
||||
|
||||
/*
|
||||
|
@ -569,7 +569,7 @@ namespace Org.BouncyCastle.Crypto.Tls
|
|||
/*
|
||||
* Check that we are doing DHE key exchange
|
||||
*/
|
||||
if (this.choosenCipherSuite.KeyExchangeAlgorithm != TlsCipherSuite.KE_DHE_RSA)
|
||||
if (this.chosenCipherSuite.KeyExchangeAlgorithm != TlsCipherSuite.KE_DHE_RSA)
|
||||
{
|
||||
this.FailWithError(AL_fatal, AP_unexpected_message);
|
||||
}
|
||||
|
@ -687,7 +687,7 @@ namespace Org.BouncyCastle.Crypto.Tls
|
|||
* There was no server key exchange message, check
|
||||
* that we are doing RSA key exchange.
|
||||
*/
|
||||
if (this.choosenCipherSuite.KeyExchangeAlgorithm != TlsCipherSuite.KE_RSA)
|
||||
if (this.chosenCipherSuite.KeyExchangeAlgorithm != TlsCipherSuite.KE_RSA)
|
||||
{
|
||||
this.FailWithError(AL_fatal, AP_unexpected_message);
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
|
||||
subSigs.Add(sGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey));
|
||||
|
||||
keys.Add(new PgpSecretKey(keyPair, null, subSigs, encAlgorithm, passPhrase, useSha1, rand));
|
||||
keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, subSigs), encAlgorithm, passPhrase, useSha1, rand));
|
||||
}
|
||||
catch (PgpException e)
|
||||
{
|
||||
|
|
|
@ -25,16 +25,6 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
{
|
||||
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>
|
||||
|
@ -43,6 +33,16 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
{
|
||||
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());
|
||||
|
|
|
@ -26,12 +26,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
private int keyStrength;
|
||||
|
||||
internal PublicKeyPacket publicPk;
|
||||
private TrustPacket trustPk;
|
||||
private ArrayList keySigs = new ArrayList();
|
||||
private ArrayList ids = new ArrayList();
|
||||
private ArrayList idTrusts = new ArrayList();
|
||||
private ArrayList idSigs = new ArrayList();
|
||||
private ArrayList subSigs;
|
||||
internal TrustPacket trustPk;
|
||||
internal ArrayList keySigs = new ArrayList();
|
||||
internal ArrayList ids = new ArrayList();
|
||||
internal ArrayList idTrusts = new ArrayList();
|
||||
internal ArrayList idSigs = new ArrayList();
|
||||
internal ArrayList subSigs;
|
||||
|
||||
private void Init()
|
||||
{
|
||||
|
@ -648,32 +648,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
string id,
|
||||
PgpSignature certification)
|
||||
{
|
||||
PgpPublicKey returnKey = new PgpPublicKey(key);
|
||||
ArrayList sigList = null;
|
||||
|
||||
for (int i = 0; i != returnKey.ids.Count; i++)
|
||||
{
|
||||
if (id.Equals(returnKey.ids[i]))
|
||||
{
|
||||
sigList = (ArrayList) returnKey.idSigs[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (sigList != null)
|
||||
{
|
||||
sigList.Add(certification);
|
||||
}
|
||||
else
|
||||
{
|
||||
sigList = new ArrayList();
|
||||
|
||||
sigList.Add(certification);
|
||||
returnKey.ids.Add(id);
|
||||
returnKey.idTrusts.Add(null);
|
||||
returnKey.idSigs.Add(sigList);
|
||||
}
|
||||
|
||||
return returnKey;
|
||||
return AddCert(key, id, certification);
|
||||
}
|
||||
|
||||
/// <summary>Add a certification for the given UserAttributeSubpackets to the given public key.</summary>
|
||||
|
@ -685,13 +660,21 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
PgpPublicKey key,
|
||||
PgpUserAttributeSubpacketVector userAttributes,
|
||||
PgpSignature certification)
|
||||
{
|
||||
return AddCert(key, userAttributes, certification);
|
||||
}
|
||||
|
||||
private static PgpPublicKey AddCert(
|
||||
PgpPublicKey key,
|
||||
object id,
|
||||
PgpSignature certification)
|
||||
{
|
||||
PgpPublicKey returnKey = new PgpPublicKey(key);
|
||||
IList sigList = null;
|
||||
|
||||
for (int i = 0; i != returnKey.ids.Count; i++)
|
||||
{
|
||||
if (userAttributes.Equals(returnKey.ids[i]))
|
||||
if (id.Equals(returnKey.ids[i]))
|
||||
{
|
||||
sigList = (IList) returnKey.idSigs[i];
|
||||
}
|
||||
|
@ -705,7 +688,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
{
|
||||
sigList = new ArrayList();
|
||||
sigList.Add(certification);
|
||||
returnKey.ids.Add(userAttributes);
|
||||
returnKey.ids.Add(id);
|
||||
returnKey.idTrusts.Add(null);
|
||||
returnKey.idSigs.Add(sigList);
|
||||
}
|
||||
|
@ -725,26 +708,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
PgpPublicKey key,
|
||||
PgpUserAttributeSubpacketVector userAttributes)
|
||||
{
|
||||
PgpPublicKey returnKey = new PgpPublicKey(key);
|
||||
bool found = false;
|
||||
|
||||
for (int i = 0; i < returnKey.ids.Count; i++)
|
||||
{
|
||||
if (userAttributes.Equals(returnKey.ids[i]))
|
||||
{
|
||||
found = true;
|
||||
returnKey.ids.RemoveAt(i);
|
||||
returnKey.idTrusts.RemoveAt(i);
|
||||
returnKey.idSigs.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return returnKey;
|
||||
return RemoveCert(key, userAttributes);
|
||||
}
|
||||
|
||||
/// <summary>Remove any certifications associated with a given ID on a key.</summary>
|
||||
|
@ -754,6 +718,13 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
public static PgpPublicKey RemoveCertification(
|
||||
PgpPublicKey key,
|
||||
string id)
|
||||
{
|
||||
return RemoveCert(key, id);
|
||||
}
|
||||
|
||||
private static PgpPublicKey RemoveCert(
|
||||
PgpPublicKey key,
|
||||
object id)
|
||||
{
|
||||
PgpPublicKey returnKey = new PgpPublicKey(key);
|
||||
bool found = false;
|
||||
|
@ -772,7 +743,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
return found ? returnKey : null;
|
||||
}
|
||||
|
||||
/// <summary>Remove any certifications associated with a given ID on a key.</summary>
|
||||
/// <summary>Remove a certification associated with a given ID on a key.</summary>
|
||||
/// <param name="key">The key the certifications are to be removed from.</param>
|
||||
/// <param name="id">The ID that the certfication is to be removed from.</param>
|
||||
/// <param name="certification">The certfication to be removed.</param>
|
||||
|
@ -781,6 +752,27 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
PgpPublicKey key,
|
||||
string id,
|
||||
PgpSignature certification)
|
||||
{
|
||||
return RemoveCert(key, id, certification);
|
||||
}
|
||||
|
||||
/// <summary>Remove a certification associated with a given user attributes on a key.</summary>
|
||||
/// <param name="key">The key the certifications are to be removed from.</param>
|
||||
/// <param name="userAttributes">The user attributes that the certfication is to be removed from.</param>
|
||||
/// <param name="certification">The certification to be removed.</param>
|
||||
/// <returns>The re-certified key, or null if the certification was not found.</returns>
|
||||
public static PgpPublicKey RemoveCertification(
|
||||
PgpPublicKey key,
|
||||
PgpUserAttributeSubpacketVector userAttributes,
|
||||
PgpSignature certification)
|
||||
{
|
||||
return RemoveCert(key, userAttributes, certification);
|
||||
}
|
||||
|
||||
private static PgpPublicKey RemoveCert(
|
||||
PgpPublicKey key,
|
||||
object id,
|
||||
PgpSignature certification)
|
||||
{
|
||||
PgpPublicKey returnKey = new PgpPublicKey(key);
|
||||
bool found = false;
|
||||
|
@ -838,5 +830,61 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
|
||||
return returnKey;
|
||||
}
|
||||
|
||||
/// <summary>Remove a certification from the key.</summary>
|
||||
/// <param name="key">The key the certifications are to be removed from.</param>
|
||||
/// <param name="certification">The certfication to be removed.</param>
|
||||
/// <returns>The modified key, null if the certification was not found.</returns>
|
||||
public static PgpPublicKey RemoveCertification(
|
||||
PgpPublicKey key,
|
||||
PgpSignature certification)
|
||||
{
|
||||
PgpPublicKey returnKey = new PgpPublicKey(key);
|
||||
ArrayList sigs = returnKey.subSigs != null
|
||||
? returnKey.subSigs
|
||||
: returnKey.keySigs;
|
||||
|
||||
// bool found = sigs.Remove(certification);
|
||||
int pos = sigs.IndexOf(certification);
|
||||
bool found = pos >= 0;
|
||||
|
||||
if (found)
|
||||
{
|
||||
sigs.RemoveAt(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (String id in key.GetUserIds())
|
||||
{
|
||||
foreach (object sig in key.GetSignaturesForId(id))
|
||||
{
|
||||
// TODO Is this the right type of equality test?
|
||||
if (certification == sig)
|
||||
{
|
||||
found = true;
|
||||
returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
foreach (PgpUserAttributeSubpacketVector id in key.GetUserAttributes())
|
||||
{
|
||||
foreach (object sig in key.GetSignaturesForUserAttribute(id))
|
||||
{
|
||||
// TODO Is this the right type of equality test?
|
||||
if (certification == sig)
|
||||
{
|
||||
found = true;
|
||||
returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,11 +150,18 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
|
||||
if (!found)
|
||||
{
|
||||
if (pubKey.IsMasterKey && masterFound)
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -11,124 +11,56 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
/// <remarks>General class to handle a PGP secret key object.</remarks>
|
||||
public class PgpSecretKey
|
||||
{
|
||||
private SecretKeyPacket secret;
|
||||
private TrustPacket trust;
|
||||
private ArrayList keySigs;
|
||||
private ArrayList ids;
|
||||
private ArrayList idTrusts;
|
||||
private ArrayList idSigs;
|
||||
private PgpPublicKey pub;
|
||||
private ArrayList subSigs;
|
||||
private readonly SecretKeyPacket secret;
|
||||
private readonly PgpPublicKey pub;
|
||||
|
||||
/// <summary>Copy constructor - master key.</summary>
|
||||
private PgpSecretKey(
|
||||
internal PgpSecretKey(
|
||||
SecretKeyPacket secret,
|
||||
TrustPacket trust,
|
||||
ArrayList keySigs,
|
||||
ArrayList ids,
|
||||
ArrayList idTrusts,
|
||||
ArrayList idSigs,
|
||||
PgpPublicKey pub)
|
||||
{
|
||||
this.secret = secret;
|
||||
this.trust = trust;
|
||||
this.keySigs = keySigs;
|
||||
this.ids = ids;
|
||||
this.idTrusts = idTrusts;
|
||||
this.idSigs = idSigs;
|
||||
this.pub = pub;
|
||||
}
|
||||
|
||||
/// <summary>Copy constructor - subkey.</summary>
|
||||
private PgpSecretKey(
|
||||
SecretKeyPacket secret,
|
||||
TrustPacket trust,
|
||||
ArrayList subSigs,
|
||||
PgpPublicKey pub)
|
||||
{
|
||||
this.secret = secret;
|
||||
this.trust = trust;
|
||||
this.subSigs = subSigs;
|
||||
this.pub = pub;
|
||||
}
|
||||
|
||||
internal PgpSecretKey(
|
||||
SecretKeyPacket secret,
|
||||
TrustPacket trust,
|
||||
ArrayList keySigs,
|
||||
ArrayList ids,
|
||||
ArrayList idTrusts,
|
||||
ArrayList idSigs)
|
||||
{
|
||||
this.secret = secret;
|
||||
this.trust = trust;
|
||||
this.keySigs = keySigs;
|
||||
this.ids = ids;
|
||||
this.idTrusts = idTrusts;
|
||||
this.idSigs = idSigs;
|
||||
this.pub = new PgpPublicKey(secret.PublicKeyPacket, trust, keySigs, ids, idTrusts, idSigs);
|
||||
}
|
||||
|
||||
internal PgpSecretKey(
|
||||
SecretKeyPacket secret,
|
||||
TrustPacket trust,
|
||||
ArrayList subSigs)
|
||||
{
|
||||
this.secret = secret;
|
||||
this.trust = trust;
|
||||
this.subSigs = subSigs;
|
||||
this.pub = new PgpPublicKey(secret.PublicKeyPacket, trust, subSigs);
|
||||
}
|
||||
|
||||
/// <summary>Create a subkey</summary>
|
||||
internal PgpSecretKey(
|
||||
PgpKeyPair keyPair,
|
||||
TrustPacket trust,
|
||||
ArrayList subSigs,
|
||||
PgpPrivateKey privKey,
|
||||
PgpPublicKey pubKey,
|
||||
SymmetricKeyAlgorithmTag encAlgorithm,
|
||||
char[] passPhrase,
|
||||
bool useSHA1,
|
||||
bool useSha1,
|
||||
SecureRandom rand)
|
||||
: this(keyPair, encAlgorithm, passPhrase, useSHA1, rand)
|
||||
: this(privKey, pubKey, encAlgorithm, passPhrase, useSha1, rand, false)
|
||||
{
|
||||
this.secret = new SecretSubkeyPacket(
|
||||
secret.PublicKeyPacket,
|
||||
secret.EncAlgorithm,
|
||||
secret.S2kUsage,
|
||||
secret.S2k,
|
||||
secret.GetIV(),
|
||||
secret.GetSecretKeyData());
|
||||
|
||||
this.trust = trust;
|
||||
this.subSigs = subSigs;
|
||||
this.pub = new PgpPublicKey(keyPair.PublicKey, trust, subSigs);
|
||||
}
|
||||
|
||||
internal PgpSecretKey(
|
||||
PgpKeyPair keyPair,
|
||||
PgpPrivateKey privKey,
|
||||
PgpPublicKey pubKey,
|
||||
SymmetricKeyAlgorithmTag encAlgorithm,
|
||||
char[] passPhrase,
|
||||
bool useSHA1,
|
||||
SecureRandom rand)
|
||||
bool useSha1,
|
||||
SecureRandom rand,
|
||||
bool isMasterKey)
|
||||
{
|
||||
PublicKeyPacket pubPk = keyPair.PublicKey.publicPk;
|
||||
|
||||
BcpgObject secKey;
|
||||
switch (keyPair.PublicKey.Algorithm)
|
||||
|
||||
this.pub = pubKey;
|
||||
|
||||
switch (pubKey.Algorithm)
|
||||
{
|
||||
case PublicKeyAlgorithmTag.RsaEncrypt:
|
||||
case PublicKeyAlgorithmTag.RsaSign:
|
||||
case PublicKeyAlgorithmTag.RsaGeneral:
|
||||
RsaPrivateCrtKeyParameters rsK = (RsaPrivateCrtKeyParameters) keyPair.PrivateKey.Key;
|
||||
RsaPrivateCrtKeyParameters rsK = (RsaPrivateCrtKeyParameters) privKey.Key;
|
||||
secKey = new RsaSecretBcpgKey(rsK.Exponent, rsK.P, rsK.Q);
|
||||
break;
|
||||
case PublicKeyAlgorithmTag.Dsa:
|
||||
DsaPrivateKeyParameters dsK = (DsaPrivateKeyParameters) keyPair.PrivateKey.Key;
|
||||
DsaPrivateKeyParameters dsK = (DsaPrivateKeyParameters) privKey.Key;
|
||||
secKey = new DsaSecretBcpgKey(dsK.X);
|
||||
break;
|
||||
case PublicKeyAlgorithmTag.ElGamalEncrypt:
|
||||
case PublicKeyAlgorithmTag.ElGamalGeneral:
|
||||
ElGamalPrivateKeyParameters esK = (ElGamalPrivateKeyParameters) keyPair.PrivateKey.Key;
|
||||
ElGamalPrivateKeyParameters esK = (ElGamalPrivateKeyParameters) privKey.Key;
|
||||
secKey = new ElGamalSecretBcpgKey(esK.X);
|
||||
break;
|
||||
default:
|
||||
|
@ -143,7 +75,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
pOut.WriteObject(secKey);
|
||||
|
||||
byte[] keyData = bOut.ToArray();
|
||||
byte[] checksumBytes = Checksum(useSHA1, keyData, keyData.Length);
|
||||
byte[] checksumBytes = Checksum(useSha1, keyData, keyData.Length);
|
||||
|
||||
pOut.Write(checksumBytes);
|
||||
|
||||
|
@ -151,7 +83,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
|
||||
if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
|
||||
{
|
||||
this.secret = new SecretKeyPacket(pubPk, encAlgorithm, null, null, bOutData);
|
||||
if (isMasterKey)
|
||||
{
|
||||
this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, null, null, bOutData);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, null, null, bOutData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -159,14 +98,19 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
byte[] iv;
|
||||
byte[] encData = EncryptKeyData(bOutData, encAlgorithm, passPhrase, rand, out s2k, out iv);
|
||||
|
||||
int usage = useSHA1
|
||||
int s2kUsage = useSha1
|
||||
? SecretKeyPacket.UsageSha1
|
||||
: SecretKeyPacket.UsageChecksum;
|
||||
|
||||
this.secret = new SecretKeyPacket(pubPk, encAlgorithm, usage, s2k, iv, encData);
|
||||
if (isMasterKey)
|
||||
{
|
||||
this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
|
||||
}
|
||||
}
|
||||
|
||||
this.trust = null;
|
||||
}
|
||||
catch (PgpException e)
|
||||
{
|
||||
|
@ -174,10 +118,9 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.StackTrace);
|
||||
throw new PgpException("Exception encrypting key", e);
|
||||
}
|
||||
|
||||
this.keySigs = new ArrayList();
|
||||
}
|
||||
|
||||
public PgpSecretKey(
|
||||
|
@ -199,25 +142,30 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
string id,
|
||||
SymmetricKeyAlgorithmTag encAlgorithm,
|
||||
char[] passPhrase,
|
||||
bool useSHA1,
|
||||
bool useSha1,
|
||||
PgpSignatureSubpacketVector hashedPackets,
|
||||
PgpSignatureSubpacketVector unhashedPackets,
|
||||
SecureRandom rand)
|
||||
: this(keyPair, encAlgorithm, passPhrase, useSHA1, rand)
|
||||
: this(keyPair.PrivateKey, certifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets), encAlgorithm, passPhrase, useSha1, rand, true)
|
||||
{
|
||||
}
|
||||
|
||||
private static PgpPublicKey certifiedPublicKey(
|
||||
int certificationLevel,
|
||||
PgpKeyPair keyPair,
|
||||
string id,
|
||||
PgpSignatureSubpacketVector hashedPackets,
|
||||
PgpSignatureSubpacketVector unhashedPackets)
|
||||
{
|
||||
PgpSignatureGenerator sGen;
|
||||
try
|
||||
{
|
||||
this.trust = null;
|
||||
this.ids = new ArrayList();
|
||||
ids.Add(id);
|
||||
|
||||
this.idTrusts = new ArrayList();
|
||||
idTrusts.Add(null);
|
||||
|
||||
this.idSigs = new ArrayList();
|
||||
|
||||
PgpSignatureGenerator sGen = new PgpSignatureGenerator(
|
||||
keyPair.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
|
||||
sGen = new PgpSignatureGenerator(keyPair.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new PgpException("Creating signature generator: " + e.Message, e);
|
||||
}
|
||||
|
||||
//
|
||||
// Generate the certification
|
||||
|
@ -227,20 +175,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
sGen.SetHashedSubpackets(hashedPackets);
|
||||
sGen.SetUnhashedSubpackets(unhashedPackets);
|
||||
|
||||
PgpSignature certification = sGen.GenerateCertification(id, keyPair.PublicKey);
|
||||
this.pub = PgpPublicKey.AddCertification(keyPair.PublicKey, id, certification);
|
||||
|
||||
ArrayList sigList = new ArrayList();
|
||||
sigList.Add(certification);
|
||||
idSigs.Add(sigList);
|
||||
}
|
||||
catch (PgpException e)
|
||||
try
|
||||
{
|
||||
throw e;
|
||||
PgpSignature certification = sGen.GenerateCertification(id, keyPair.PublicKey);
|
||||
return PgpPublicKey.AddCertification(keyPair.PublicKey, id, certification);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new PgpException("Exception encrypting key", e);
|
||||
throw new PgpException("Exception doing certification: " + e.Message, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,11 +213,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
string id,
|
||||
SymmetricKeyAlgorithmTag encAlgorithm,
|
||||
char[] passPhrase,
|
||||
bool useSHA1,
|
||||
bool useSha1,
|
||||
PgpSignatureSubpacketVector hashedPackets,
|
||||
PgpSignatureSubpacketVector unhashedPackets,
|
||||
SecureRandom rand)
|
||||
: this(certificationLevel, new PgpKeyPair(algorithm, pubKey, privKey, time), id, encAlgorithm, passPhrase, useSHA1, hashedPackets, unhashedPackets, rand)
|
||||
: this(certificationLevel, new PgpKeyPair(algorithm, pubKey, privKey, time), id, encAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -310,7 +252,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
/// <summary>True, if this is a master key.</summary>
|
||||
public bool IsMasterKey
|
||||
{
|
||||
get { return subSigs == null; }
|
||||
get { return pub.IsMasterKey; }
|
||||
}
|
||||
|
||||
/// <summary>The algorithm the key is encrypted with.</summary>
|
||||
|
@ -378,8 +320,8 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
|
||||
data = c.DoFinal(encData);
|
||||
|
||||
bool useSHA1 = secret.S2kUsage == SecretKeyPacket.UsageSha1;
|
||||
byte[] check = Checksum(useSHA1, data, (useSHA1) ? data.Length - 20 : data.Length - 2);
|
||||
bool useSha1 = secret.S2kUsage == SecretKeyPacket.UsageSha1;
|
||||
byte[] check = Checksum(useSha1, data, (useSha1) ? data.Length - 20 : data.Length - 2);
|
||||
|
||||
for (int i = 0; i != check.Length; i++)
|
||||
{
|
||||
|
@ -510,11 +452,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
}
|
||||
|
||||
private static byte[] Checksum(
|
||||
bool useSHA1,
|
||||
bool useSha1,
|
||||
byte[] bytes,
|
||||
int length)
|
||||
{
|
||||
if (useSHA1)
|
||||
if (useSha1)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -553,38 +495,38 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr);
|
||||
|
||||
bcpgOut.WritePacket(secret);
|
||||
if (trust != null)
|
||||
if (pub.trustPk != null)
|
||||
{
|
||||
bcpgOut.WritePacket(trust);
|
||||
bcpgOut.WritePacket(pub.trustPk);
|
||||
}
|
||||
|
||||
if (subSigs == null) // is not a sub key
|
||||
if (pub.subSigs == null) // is not a sub key
|
||||
{
|
||||
foreach (PgpSignature keySig in keySigs)
|
||||
foreach (PgpSignature keySig in pub.keySigs)
|
||||
{
|
||||
keySig.Encode(bcpgOut);
|
||||
}
|
||||
|
||||
for (int i = 0; i != ids.Count; i++)
|
||||
for (int i = 0; i != pub.ids.Count; i++)
|
||||
{
|
||||
if (ids[i] is string)
|
||||
object pubID = pub.ids[i];
|
||||
if (pubID is string)
|
||||
{
|
||||
string id = (string) ids[i];
|
||||
|
||||
string id = (string) pubID;
|
||||
bcpgOut.WritePacket(new UserIdPacket(id));
|
||||
}
|
||||
else
|
||||
{
|
||||
PgpUserAttributeSubpacketVector v = (PgpUserAttributeSubpacketVector)ids[i];
|
||||
PgpUserAttributeSubpacketVector v = (PgpUserAttributeSubpacketVector) pubID;
|
||||
bcpgOut.WritePacket(new UserAttributePacket(v.ToSubpacketArray()));
|
||||
}
|
||||
|
||||
if (idTrusts[i] != null)
|
||||
if (pub.idTrusts[i] != null)
|
||||
{
|
||||
bcpgOut.WritePacket((ContainedPacket)idTrusts[i]);
|
||||
bcpgOut.WritePacket((ContainedPacket)pub.idTrusts[i]);
|
||||
}
|
||||
|
||||
foreach (PgpSignature sig in (ArrayList) idSigs[i])
|
||||
foreach (PgpSignature sig in (ArrayList) pub.idSigs[i])
|
||||
{
|
||||
sig.Encode(bcpgOut);
|
||||
}
|
||||
|
@ -592,7 +534,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
}
|
||||
else
|
||||
{
|
||||
foreach (PgpSignature subSig in subSigs)
|
||||
foreach (PgpSignature subSig in pub.subSigs)
|
||||
{
|
||||
subSig.Encode(bcpgOut);
|
||||
}
|
||||
|
@ -671,13 +613,22 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
newEncAlgorithm, s2kUsage, s2k, iv, keyData);
|
||||
}
|
||||
|
||||
if (key.subSigs == null)
|
||||
{
|
||||
return new PgpSecretKey(secret, key.trust, key.keySigs, key.ids,
|
||||
key.idTrusts, key.idSigs, key.pub);
|
||||
return new PgpSecretKey(secret, key.pub);
|
||||
}
|
||||
|
||||
return new PgpSecretKey(secret, key.trust, key.subSigs, key.pub);
|
||||
/// <summary>Replace the passed the public key on the passed in secret key.</summary>
|
||||
/// <param name="secretKey">Secret key to change.</param>
|
||||
/// <param name="publicKey">New public key.</param>
|
||||
/// <returns>A new secret key.</returns>
|
||||
/// <exception cref="ArgumentException">If KeyId's do not match.</exception>
|
||||
public static PgpSecretKey ReplacePublicKey(
|
||||
PgpSecretKey secretKey,
|
||||
PgpPublicKey publicKey)
|
||||
{
|
||||
if (publicKey.KeyId != secretKey.KeyId)
|
||||
throw new ArgumentException("KeyId's do not match");
|
||||
|
||||
return new PgpSecretKey(secretKey.secret, publicKey);
|
||||
}
|
||||
|
||||
private static byte[] EncryptKeyData(
|
||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Collections;
|
||||
using System.IO;
|
||||
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities.Collections;
|
||||
|
||||
namespace Org.BouncyCastle.Bcpg.OpenPgp
|
||||
|
@ -16,12 +17,21 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
public class PgpSecretKeyRing
|
||||
: PgpKeyRing
|
||||
{
|
||||
private readonly ArrayList keys;
|
||||
private readonly IList keys;
|
||||
private readonly IList extraPubKeys;
|
||||
|
||||
internal PgpSecretKeyRing(
|
||||
ArrayList keys)
|
||||
IList keys)
|
||||
: this(keys, new ArrayList())
|
||||
{
|
||||
}
|
||||
|
||||
private PgpSecretKeyRing(
|
||||
IList keys,
|
||||
IList extraPubKeys)
|
||||
{
|
||||
this.keys = keys;
|
||||
this.extraPubKeys = extraPubKeys;
|
||||
}
|
||||
|
||||
public PgpSecretKeyRing(
|
||||
|
@ -34,6 +44,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
Stream inputStream)
|
||||
{
|
||||
this.keys = new ArrayList();
|
||||
this.extraPubKeys = new ArrayList();
|
||||
|
||||
BcpgInputStream bcpgInput = BcpgInputStream.Wrap(inputStream);
|
||||
|
||||
|
@ -62,11 +73,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
ArrayList ids, idTrusts, idSigs;
|
||||
ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs);
|
||||
|
||||
keys.Add(new PgpSecretKey(secret, trust, keySigs, ids, idTrusts, idSigs));
|
||||
keys.Add(new PgpSecretKey(secret, new PgpPublicKey(secret.PublicKeyPacket, trust, keySigs, ids, idTrusts, idSigs)));
|
||||
|
||||
|
||||
// Read subkeys
|
||||
while (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey)
|
||||
while (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey
|
||||
|| bcpgInput.NextPacketTag() == PacketTag.PublicSubkey)
|
||||
{
|
||||
if (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey)
|
||||
{
|
||||
SecretSubkeyPacket sub = (SecretSubkeyPacket) bcpgInput.ReadPacket();
|
||||
|
||||
|
@ -81,7 +95,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
TrustPacket subTrust = ReadOptionalTrustPacket(bcpgInput);
|
||||
ArrayList sigList = ReadSignaturesAndTrust(bcpgInput);
|
||||
|
||||
keys.Add(new PgpSecretKey(sub, subTrust, sigList));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,6 +142,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
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();
|
||||
|
@ -133,10 +168,68 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
if (outStr == null)
|
||||
throw new ArgumentNullException("outStr");
|
||||
|
||||
foreach (PgpSecretKey k in keys)
|
||||
foreach (PgpSecretKey key in keys)
|
||||
{
|
||||
k.Encode(outStr);
|
||||
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>
|
||||
|
@ -171,13 +264,20 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
|
||||
if (!found)
|
||||
{
|
||||
if (secKey.IsMasterKey && masterFound)
|
||||
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);
|
||||
return new PgpSecretKeyRing(keys, secRing.extraPubKeys);
|
||||
}
|
||||
|
||||
/// <summary>Returns a new key ring with the secret key passed in removed from the key ring.</summary>
|
||||
|
@ -202,7 +302,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
}
|
||||
}
|
||||
|
||||
return found ? new PgpSecretKeyRing(keys) : null;
|
||||
return found ? new PgpSecretKeyRing(keys, secRing.extraPubKeys) : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
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;
|
||||
|
|
|
@ -116,6 +116,28 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
|
|||
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)
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace Org.BouncyCastle.Pkcs
|
|||
PrivateKeyInfo keyInfo)
|
||||
{
|
||||
if (!PbeUtilities.IsPbeAlgorithm(algorithm))
|
||||
throw new ArgumentException("attempt to use non-Pbe algorithm with Pbe EncryptedPrivateKeyInfo generation");
|
||||
throw new ArgumentException("attempt to use non-PBE algorithm with PBE EncryptedPrivateKeyInfo generation");
|
||||
|
||||
IBufferedCipher cipher = PbeUtilities.CreateEngine(algorithm) as IBufferedCipher;
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ namespace Org.BouncyCastle.Security
|
|||
switch (mechanism)
|
||||
{
|
||||
case "DH":
|
||||
case "DIFFIEHELLMAN":
|
||||
return new DHBasicAgreement();
|
||||
case "ECDH":
|
||||
return new ECDHBasicAgreement();
|
||||
|
|
|
@ -134,7 +134,8 @@ namespace Org.BouncyCastle.Security
|
|||
//
|
||||
// key pair generators.
|
||||
//
|
||||
AddKpgAlgorithm("DH");
|
||||
AddKpgAlgorithm("DH",
|
||||
"DIFFIEHELLMAN");
|
||||
AddKpgAlgorithm("DSA");
|
||||
AddKpgAlgorithm("EC");
|
||||
AddKpgAlgorithm("ECDH",
|
||||
|
|
|
@ -15,6 +15,7 @@ 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
|
||||
{
|
||||
|
@ -177,5 +178,33 @@ namespace Org.BouncyCastle.Security
|
|||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace Org.BouncyCastle.X509
|
|||
|
||||
while ((line = ReadLine(inStream)) != null)
|
||||
{
|
||||
if (line.Equals(_header1) || line.Equals(_header2))
|
||||
if (line.StartsWith(_header1) || line.StartsWith(_header2))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ namespace Org.BouncyCastle.X509
|
|||
|
||||
while ((line = ReadLine(inStream)) != null)
|
||||
{
|
||||
if (line.Equals(_footer1) || line.Equals(_footer2))
|
||||
if (line.StartsWith(_footer1) || line.StartsWith(_footer2))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -212,7 +212,7 @@ namespace Org.BouncyCastle.X509.Store
|
|||
}
|
||||
}
|
||||
|
||||
if (issuer != null && !issuer.Equivalent(c.IssuerDN))
|
||||
if (issuer != null && !issuer.Equivalent(c.IssuerDN, true))
|
||||
return false;
|
||||
|
||||
if (keyUsage != null)
|
||||
|
@ -277,7 +277,7 @@ namespace Org.BouncyCastle.X509.Store
|
|||
if (serialNumber != null && !serialNumber.Equals(c.SerialNumber))
|
||||
return false;
|
||||
|
||||
if (subject != null && !subject.Equivalent(c.SubjectDN))
|
||||
if (subject != null && !subject.Equivalent(c.SubjectDN, true))
|
||||
return false;
|
||||
|
||||
if (!MatchExtension(subjectKeyIdentifier, c, X509Extensions.SubjectKeyIdentifier))
|
||||
|
@ -297,7 +297,7 @@ namespace Org.BouncyCastle.X509.Store
|
|||
X509Name a,
|
||||
X509Name b)
|
||||
{
|
||||
return a == null ? b == null : a.Equivalent(b);
|
||||
return a == null ? b == null : a.Equivalent(b, true);
|
||||
}
|
||||
|
||||
private static bool[] CopyBoolArray(
|
||||
|
@ -331,7 +331,7 @@ namespace Org.BouncyCastle.X509.Store
|
|||
if (extVal == null)
|
||||
return false;
|
||||
|
||||
return extVal != null && Arrays.AreEqual(b, extVal.GetEncoded());
|
||||
return Arrays.AreEqual(b, extVal.GetOctets());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -207,7 +207,7 @@ namespace Org.BouncyCastle.X509.Store
|
|||
|
||||
foreach (X509Name issuer in issuers)
|
||||
{
|
||||
if (issuer.Equivalent(i))
|
||||
if (issuer.Equivalent(i, true))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Org.BouncyCastle.X509.Store
|
||||
|
@ -21,24 +22,40 @@ namespace Org.BouncyCastle.X509.Store
|
|||
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":
|
||||
case "CERTIFICATE":
|
||||
case "CERTIFICATEPAIR":
|
||||
case "CRL":
|
||||
{
|
||||
if (parts[1] == "COLLECTION")
|
||||
{
|
||||
X509CollectionStoreParameters p = (X509CollectionStoreParameters) parameters;
|
||||
return new X509CollectionStore(p.GetCollection());
|
||||
}
|
||||
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.");
|
||||
}
|
||||
|
||||
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