BouncyCastle update.

git-svn-id: svn://svn.code.sf.net/p/itextsharp/code/trunk@18 820d3149-562b-4f88-9aa4-a8e61a3485cf
master
psoares33 2008-12-17 11:23:50 +00:00
parent c12d0aa854
commit f00f5ff42a
73 changed files with 16345 additions and 15168 deletions

View File

@ -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"

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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
}
}

View File

@ -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);

View File

@ -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;

View File

@ -13,8 +13,7 @@ namespace Org.BouncyCastle.Asn1.Esf
/// </code>
/// </remarks>
public class SignaturePolicyIdentifier
: Asn1Encodable
//, Asn1Choice
: Asn1Encodable, IAsn1Choice
{
private readonly SignaturePolicyId sigPolicy;

View File

@ -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);
}
}
}

View File

@ -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
* }

View File

@ -38,8 +38,7 @@ namespace Org.BouncyCastle.Asn1.IsisMtt.Ocsp
* </pre>
*/
public class RequestedCertificate
: Asn1Encodable
//, ASN1Choice
: Asn1Encodable, IAsn1Choice
{
public enum Choice
{

View File

@ -22,8 +22,7 @@ namespace Org.BouncyCastle.Asn1.IsisMtt.X509
* of a specific country.
*/
public class DeclarationOfMajority
: Asn1Encodable
//, ASN1Choice
: Asn1Encodable, IAsn1Choice
{
public enum Choice
{

View File

@ -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;

View File

@ -6,7 +6,7 @@ using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Asn1.Ocsp
{
public class ResponderID
: Asn1Encodable
: Asn1Encodable, IAsn1Choice
{
private readonly Asn1Encodable id;

View File

@ -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));
}

View File

@ -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 } //

View File

@ -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

View File

@ -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];
}
}

View File

@ -3,8 +3,7 @@ using System;
namespace Org.BouncyCastle.Asn1.X500
{
public class DirectoryString
: Asn1Encodable, IAsn1String
//, Asn1Choice
: Asn1Encodable, IAsn1Choice, IAsn1String
{
private readonly DerStringBase str;

View File

@ -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 + ")";
}
}
}

View File

@ -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;

View File

@ -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();
}
}
}

View File

@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Asn1.X509
* @see PolicyInformation
*/
public class DisplayText
: Asn1Encodable
: Asn1Encodable, IAsn1Choice
{
/**
* Constant corresponding to ia5String encoding.

View File

@ -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(

View File

@ -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

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -19,8 +19,7 @@ namespace Org.BouncyCastle.Asn1.X509
* according to RFC 3281.</p>
*/
public class Target
: Asn1Encodable
//, ASN1Choice
: Asn1Encodable, IAsn1Choice
{
public enum Choice
{

View File

@ -3,7 +3,7 @@ using System;
namespace Org.BouncyCastle.Asn1.X509
{
public class Time
: Asn1Encodable
: Asn1Encodable, IAsn1Choice
{
internal Asn1Object time;

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -3,7 +3,7 @@ using Org.BouncyCastle.Asn1;
namespace Org.BouncyCastle.Asn1.X9
{
public class X962Parameters
: Asn1Encodable
: Asn1Encodable, IAsn1Choice
{
private readonly Asn1Object _params;

View File

@ -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));
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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
}
}

View File

@ -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)
{
}
}
}

View File

@ -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;
}
}
}

View File

@ -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; }
}
}
}

View File

@ -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; }

View File

@ -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(

View File

@ -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();
}
}
}

View File

@ -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.
//

View File

@ -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)
{

View File

@ -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)
{

View File

@ -39,10 +39,7 @@ namespace Org.BouncyCastle.Cms
*/
public virtual AlgorithmIdentifier KeyDerivationAlgorithm
{
get
{
return _info.KeyDerivationAlgorithm;
}
get { return _info.KeyDerivationAlgorithm; }
}
/**

View File

@ -52,7 +52,7 @@ namespace Org.BouncyCastle.Cms
{
Asn1OctetString octs = Asn1OctetString.GetInstance(s.ID);
sid.SubjectKeyIdentifier = octs.GetOctets();
sid.SubjectKeyIdentifier = octs.GetEncoded();
}
else
{

View File

@ -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;
}

View File

@ -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)

View File

@ -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()
{
}
}
}

View File

@ -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();
}
}
}

View File

@ -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.
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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)
{

View File

@ -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);
}

View File

@ -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)
{

View File

@ -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());

View File

@ -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;
}
}
}

View File

@ -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);
}

View File

@ -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(

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -49,6 +49,7 @@ namespace Org.BouncyCastle.Security
switch (mechanism)
{
case "DH":
case "DIFFIEHELLMAN":
return new DHBasicAgreement();
case "ECDH":
return new ECDHBasicAgreement();

View File

@ -134,7 +134,8 @@ namespace Org.BouncyCastle.Security
//
// key pair generators.
//
AddKpgAlgorithm("DH");
AddKpgAlgorithm("DH",
"DIFFIEHELLMAN");
AddKpgAlgorithm("DSA");
AddKpgAlgorithm("EC");
AddKpgAlgorithm("ECDH",

View File

@ -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));
}
}
}

View File

@ -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;
}

View File

@ -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());
}
}
}

View File

@ -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;

View File

@ -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);
}
}
}
}