BouncyCastle update.

git-svn-id: svn://svn.code.sf.net/p/itextsharp/code/trunk@19 820d3149-562b-4f88-9aa4-a8e61a3485cf
master
psoares33 2009-04-03 17:34:37 +00:00
parent f00f5ff42a
commit 9e5c88451d
85 changed files with 16254 additions and 4487 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
<VisualStudioProject>
<CSHARP
ProjectType = "Local"
ProductVersion = "7.10.6030"
ProductVersion = "7.10.3077"
SchemaVersion = "2.0"
ProjectGuid = "{84C4FDD9-3ED7-453B-B9DA-B3ED52CB071C}"
>
@ -2282,6 +2282,16 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\asn1\BerApplicationSpecific.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\asn1\BerApplicationSpecificParser.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\asn1\BERGenerator.cs"
SubType = "Code"
@ -2517,6 +2527,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\asn1\IAsn1ApplicationSpecificParser.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\asn1\IAsn1Choice.cs"
SubType = "Code"
@ -2592,6 +2607,16 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\asn1\cms\AuthenticatedData.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\asn1\cms\AuthenticatedDataParser.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\asn1\cms\CMSAttributes.cs"
SubType = "Code"
@ -2787,6 +2812,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\asn1\eac\EACObjectIdentifiers.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\asn1\esf\CertificateValues.cs"
SubType = "Code"
@ -4607,6 +4637,26 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\crypto\agreement\srp\SRP6Client.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\crypto\agreement\srp\SRP6Server.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\crypto\agreement\srp\SRP6Utilities.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\crypto\agreement\srp\SRP6VerifierGenerator.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\crypto\digests\GeneralDigest.cs"
SubType = "Code"
@ -5082,6 +5132,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\crypto\io\SignerStream.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\crypto\macs\CBCBlockCipherMac.cs"
SubType = "Code"
@ -5522,6 +5577,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\crypto\signers\GenericSigner.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\crypto\signers\GOST3410DigestSigner.cs"
SubType = "Code"
@ -5597,6 +5657,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\crypto\tls\TlsDssSigner.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\crypto\tls\TlsException.cs"
SubType = "Code"
@ -5627,6 +5692,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\crypto\tls\TlsRsaSigner.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\crypto\tls\TlsUtilities.cs"
SubType = "Code"
@ -6002,11 +6072,21 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\openssl\EncryptionException.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\openssl\IPasswordFinder.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\openssl\PasswordException.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\openssl\PEMReader.cs"
SubType = "Code"
@ -6062,6 +6142,116 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\CertStatus.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixAttrCertChecker.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixAttrCertPathBuilder.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixAttrCertPathValidator.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixBuilderParameters.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixCertPath.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixCertPathBuilder.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixCertPathBuilderException.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixCertPathBuilderResult.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixCertPathChecker.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixCertPathValidator.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixCertPathValidatorException.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixCertPathValidatorResult.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixCertPathValidatorUtilities.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixNameConstraintValidator.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixNameConstraintValidatorException.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixParameters.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\PkixPolicyNode.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\ReasonsMask.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\Rfc3280CertPathUtilities.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\Rfc3281CertPathUtilities.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\pkix\TrustAnchor.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "srcbc\security\AgreementUtilities.cs"
SubType = "Code"

View File

@ -59,8 +59,16 @@ namespace Org.BouncyCastle.Asn1
IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in);
if ((tag & Asn1Tags.Application) != 0)
{
Asn1StreamParser sp2 = new Asn1StreamParser(indIn);
return new BerApplicationSpecificParser(tagNo, sp2);
}
if ((tag & Asn1Tags.Tagged) != 0)
{
// TODO Investigate passing an Asn1StreamParser into this constructor
return new BerTaggedObjectParser(tag, tagNo, indIn);
}

View File

@ -111,8 +111,16 @@ namespace Org.BouncyCastle.Asn1
IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this);
if ((tag & Asn1Tags.Application) != 0)
{
Asn1StreamParser sp2 = new Asn1StreamParser(indIn);
return new BerApplicationSpecificParser(tagNo, sp2).ToAsn1Object();
}
if ((tag & Asn1Tags.Tagged) != 0)
{
// TODO Investigate passing an Asn1StreamParser into this constructor
return new BerTaggedObjectParser(tag, tagNo, indIn).ToAsn1Object();
}

View File

@ -0,0 +1,15 @@
using System;
namespace Org.BouncyCastle.Asn1
{
public class BerApplicationSpecific
: DerApplicationSpecific
{
public BerApplicationSpecific(
int tagNo,
Asn1EncodableVector vec)
: base(tagNo, vec)
{
}
}
}

View File

@ -0,0 +1,29 @@
using System;
namespace Org.BouncyCastle.Asn1
{
public class BerApplicationSpecificParser
: IAsn1ApplicationSpecificParser
{
private readonly int tag;
private readonly Asn1StreamParser parser;
internal BerApplicationSpecificParser(
int tag,
Asn1StreamParser parser)
{
this.tag = tag;
this.parser = parser;
}
public IAsn1Convertible ReadObject()
{
return parser.ReadObject();
}
public Asn1Object ToAsn1Object()
{
return new BerApplicationSpecific(tag, parser.ReadVector());
}
}
}

View File

@ -44,9 +44,6 @@ namespace Org.BouncyCastle.Asn1
int tag,
Asn1Encodable obj)
{
if (tag >= 0x1f)
throw new IOException("unsupported tag number");
byte[] data = obj.GetDerEncoded();
this.isConstructed = isExplicit;
@ -65,6 +62,29 @@ namespace Org.BouncyCastle.Asn1
}
}
public DerApplicationSpecific(
int tagNo,
Asn1EncodableVector vec)
{
this.tag = tagNo;
this.isConstructed = true;
MemoryStream bOut = new MemoryStream();
for (int i = 0; i != vec.Count; i++)
{
try
{
byte[] bs = vec[i].GetEncoded();
bOut.Write(bs, 0, bs.Length);
}
catch (IOException e)
{
throw new InvalidOperationException("malformed object", e);
}
}
this.octets = bOut.ToArray();
}
private int GetLengthOfLength(
byte[] data)
{
@ -93,6 +113,12 @@ namespace Org.BouncyCastle.Asn1
get { return tag; }
}
/**
* Return the enclosed object assuming explicit tagging.
*
* @return the resulting object
* @throws IOException if reconstruction fails.
*/
public Asn1Object GetObject()
{
return FromByteArray(GetContents());
@ -108,11 +134,16 @@ namespace Org.BouncyCastle.Asn1
public Asn1Object GetObject(
int derTagNo)
{
if (tag >= 0x1f)
if (derTagNo >= 0x1f)
throw new IOException("unsupported tag number");
byte[] tmp = this.GetEncoded();
tmp[0] = (byte) derTagNo;
byte[] orig = this.GetEncoded();
byte[] tmp = ReplaceTagNumber(derTagNo, orig);
if ((orig[0] & Asn1Tags.Constructed) != 0)
{
tmp[0] |= Asn1Tags.Constructed;
}
return FromByteArray(tmp);;
}
@ -146,5 +177,46 @@ namespace Org.BouncyCastle.Asn1
{
return isConstructed.GetHashCode() ^ tag.GetHashCode() ^ Arrays.GetHashCode(octets);
}
private byte[] ReplaceTagNumber(
int newTag,
byte[] input)
{
int tagNo = input[0] & 0x1f;
int index = 1;
//
// with tagged object tag number is bottom 5 bits, or stored at the start of the content
//
if (tagNo == 0x1f)
{
tagNo = 0;
int b = input[index++] & 0xff;
// X.690-0207 8.1.2.4.2
// "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
if ((b & 0x7f) == 0) // Note: -1 will pass
{
throw new InvalidOperationException("corrupted stream - invalid high tag number found");
}
while ((b >= 0) && ((b & 0x80) != 0))
{
tagNo |= (b & 0x7f);
tagNo <<= 7;
b = input[index++] & 0xff;
}
tagNo |= (b & 0x7f);
}
byte[] tmp = new byte[input.Length - index + 1];
Array.Copy(input, index, tmp, 1, tmp.Length - 1);
tmp[0] = (byte)newTag;
return tmp;
}
}
}

View File

@ -0,0 +1,10 @@
using System;
namespace Org.BouncyCastle.Asn1
{
public interface IAsn1ApplicationSpecificParser
: IAsn1Convertible
{
IAsn1Convertible ReadObject();
}
}

View File

@ -0,0 +1,273 @@
using System;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Asn1.Cms
{
public class AuthenticatedData
: Asn1Encodable
{
private DerInteger version;
private OriginatorInfo originatorInfo;
private Asn1Set recipientInfos;
private AlgorithmIdentifier macAlgorithm;
private AlgorithmIdentifier digestAlgorithm;
private ContentInfo encapsulatedContentInfo;
private Asn1Set authAttrs;
private Asn1OctetString mac;
private Asn1Set unauthAttrs;
public AuthenticatedData(
OriginatorInfo originatorInfo,
Asn1Set recipientInfos,
AlgorithmIdentifier macAlgorithm,
AlgorithmIdentifier digestAlgorithm,
ContentInfo encapsulatedContent,
Asn1Set authAttrs,
Asn1OctetString mac,
Asn1Set unauthAttrs)
{
if (digestAlgorithm != null || authAttrs != null)
{
if (digestAlgorithm == null || authAttrs == null)
{
throw new ArgumentException("digestAlgorithm and authAttrs must be set together");
}
}
version = new DerInteger(calculateVersion(originatorInfo));
this.originatorInfo = originatorInfo;
this.macAlgorithm = macAlgorithm;
this.digestAlgorithm = digestAlgorithm;
this.recipientInfos = recipientInfos;
this.encapsulatedContentInfo = encapsulatedContent;
this.authAttrs = authAttrs;
this.mac = mac;
this.unauthAttrs = unauthAttrs;
}
private AuthenticatedData(
Asn1Sequence seq)
{
int index = 0;
version = (DerInteger)seq[index++];
Asn1Encodable tmp = seq[index++];
if (tmp is Asn1TaggedObject)
{
originatorInfo = OriginatorInfo.GetInstance((Asn1TaggedObject)tmp, false);
tmp = seq[index++];
}
recipientInfos = Asn1Set.GetInstance(tmp);
macAlgorithm = AlgorithmIdentifier.GetInstance(seq[index++]);
tmp = seq[index++];
if (tmp is Asn1TaggedObject)
{
digestAlgorithm = AlgorithmIdentifier.GetInstance((Asn1TaggedObject)tmp, false);
tmp = seq[index++];
}
encapsulatedContentInfo = ContentInfo.GetInstance(tmp);
tmp = seq[index++];
if (tmp is Asn1TaggedObject)
{
authAttrs = Asn1Set.GetInstance((Asn1TaggedObject)tmp, false);
tmp = seq[index++];
}
mac = Asn1OctetString.GetInstance(tmp);
if (seq.Count > index)
{
unauthAttrs = Asn1Set.GetInstance((Asn1TaggedObject)seq[index], false);
}
}
/**
* return an AuthenticatedData object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
* tagged false otherwise.
* @throws IllegalArgumentException if the object held by the
* tagged object cannot be converted.
*/
public static AuthenticatedData GetInstance(
Asn1TaggedObject obj,
bool explicitly)
{
return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
}
/**
* return an AuthenticatedData object from the given object.
*
* @param obj the object we want converted.
* @throws IllegalArgumentException if the object cannot be converted.
*/
public static AuthenticatedData GetInstance(
Object obj)
{
if (obj == null || obj is AuthenticatedData)
{
return (AuthenticatedData)obj;
}
if (obj is Asn1Sequence)
{
return new AuthenticatedData((Asn1Sequence)obj);
}
throw new ArgumentException("Invalid AuthenticatedData: " + obj.GetType().Name);
}
public DerInteger Version
{
get { return version; }
}
public OriginatorInfo GetOriginatorInfo()
{
return originatorInfo;
}
public Asn1Set GetRecipientInfos()
{
return recipientInfos;
}
public AlgorithmIdentifier GetMacAlgorithm()
{
return macAlgorithm;
}
public ContentInfo GetEncapsulatedContentInfo()
{
return encapsulatedContentInfo;
}
public Asn1Set GetAuthAttrs()
{
return authAttrs;
}
public Asn1OctetString GetMac()
{
return mac;
}
public Asn1Set GetUnauthAttrs()
{
return unauthAttrs;
}
/**
* Produce an object suitable for an ASN1OutputStream.
* <pre>
* AuthenticatedData ::= SEQUENCE {
* version CMSVersion,
* originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
* recipientInfos RecipientInfos,
* macAlgorithm MessageAuthenticationCodeAlgorithm,
* digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
* encapContentInfo EncapsulatedContentInfo,
* authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
* mac MessageAuthenticationCode,
* unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
*
* AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
*
* UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
*
* MessageAuthenticationCode ::= OCTET STRING
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
Asn1EncodableVector v = new Asn1EncodableVector(version);
if (originatorInfo != null)
{
v.Add(new DerTaggedObject(false, 0, originatorInfo));
}
v.Add(recipientInfos);
v.Add(macAlgorithm);
if (digestAlgorithm != null)
{
v.Add(new DerTaggedObject(false, 1, digestAlgorithm));
}
v.Add(encapsulatedContentInfo);
if (authAttrs != null)
{
v.Add(new DerTaggedObject(false, 2, authAttrs));
}
v.Add(mac);
if (unauthAttrs != null)
{
v.Add(new DerTaggedObject(false, 3, unauthAttrs));
}
return new BerSequence(v);
}
public static int calculateVersion(OriginatorInfo origInfo)
{
if (origInfo == null)
{
return 0;
}
else
{
int ver = 0;
foreach (object obj in origInfo.Certificates)
{
if (obj is Asn1TaggedObject)
{
Asn1TaggedObject tag = (Asn1TaggedObject)obj;
if (tag.TagNo == 2)
{
ver = 1;
}
else if (tag.TagNo == 3)
{
ver = 3;
break;
}
}
}
foreach (object obj in origInfo.Crls)
{
if (obj is Asn1TaggedObject)
{
Asn1TaggedObject tag = (Asn1TaggedObject)obj;
if (tag.TagNo == 1)
{
ver = 3;
break;
}
}
}
return ver;
}
}
}
}

View File

@ -0,0 +1,164 @@
using System;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Asn1.Cms
{
/**
* Produce an object suitable for an ASN1OutputStream.
* <pre>
* AuthenticatedData ::= SEQUENCE {
* version CMSVersion,
* originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
* recipientInfos RecipientInfos,
* macAlgorithm MessageAuthenticationCodeAlgorithm,
* digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
* encapContentInfo EncapsulatedContentInfo,
* authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
* mac MessageAuthenticationCode,
* unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
*
* AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
*
* UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
*
* MessageAuthenticationCode ::= OCTET STRING
* </pre>
*/
public class AuthenticatedDataParser
{
private Asn1SequenceParser seq;
private DerInteger version;
private IAsn1Convertible nextObject;
private bool originatorInfoCalled;
public AuthenticatedDataParser(
Asn1SequenceParser seq)
{
this.seq = seq;
this.version = (DerInteger)seq.ReadObject();
}
public DerInteger Version
{
get { return version; }
}
public OriginatorInfo GetOriginatorInfo()
{
originatorInfoCalled = true;
if (nextObject == null)
{
nextObject = seq.ReadObject();
}
if (nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)nextObject).TagNo == 0)
{
Asn1SequenceParser originatorInfo = (Asn1SequenceParser) ((Asn1TaggedObjectParser)nextObject).GetObjectParser(Asn1Tags.Sequence, false);
nextObject = null;
return OriginatorInfo.GetInstance(originatorInfo.ToAsn1Object());
}
return null;
}
public Asn1SetParser GetRecipientInfos()
{
if (!originatorInfoCalled)
{
GetOriginatorInfo();
}
if (nextObject == null)
{
nextObject = seq.ReadObject();
}
Asn1SetParser recipientInfos = (Asn1SetParser)nextObject;
nextObject = null;
return recipientInfos;
}
public AlgorithmIdentifier GetMacAlgorithm()
{
if (nextObject == null)
{
nextObject = seq.ReadObject();
}
if (nextObject != null)
{
Asn1SequenceParser o = (Asn1SequenceParser)nextObject;
nextObject = null;
return AlgorithmIdentifier.GetInstance(o.ToAsn1Object());
}
return null;
}
public ContentInfoParser GetEnapsulatedContentInfo()
{
if (nextObject == null)
{
nextObject = seq.ReadObject();
}
if (nextObject != null)
{
Asn1SequenceParser o = (Asn1SequenceParser)nextObject;
nextObject = null;
return new ContentInfoParser(o);
}
return null;
}
public Asn1SetParser GetAuthAttrs()
{
if (nextObject == null)
{
nextObject = seq.ReadObject();
}
if (nextObject is Asn1TaggedObjectParser)
{
IAsn1Convertible o = nextObject;
nextObject = null;
return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false);
}
return null;
}
public Asn1OctetString GetMac()
{
if (nextObject == null)
{
nextObject = seq.ReadObject();
}
IAsn1Convertible o = nextObject;
nextObject = null;
return Asn1OctetString.GetInstance(o.ToAsn1Object());
}
public Asn1SetParser GetUnauthAttrs()
{
if (nextObject == null)
{
nextObject = seq.ReadObject();
}
if (nextObject != null)
{
IAsn1Convertible o = nextObject;
nextObject = null;
return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false);
}
return null;
}
}
}

View File

@ -0,0 +1,48 @@
using System;
using Org.BouncyCastle.Asn1;
namespace Org.BouncyCastle.Asn1.Eac
{
public abstract class EacObjectIdentifiers
{
// bsi-de OBJECT IDENTIFIER ::= {
// itu-t(0) identified-organization(4) etsi(0)
// reserved(127) etsi-identified-organization(0) 7
// }
public static readonly DerObjectIdentifier bsi_de = new DerObjectIdentifier("0.4.0.127.0.7");
// id-PK OBJECT IDENTIFIER ::= {
// bsi-de protocols(2) smartcard(2) 1
// }
public static readonly DerObjectIdentifier id_PK = new DerObjectIdentifier(bsi_de + ".2.2.1");
public static readonly DerObjectIdentifier id_PK_DH = new DerObjectIdentifier(id_PK + ".1");
public static readonly DerObjectIdentifier id_PK_ECDH = new DerObjectIdentifier(id_PK + ".2");
// id-CA OBJECT IDENTIFIER ::= {
// bsi-de protocols(2) smartcard(2) 3
// }
public static readonly DerObjectIdentifier id_CA = new DerObjectIdentifier(bsi_de + ".2.2.3");
public static readonly DerObjectIdentifier id_CA_DH = new DerObjectIdentifier(id_CA + ".1");
public static readonly DerObjectIdentifier id_CA_DH_3DES_CBC_CBC = new DerObjectIdentifier(id_CA_DH + ".1");
public static readonly DerObjectIdentifier id_CA_ECDH = new DerObjectIdentifier(id_CA + ".2");
public static readonly DerObjectIdentifier id_CA_ECDH_3DES_CBC_CBC = new DerObjectIdentifier(id_CA_ECDH + ".1");
//
// id-TA OBJECT IDENTIFIER ::= {
// bsi-de protocols(2) smartcard(2) 2
// }
public static readonly DerObjectIdentifier id_TA = new DerObjectIdentifier(bsi_de + ".2.2.2");
public static readonly DerObjectIdentifier id_TA_RSA = new DerObjectIdentifier(id_TA + ".1");
public static readonly DerObjectIdentifier id_TA_RSA_v1_5_SHA_1 = new DerObjectIdentifier(id_TA_RSA + ".1");
public static readonly DerObjectIdentifier id_TA_RSA_v1_5_SHA_256 = new DerObjectIdentifier(id_TA_RSA + ".2");
public static readonly DerObjectIdentifier id_TA_RSA_PSS_SHA_1 = new DerObjectIdentifier(id_TA_RSA + ".3");
public static readonly DerObjectIdentifier id_TA_RSA_PSS_SHA_256 = new DerObjectIdentifier(id_TA_RSA + ".4");
public static readonly DerObjectIdentifier id_TA_ECDSA = new DerObjectIdentifier(id_TA + ".2");
public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_1 = new DerObjectIdentifier(id_TA_ECDSA + ".1");
public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_224 = new DerObjectIdentifier(id_TA_ECDSA + ".2");
public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_256 = new DerObjectIdentifier(id_TA_ECDSA + ".3");
}
}

View File

@ -37,9 +37,10 @@ namespace Org.BouncyCastle.Asn1.Nist
DefineCurve("B-233", SecObjectIdentifiers.SecT233r1);
DefineCurve("B-163", SecObjectIdentifiers.SecT163r2);
DefineCurve("P-521", SecObjectIdentifiers.SecP521r1);
DefineCurve("P-384", SecObjectIdentifiers.SecP384r1);
DefineCurve("P-256", SecObjectIdentifiers.SecP256r1);
DefineCurve("P-224", SecObjectIdentifiers.SecP224r1);
DefineCurve("P-384", SecObjectIdentifiers.SecP384r1);
DefineCurve("P-192", SecObjectIdentifiers.SecP192r1);
}
public static X9ECParameters GetByName(

View File

@ -151,6 +151,7 @@ namespace Org.BouncyCastle.Asn1.Pkcs
//
public const string IdCT = "1.2.840.113549.1.9.16.1";
public static readonly DerObjectIdentifier IdCTAuthData = new DerObjectIdentifier(IdCT + ".2");
public static readonly DerObjectIdentifier IdCTTstInfo = new DerObjectIdentifier(IdCT + ".4");
public static readonly DerObjectIdentifier IdCTCompressedData = new DerObjectIdentifier(IdCT + ".9");

View File

@ -1,5 +1,6 @@
using System;
using System.Collections;
using System.IO;
using System.Text;
using Org.BouncyCastle.Utilities;
@ -16,6 +17,7 @@ namespace Org.BouncyCastle.Asn1.Utilities
}
private const string Tab = " ";
private const int SampleSize = 32;
/**
* dump a Der object as a formatted string with indentation
@ -24,6 +26,7 @@ namespace Org.BouncyCastle.Asn1.Utilities
*/
private static string AsString(
string indent,
bool verbose,
Asn1Object obj)
{
if (obj is Asn1Sequence)
@ -57,7 +60,7 @@ namespace Org.BouncyCastle.Asn1.Utilities
}
else
{
buf.Append(AsString(tab, o.ToAsn1Object()));
buf.Append(AsString(tab, verbose, o.ToAsn1Object()));
}
}
return buf.ToString();
@ -97,7 +100,7 @@ namespace Org.BouncyCastle.Asn1.Utilities
}
else
{
buf.Append(AsString(tab, o.GetObject()));
buf.Append(AsString(tab, verbose, o.GetObject()));
}
return buf.ToString();
@ -121,7 +124,7 @@ namespace Org.BouncyCastle.Asn1.Utilities
}
else
{
buf.Append(AsString(tab, o.ToAsn1Object()));
buf.Append(AsString(tab, verbose, o.ToAsn1Object()));
}
}
@ -146,7 +149,7 @@ namespace Org.BouncyCastle.Asn1.Utilities
}
else
{
buf.Append(AsString(tab, o.ToAsn1Object()));
buf.Append(AsString(tab, verbose, o.ToAsn1Object()));
}
}
@ -166,15 +169,22 @@ namespace Org.BouncyCastle.Asn1.Utilities
}
else if (obj is BerOctetString)
{
return indent + "BER Octet String" + "[" + ((Asn1OctetString)obj).GetOctets().Length + "] " + NewLine;
byte[] octets = ((Asn1OctetString)obj).GetOctets();
string extra = verbose ? dumpBinaryDataAsString(indent, octets) : "";
return indent + "BER Octet String" + "[" + octets.Length + "] " + extra + NewLine;
}
else if (obj is DerOctetString)
{
return indent + "DER Octet String" + "[" + ((Asn1OctetString)obj).GetOctets().Length + "] " + NewLine;
byte[] octets = ((Asn1OctetString)obj).GetOctets();
string extra = verbose ? dumpBinaryDataAsString(indent, octets) : "";
return indent + "DER Octet String" + "[" + octets.Length + "] " + extra + NewLine;
}
else if (obj is DerBitString)
{
return indent + "DER Bit String" + "[" + ((DerBitString)obj).GetBytes().Length + ", " + ((DerBitString)obj).PadBits + "] " + NewLine;
DerBitString bt = (DerBitString)obj;
byte[] bytes = bt.GetBytes();
string extra = verbose ? dumpBinaryDataAsString(indent, bytes) : "";
return indent + "DER Bit String" + "[" + bytes.Length + ", " + bt.PadBits + "] " + extra + NewLine;
}
else if (obj is DerIA5String)
{
@ -214,37 +224,138 @@ namespace Org.BouncyCastle.Asn1.Utilities
return indent + "Unknown " + ((int)((DerUnknownTag)obj).Tag).ToString("X") + " "
+ Encoding.ASCII.GetString(hex, 0, hex.Length) + NewLine;
}
else if (obj is BerApplicationSpecific)
{
return outputApplicationSpecific("BER", indent, verbose, (BerApplicationSpecific)obj);
}
else if (obj is DerApplicationSpecific)
{
return outputApplicationSpecific("DER", indent, verbose, (DerApplicationSpecific)obj);
}
else
{
return indent + obj.ToString() + NewLine;
}
}
private static string outputApplicationSpecific(
string type,
string indent,
bool verbose,
DerApplicationSpecific app)
{
StringBuilder buf = new StringBuilder();
if (app.IsConstructed())
{
try
{
Asn1Sequence s = Asn1Sequence.GetInstance(app.GetObject(Asn1Tags.Sequence));
buf.Append(indent + type + " ApplicationSpecific[" + app.ApplicationTag + "]" + NewLine);
foreach (Asn1Encodable ae in s)
{
buf.Append(AsString(indent + Tab, verbose, ae.ToAsn1Object()));
}
}
catch (IOException e)
{
buf.Append(e);
}
return buf.ToString();
}
return indent + type + " ApplicationSpecific[" + app.ApplicationTag + "] ("
+ Encoding.ASCII.GetString(Hex.Encode(app.GetContents())) + ")" + NewLine;
}
[Obsolete("Use version accepting Asn1Encodable")]
public static string DumpAsString(
object obj)
{
if (obj is Asn1Object)
if (obj is Asn1Encodable)
{
return AsString("", (Asn1Object)obj);
}
else if (obj is Asn1Encodable)
{
return AsString("", ((Asn1Encodable)obj).ToAsn1Object());
return AsString("", false, ((Asn1Encodable)obj).ToAsn1Object());
}
return "unknown object type " + obj.ToString();
}
/**
* dump out a DER object as a formatted string
* dump out a DER object as a formatted string, in non-verbose mode
*
* @param obj the Asn1Encodable to be dumped out.
* @return the resulting string.
*/
public static string DumpAsString(
Asn1Encodable obj)
{
return AsString("", obj.ToAsn1Object());
return DumpAsString(obj, false);
}
/**
* Dump out the object as a string
*
* @param obj the Asn1Encodable to be dumped out.
* @param verbose if true, dump out the contents of octet and bit strings.
* @return the resulting string.
*/
public static string DumpAsString(
Asn1Encodable obj,
bool verbose)
{
return AsString("", verbose, obj.ToAsn1Object());
}
private static string dumpBinaryDataAsString(string indent, byte[] bytes)
{
indent += Tab;
StringBuilder buf = new StringBuilder(NewLine);
for (int i = 0; i < bytes.Length; i += SampleSize)
{
if (bytes.Length - i > SampleSize)
{
buf.Append(indent);
buf.Append(Encoding.ASCII.GetString(Hex.Encode(bytes, i, SampleSize)));
buf.Append(Tab);
buf.Append(calculateAscString(bytes, i, SampleSize));
buf.Append(NewLine);
}
else
{
buf.Append(indent);
buf.Append(Encoding.ASCII.GetString(Hex.Encode(bytes, i, bytes.Length - i)));
for (int j = bytes.Length - i; j != SampleSize; j++)
{
buf.Append(" ");
}
buf.Append(Tab);
buf.Append(calculateAscString(bytes, i, bytes.Length - i));
buf.Append(NewLine);
}
}
return buf.ToString();
}
private static string calculateAscString(
byte[] bytes,
int off,
int len)
{
StringBuilder buf = new StringBuilder();
for (int i = off; i != off + len; i++)
{
char c = (char)bytes[i];
if (c >= ' ' && c <= '~')
{
buf.Append(c);
}
}
return buf.ToString();
}
}
}

View File

@ -57,6 +57,17 @@ namespace Org.BouncyCastle.Asn1.X509
}
}
public ExtendedKeyUsage(
params KeyPurposeID[] usages)
{
this.seq = new DerSequence(usages);
foreach (KeyPurposeID usage in usages)
{
this.usageTable.Add(usage, usage);
}
}
public ExtendedKeyUsage(
ArrayList usages)
{

View File

@ -32,6 +32,8 @@ namespace Org.BouncyCastle.Asn1.X509
internal X509Extensions extensions;
private bool altNamePresentAndCritical;
private DerBitString issuerUniqueID;
private DerBitString subjectUniqueID;
public V3TbsCertificateGenerator()
{
@ -85,6 +87,18 @@ namespace Org.BouncyCastle.Asn1.X509
this.subject = subject;
}
public void SetIssuerUniqueID(
DerBitString uniqueID)
{
this.issuerUniqueID = uniqueID;
}
public void SetSubjectUniqueID(
DerBitString uniqueID)
{
this.subjectUniqueID = uniqueID;
}
public void SetSubjectPublicKeyInfo(
SubjectPublicKeyInfo pubKeyInfo)
{
@ -133,6 +147,16 @@ namespace Org.BouncyCastle.Asn1.X509
v.Add(subjectPublicKeyInfo);
if (issuerUniqueID != null)
{
v.Add(new DerTaggedObject(false, 1, issuerUniqueID));
}
if (subjectUniqueID != null)
{
v.Add(new DerTaggedObject(false, 2, subjectUniqueID));
}
if (extensions != null)
{
v.Add(new DerTaggedObject(3, extensions));

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,9 @@ namespace Org.BouncyCastle.Asn1.X509
public static readonly DerObjectIdentifier Organization = new DerObjectIdentifier(ID + ".10");
public static readonly DerObjectIdentifier OrganizationalUnitName = new DerObjectIdentifier(ID + ".11");
public static readonly DerObjectIdentifier id_at_telephoneNumber = new DerObjectIdentifier(ID + ".20");
public static readonly DerObjectIdentifier id_at_name = new DerObjectIdentifier(ID + ".41");
// id-SHA1 OBJECT IDENTIFIER ::=
// {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } //
public static readonly DerObjectIdentifier IdSha1 = new DerObjectIdentifier("1.3.14.3.2.26");

View File

@ -1,6 +1,8 @@
using System;
using System.IO;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Bcpg
{
/// <remarks>Generic literal data packet.</remarks>
@ -47,5 +49,10 @@ namespace Org.BouncyCastle.Bcpg
{
get { return fileName; }
}
}
public byte[] GetRawFileName()
{
return Strings.ToByteArray(fileName);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -2,20 +2,20 @@ using System;
namespace Org.BouncyCastle.Crypto
{
public abstract class CryptoException
public class CryptoException
: Exception
{
protected CryptoException()
public CryptoException()
{
}
protected CryptoException(
public CryptoException(
string message)
: base(message)
{
}
protected CryptoException(
public CryptoException(
string message,
Exception exception)
: base(message, exception)

View File

@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
@ -56,12 +57,13 @@ namespace Org.BouncyCastle.Crypto.Agreement
*/
public BigInteger CalculateMessage()
{
int bits = dhParams.P.BitLength - 1;
DHKeyPairGenerator dhGen = new DHKeyPairGenerator();
dhGen.Init(new DHKeyGenerationParameters(random, dhParams));
AsymmetricCipherKeyPair dhPair = dhGen.GenerateKeyPair();
// TODO Should the generated numbers always have length 'P.BitLength - 1'?
this.privateValue = new BigInteger(bits, random).SetBit(bits - 1);
this.privateValue = ((DHPrivateKeyParameters)dhPair.Private).X;
return dhParams.G.ModPow(privateValue, dhParams.P);
return ((DHPublicKeyParameters)dhPair.Public).Y;
}
/**
@ -83,7 +85,9 @@ namespace Org.BouncyCastle.Crypto.Agreement
throw new ArgumentException("Diffie-Hellman public key has wrong parameters.");
}
return message.ModPow(key.X, dhParams.P).Multiply(pub.Y.ModPow(privateValue, dhParams.P)).Mod(dhParams.P);
BigInteger p = dhParams.P;
return message.ModPow(key.X, p).Multiply(pub.Y.ModPow(privateValue, p)).Mod(p);
}
}
}

View File

@ -0,0 +1,93 @@
using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Agreement.Srp
{
/**
* Implements the client side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
* This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
* "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
*/
public class Srp6Client
{
protected BigInteger N;
protected BigInteger g;
protected BigInteger privA;
protected BigInteger pubA;
protected BigInteger B;
protected BigInteger x;
protected BigInteger u;
protected BigInteger S;
protected IDigest digest;
protected SecureRandom random;
public Srp6Client()
{
}
/**
* Initialises the client to begin new authentication attempt
* @param N The safe prime associated with the client's verifier
* @param g The group parameter associated with the client's verifier
* @param digest The digest algorithm associated with the client's verifier
* @param random For key generation
*/
public virtual void Init(BigInteger N, BigInteger g, IDigest digest, SecureRandom random)
{
this.N = N;
this.g = g;
this.digest = digest;
this.random = random;
}
/**
* Generates client's credentials given the client's salt, identity and password
* @param salt The salt used in the client's verifier.
* @param identity The user's identity (eg. username)
* @param password The user's password
* @return Client's public value to send to server
*/
public virtual BigInteger GenerateClientCredentials(byte[] salt, byte[] identity, byte[] password)
{
this.x = Srp6Utilities.CalculateX(digest, N, salt, identity, password);
this.privA = SelectPrivateValue();
this.pubA = g.ModPow(privA, N);
return pubA;
}
/**
* Generates client's verification message given the server's credentials
* @param serverB The server's credentials
* @return Client's verification message for the server
* @throws CryptoException If server's credentials are invalid
*/
public virtual BigInteger CalculateSecret(BigInteger serverB)
{
this.B = Srp6Utilities.ValidatePublicValue(N, serverB);
this.u = Srp6Utilities.CalculateU(digest, N, pubA, B);
this.S = CalculateS();
return S;
}
protected virtual BigInteger SelectPrivateValue()
{
return Srp6Utilities.GeneratePrivateValue(digest, N, g, random);
}
private BigInteger CalculateS()
{
BigInteger k = Srp6Utilities.CalculateK(digest, N, g);
BigInteger exp = u.Multiply(x).Mod(N).Add(privA).Mod(N);
BigInteger tmp = g.ModPow(x, N).Multiply(k).Mod(N);
return B.Subtract(tmp).Mod(N).ModPow(exp, N);
}
}
}

View File

@ -0,0 +1,90 @@
using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Agreement.Srp
{
/**
* Implements the server side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
* This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
* "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
*/
public class Srp6Server
{
protected BigInteger N;
protected BigInteger g;
protected BigInteger v;
protected SecureRandom random;
protected IDigest digest;
protected BigInteger A;
protected BigInteger privB;
protected BigInteger pubB;
protected BigInteger u;
protected BigInteger S;
public Srp6Server()
{
}
/**
* Initialises the server to accept a new client authentication attempt
* @param N The safe prime associated with the client's verifier
* @param g The group parameter associated with the client's verifier
* @param v The client's verifier
* @param digest The digest algorithm associated with the client's verifier
* @param random For key generation
*/
public virtual void Init(BigInteger N, BigInteger g, BigInteger v, IDigest digest, SecureRandom random)
{
this.N = N;
this.g = g;
this.v = v;
this.random = random;
this.digest = digest;
}
/**
* Generates the server's credentials that are to be sent to the client.
* @return The server's public value to the client
*/
public virtual BigInteger GenerateServerCredentials()
{
BigInteger k = Srp6Utilities.CalculateK(digest, N, g);
this.privB = SelectPrivateValue();
this.pubB = k.Multiply(v).Mod(N).Add(g.ModPow(privB, N)).Mod(N);
return pubB;
}
/**
* Processes the client's credentials. If valid the shared secret is generated and returned.
* @param clientA The client's credentials
* @return A shared secret BigInteger
* @throws CryptoException If client's credentials are invalid
*/
public virtual BigInteger CalculateSecret(BigInteger clientA)
{
this.A = Srp6Utilities.ValidatePublicValue(N, clientA);
this.u = Srp6Utilities.CalculateU(digest, N, A, pubB);
this.S = CalculateS();
return S;
}
protected virtual BigInteger SelectPrivateValue()
{
return Srp6Utilities.GeneratePrivateValue(digest, N, g, random);
}
private BigInteger CalculateS()
{
return v.ModPow(u, N).Multiply(A).Mod(N).ModPow(privB, N);
}
}
}

View File

@ -0,0 +1,85 @@
using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Agreement.Srp
{
public class Srp6Utilities
{
public static BigInteger CalculateK(IDigest digest, BigInteger N, BigInteger g)
{
return HashPaddedPair(digest, N, N, g);
}
public static BigInteger CalculateU(IDigest digest, BigInteger N, BigInteger A, BigInteger B)
{
return HashPaddedPair(digest, N, A, B);
}
public static BigInteger CalculateX(IDigest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password)
{
byte[] output = new byte[digest.GetDigestSize()];
digest.BlockUpdate(identity, 0, identity.Length);
digest.Update((byte)':');
digest.BlockUpdate(password, 0, password.Length);
digest.DoFinal(output, 0);
digest.BlockUpdate(salt, 0, salt.Length);
digest.BlockUpdate(output, 0, output.Length);
digest.DoFinal(output, 0);
return new BigInteger(1, output).Mod(N);
}
public static BigInteger GeneratePrivateValue(IDigest digest, BigInteger N, BigInteger g, SecureRandom random)
{
int minBits = System.Math.Min(256, N.BitLength / 2);
BigInteger min = BigInteger.One.ShiftLeft(minBits - 1);
BigInteger max = N.Subtract(BigInteger.One);
return BigIntegers.CreateRandomInRange(min, max, random);
}
public static BigInteger ValidatePublicValue(BigInteger N, BigInteger val)
{
val = val.Mod(N);
// Check that val % N != 0
if (val.Equals(BigInteger.Zero))
throw new CryptoException("Server credentials invalid");
return val;
}
private static BigInteger HashPaddedPair(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2)
{
int padLength = (N.BitLength + 7) / 8;
byte[] n1_bytes = GetPadded(n1, padLength);
byte[] n2_bytes = GetPadded(n2, padLength);
digest.BlockUpdate(n1_bytes, 0, n1_bytes.Length);
digest.BlockUpdate(n2_bytes, 0, n2_bytes.Length);
byte[] output = new byte[digest.GetDigestSize()];
digest.DoFinal(output, 0);
return new BigInteger(1, output).Mod(N);
}
private static byte[] GetPadded(BigInteger n, int length)
{
byte[] bs = BigIntegers.AsUnsignedByteArray(n);
if (bs.Length < length)
{
byte[] tmp = new byte[length];
Array.Copy(bs, 0, tmp, length - bs.Length, bs.Length);
bs = tmp;
}
return bs;
}
}
}

View File

@ -0,0 +1,49 @@
using System;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Crypto.Agreement.Srp
{
/**
* Generates new SRP verifier for user
*/
public class Srp6VerifierGenerator
{
protected BigInteger N;
protected BigInteger g;
protected IDigest digest;
public Srp6VerifierGenerator()
{
}
/**
* Initialises generator to create new verifiers
* @param N The safe prime to use (see DHParametersGenerator)
* @param g The group parameter to use (see DHParametersGenerator)
* @param digest The digest to use. The same digest type will need to be used later for the actual authentication
* attempt. Also note that the final session key size is dependent on the chosen digest.
*/
public virtual void Init(BigInteger N, BigInteger g, IDigest digest)
{
this.N = N;
this.g = g;
this.digest = digest;
}
/**
* Creates a new SRP verifier
* @param salt The salt to use, generally should be large and random
* @param identity The user's identifying information (eg. username)
* @param password The user's password
* @return A new verifier for use in future SRP authentication
*/
public virtual BigInteger GenerateVerifier(byte[] salt, byte[] identity, byte[] password)
{
BigInteger x = Srp6Utilities.CalculateX(digest, N, salt, identity, password);
return g.ModPow(x, N);
}
}
}

View File

@ -100,7 +100,7 @@ namespace Org.BouncyCastle.Crypto.Digests
{
byteCount = 0;
xBufOff = 0;
for ( int i = 0; i < xBuf.Length; i++ ) xBuf[i] = 0;
Array.Clear(xBuf, 0, xBuf.Length);
}
public int GetByteLength()

View File

@ -17,16 +17,15 @@ namespace Org.BouncyCastle.Crypto.Digests
public class Sha256Digest
: GeneralDigest
{
private const int DigestLength = 32;
private const int DigestLength = 32;
private int H1, H2, H3, H4, H5, H6, H7, H8;
private int[] X = new int[64];
private int xOff;
private uint H1, H2, H3, H4, H5, H6, H7, H8;
private uint[] X = new uint[64];
private int xOff;
public Sha256Digest()
{
Reset();
initHs();
}
/**
@ -61,9 +60,11 @@ namespace Org.BouncyCastle.Crypto.Digests
internal override void ProcessWord(
byte[] input,
int inOff)
{
X[xOff++] = ((input[inOff] & 0xff) << 24) | ((input[inOff + 1] & 0xff) << 16)
| ((input[inOff + 2] & 0xff) << 8) | ((input[inOff + 3] & 0xff));
{
X[xOff++] = (((uint)input[inOff]) << 24)
| (((uint)input[inOff + 1]) << 16)
| (((uint)input[inOff + 2]) << 8)
| ((uint)input[inOff + 3]);
if (xOff == 16)
{
@ -72,26 +73,26 @@ namespace Org.BouncyCastle.Crypto.Digests
}
private void UnpackWord(
int word,
uint word,
byte[] outBytes,
int outOff)
{
outBytes[outOff] = (byte)((uint) word >> 24);
outBytes[outOff + 1] = (byte)((uint) word >> 16);
outBytes[outOff + 2] = (byte)((uint) word >> 8);
outBytes[outOff] = (byte)(word >> 24);
outBytes[outOff + 1] = (byte)(word >> 16);
outBytes[outOff + 2] = (byte)(word >> 8);
outBytes[outOff + 3] = (byte)word;
}
internal override void ProcessLength(
long bitLength)
long bitLength)
{
if (xOff > 14)
{
ProcessBlock();
}
X[14] = (int)((ulong) bitLength >> 32);
X[15] = (int)(bitLength & 0xffffffff);
X[14] = (uint)((ulong)bitLength >> 32);
X[15] = (uint)((ulong)bitLength);
}
public override int DoFinal(
@ -121,28 +122,27 @@ namespace Org.BouncyCastle.Crypto.Digests
{
base.Reset();
initHs();
xOff = 0;
Array.Clear(X, 0, X.Length);
}
private void initHs()
{
/* SHA-256 initial hash value
* The first 32 bits of the fractional parts of the square roots
* of the first eight prime numbers
*/
unchecked
{
H1 = (int) 0x6a09e667;
H2 = (int) 0xbb67ae85;
H3 = (int) 0x3c6ef372;
H4 = (int) 0xa54ff53a;
H5 = (int) 0x510e527f;
H6 = (int) 0x9b05688c;
H7 = (int) 0x1f83d9ab;
H8 = (int) 0x5be0cd19;
}
xOff = 0;
for (int i = 0; i != X.Length; i++)
{
X[i] = 0;
}
}
H1 = 0x6a09e667;
H2 = 0xbb67ae85;
H3 = 0x3c6ef372;
H4 = 0xa54ff53a;
H5 = 0x510e527f;
H6 = 0x9b05688c;
H7 = 0x1f83d9ab;
H8 = 0x5be0cd19;
}
internal override void ProcessBlock()
{
@ -157,57 +157,57 @@ namespace Org.BouncyCastle.Crypto.Digests
//
// set up working variables.
//
int a = H1;
int b = H2;
int c = H3;
int d = H4;
int e = H5;
int f = H6;
int g = H7;
int h = H8;
uint a = H1;
uint b = H2;
uint c = H3;
uint d = H4;
uint e = H5;
uint f = H6;
uint g = H7;
uint h = H8;
int t = 0;
for(int i = 0; i < 8; i ++)
for(int i = 0; i < 8; ++i)
{
// t = 8 * i
h += Sum1(e) + Ch(e, f, g) + K[t] + X[t++];
h += Sum1Ch(e, f, g) + K[t] + X[t++];
d += h;
h += Sum0(a) + Maj(a, b, c);
h += Sum0Maj(a, b, c);
// t = 8 * i + 1
g += Sum1(d) + Ch(d, e, f) + K[t] + X[t++];
g += Sum1Ch(d, e, f) + K[t] + X[t++];
c += g;
g += Sum0(h) + Maj(h, a, b);
g += Sum0Maj(h, a, b);
// t = 8 * i + 2
f += Sum1(c) + Ch(c, d, e) + K[t] + X[t++];
f += Sum1Ch(c, d, e) + K[t] + X[t++];
b += f;
f += Sum0(g) + Maj(g, h, a);
f += Sum0Maj(g, h, a);
// t = 8 * i + 3
e += Sum1(b) + Ch(b, c, d) + K[t] + X[t++];
e += Sum1Ch(b, c, d) + K[t] + X[t++];
a += e;
e += Sum0(f) + Maj(f, g, h);
e += Sum0Maj(f, g, h);
// t = 8 * i + 4
d += Sum1(a) + Ch(a, b, c) + K[t] + X[t++];
d += Sum1Ch(a, b, c) + K[t] + X[t++];
h += d;
d += Sum0(e) + Maj(e, f, g);
d += Sum0Maj(e, f, g);
// t = 8 * i + 5
c += Sum1(h) + Ch(h, a, b) + K[t] + X[t++];
c += Sum1Ch(h, a, b) + K[t] + X[t++];
g += c;
c += Sum0(d) + Maj(d, e, f);
c += Sum0Maj(d, e, f);
// t = 8 * i + 6
b += Sum1(g) + Ch(g, h, a) + K[t] + X[t++];
b += Sum1Ch(g, h, a) + K[t] + X[t++];
f += b;
b += Sum0(c) + Maj(c, d, e);
b += Sum0Maj(c, d, e);
// t = 8 * i + 7
a += Sum1(f) + Ch(f, g, h) + K[t] + X[t++];
a += Sum1Ch(f, g, h) + K[t] + X[t++];
e += a;
a += Sum0(b) + Maj(b, c, d);
a += Sum0Maj(b, c, d);
}
H1 += a;
@ -227,84 +227,88 @@ namespace Org.BouncyCastle.Crypto.Digests
Array.Clear(X, 0, 16);
}
/* SHA-256 functions */
private static int Ch(
int x,
int y,
int z)
private static uint Sum1Ch(
uint x,
uint y,
uint z)
{
// return Sum1(x) + Ch(x, y, z);
return (((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7)))
+ ((x & y) ^ ((~x) & z));
}
private static uint Sum0Maj(
uint x,
uint y,
uint z)
{
// return Sum0(x) + Maj(x, y, z);
return (((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10)))
+ ((x & y) ^ (x & z) ^ (y & z));
}
// /* SHA-256 functions */
// private static uint Ch(
// uint x,
// uint y,
// uint z)
// {
// return ((x & y) ^ ((~x) & z));
// }
//
// private static uint Maj(
// uint x,
// uint y,
// uint z)
// {
// return ((x & y) ^ (x & z) ^ (y & z));
// }
//
// private static uint Sum0(
// uint x)
// {
// return ((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10));
// }
//
// private static uint Sum1(
// uint x)
// {
// return ((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7));
// }
private static uint Theta0(
uint x)
{
return ((x & y) ^ ((~x) & z));
return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3);
}
private static int Maj(
int x,
int y,
int z)
private static uint Theta1(
uint x)
{
return ((x & y) ^ (x & z) ^ (y & z));
}
private static int Sum0(
int x)
{
return (((int)((uint)x >> 2)) | (x << 30)) ^ (((int)((uint)x >> 13)) | (x << 19)) ^ (((int)((uint)x >> 22)) | (x << 10));
}
private static int Sum1(
int x)
{
return (((int)((uint)x >> 6)) | (x << 26)) ^ (((int)((uint)x >> 11)) | (x << 21)) ^ (((int)((uint)x >> 25)) | (x << 7));
}
private static int Theta0(
int x)
{
return (((int)((uint)x >> 7)) | (x << 25)) ^ (((int)((uint)x >> 18)) | (x << 14)) ^ ((int)((uint)x >> 3));
}
private static int Theta1(
int x)
{
return (((int)((uint)x >> 17)) | (x << 15)) ^ (((int)((uint)x >> 19)) | (x << 13)) ^ ((int)((uint)x >> 10));
return ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10);
}
/* SHA-256 Constants
* (represent the first 32 bits of the fractional parts of the
* cube roots of the first sixty-four prime numbers)
*/
internal static readonly int[] K = {
unchecked ((int) 0x428a2f98), unchecked ((int) 0x71374491),
unchecked ((int) 0xb5c0fbcf), unchecked ((int) 0xe9b5dba5),
unchecked ((int) 0x3956c25b), unchecked ((int) 0x59f111f1),
unchecked ((int) 0x923f82a4), unchecked ((int) 0xab1c5ed5),
unchecked ((int) 0xd807aa98), unchecked ((int) 0x12835b01),
unchecked ((int) 0x243185be), unchecked ((int) 0x550c7dc3),
unchecked ((int) 0x72be5d74), unchecked ((int) 0x80deb1fe),
unchecked ((int) 0x9bdc06a7), unchecked ((int) 0xc19bf174),
unchecked ((int) 0xe49b69c1), unchecked ((int) 0xefbe4786),
unchecked ((int) 0x0fc19dc6), unchecked ((int) 0x240ca1cc),
unchecked ((int) 0x2de92c6f), unchecked ((int) 0x4a7484aa),
unchecked ((int) 0x5cb0a9dc), unchecked ((int) 0x76f988da),
unchecked ((int) 0x983e5152), unchecked ((int) 0xa831c66d),
unchecked ((int) 0xb00327c8), unchecked ((int) 0xbf597fc7),
unchecked ((int) 0xc6e00bf3), unchecked ((int) 0xd5a79147),
unchecked ((int) 0x06ca6351), unchecked ((int) 0x14292967),
unchecked ((int) 0x27b70a85), unchecked ((int) 0x2e1b2138),
unchecked ((int) 0x4d2c6dfc), unchecked ((int) 0x53380d13),
unchecked ((int) 0x650a7354), unchecked ((int) 0x766a0abb),
unchecked ((int) 0x81c2c92e), unchecked ((int) 0x92722c85),
unchecked ((int) 0xa2bfe8a1), unchecked ((int) 0xa81a664b),
unchecked ((int) 0xc24b8b70), unchecked ((int) 0xc76c51a3),
unchecked ((int) 0xd192e819), unchecked ((int) 0xd6990624),
unchecked ((int) 0xf40e3585), unchecked ((int) 0x106aa070),
unchecked ((int) 0x19a4c116), unchecked ((int) 0x1e376c08),
unchecked ((int) 0x2748774c), unchecked ((int) 0x34b0bcb5),
unchecked ((int) 0x391c0cb3), unchecked ((int) 0x4ed8aa4a),
unchecked ((int) 0x5b9cca4f), unchecked ((int) 0x682e6ff3),
unchecked ((int) 0x748f82ee), unchecked ((int) 0x78a5636f),
unchecked ((int) 0x84c87814), unchecked ((int) 0x8cc70208),
unchecked ((int) 0x90befffa), unchecked ((int) 0xa4506ceb),
unchecked ((int) 0xbef9a3f7), unchecked ((int) 0xc67178f2)
private static readonly uint[] K = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
}
}

View File

@ -78,12 +78,12 @@ namespace Org.BouncyCastle.Crypto.Engines
* Outerbridge's D3DES...
*/
private static readonly short[] Df_Key =
{
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67
};
// private static readonly short[] Df_Key =
// {
// 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
// 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
// 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67
// };
private static readonly short[] bytebit =
{

View File

@ -13,7 +13,7 @@ namespace Org.BouncyCastle.Crypto.Engines
private const int
rounds = 32,
block_size = 8,
key_size = 16,
// key_size = 16,
delta = unchecked((int) 0x9E3779B9),
d_sum = unchecked((int) 0xC6EF3720); // sum on decrypt

View File

@ -13,7 +13,7 @@ namespace Org.BouncyCastle.Crypto.Engines
private const int
rounds = 32,
block_size = 8,
key_size = 16,
// key_size = 16,
delta = unchecked((int) 0x9E3779B9);
/*

View File

@ -6,10 +6,10 @@ using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* a basic Diffie-Helman key pair generator.
* a basic Diffie-Hellman key pair generator.
*
* This Generates keys consistent for use with the basic algorithm for
* Diffie-Helman.
* This generates keys consistent for use with the basic algorithm for
* Diffie-Hellman.
*/
public class DHBasicKeyPairGenerator
: IAsymmetricCipherKeyPairGenerator
@ -19,22 +19,20 @@ namespace Org.BouncyCastle.Crypto.Generators
public virtual void Init(
KeyGenerationParameters parameters)
{
this.param = (DHKeyGenerationParameters) parameters;
this.param = (DHKeyGenerationParameters)parameters;
}
public virtual AsymmetricCipherKeyPair GenerateKeyPair()
{
DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.Instance;
DHParameters dhParams = param.Parameters;
DHParameters dhp = param.Parameters;
BigInteger p = dhParams.P;
BigInteger x = helper.CalculatePrivate(p, param.Random, dhParams.L);
BigInteger y = helper.CalculatePublic(p, dhParams.G, x);
BigInteger x = helper.CalculatePrivate(dhp, param.Random);
BigInteger y = helper.CalculatePublic(dhp, x);
return new AsymmetricCipherKeyPair(
new DHPublicKeyParameters(y, dhParams),
new DHPrivateKeyParameters(x, dhParams));
new DHPublicKeyParameters(y, dhp),
new DHPrivateKeyParameters(x, dhp));
}
}
}

View File

@ -1,14 +1,14 @@
using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Generators
{
class DHKeyGeneratorHelper
{
private const int MAX_ITERATIONS = 1000;
internal static readonly DHKeyGeneratorHelper Instance = new DHKeyGeneratorHelper();
private DHKeyGeneratorHelper()
@ -16,63 +16,38 @@ namespace Org.BouncyCastle.Crypto.Generators
}
internal BigInteger CalculatePrivate(
BigInteger p,
SecureRandom random,
int limit)
{
//
// calculate the private key
//
BigInteger pSub2 = p.Subtract(BigInteger.Two);
BigInteger x;
if (limit == 0)
{
x = createInRange(pSub2, random);
}
else
{
do
{
// TODO Check this (should the generated numbers always be odd,
// and length 'limit'?)
x = new BigInteger(limit, 0, random);
}
while (x.SignValue == 0);
}
return x;
}
private BigInteger createInRange(
BigInteger max,
DHParameters dhParams,
SecureRandom random)
{
BigInteger x;
int maxLength = max.BitLength;
int count = 0;
int limit = dhParams.L;
do
if (limit != 0)
{
x = new BigInteger(maxLength, random);
count++;
}
while ((x.SignValue == 0 || x.CompareTo(max) > 0) && count != MAX_ITERATIONS);
if (count == MAX_ITERATIONS) // fall back to a faster (restricted) method
{
return new BigInteger(maxLength - 1, random).SetBit(0);
return new BigInteger(limit, random).SetBit(limit - 1);
}
return x;
BigInteger min = BigInteger.Two;
int m = dhParams.M;
if (m != 0)
{
min = BigInteger.One.ShiftLeft(m - 1);
}
BigInteger max = dhParams.P.Subtract(BigInteger.Two);
BigInteger q = dhParams.Q;
if (q != null)
{
max = q.Subtract(BigInteger.Two);
}
return BigIntegers.CreateRandomInRange(min, max, random);
}
internal BigInteger CalculatePublic(
BigInteger p,
BigInteger g,
BigInteger x)
DHParameters dhParams,
BigInteger x)
{
return g.ModPow(x, p);
return dhParams.G.ModPow(x, dhParams.P);
}
}
}

View File

@ -6,9 +6,9 @@ using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* a Diffie-Helman key pair generator.
* a Diffie-Hellman key pair generator.
*
* This Generates keys consistent for use in the MTI/A0 key agreement protocol
* This generates keys consistent for use in the MTI/A0 key agreement protocol
* as described in "Handbook of Applied Cryptography", Pages 516-519.
*/
public class DHKeyPairGenerator
@ -19,22 +19,20 @@ namespace Org.BouncyCastle.Crypto.Generators
public virtual void Init(
KeyGenerationParameters parameters)
{
this.param = (DHKeyGenerationParameters) parameters;
this.param = (DHKeyGenerationParameters)parameters;
}
public virtual AsymmetricCipherKeyPair GenerateKeyPair()
{
DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.Instance;
DHParameters dhParams = param.Parameters;
DHParameters dhp = param.Parameters;
BigInteger p = dhParams.P;
BigInteger x = helper.CalculatePrivate(p, param.Random, dhParams.L);
BigInteger y = helper.CalculatePublic(p, dhParams.G, x);
BigInteger x = helper.CalculatePrivate(dhp, param.Random);
BigInteger y = helper.CalculatePublic(dhp, x);
return new AsymmetricCipherKeyPair(
new DHPublicKeyParameters(y, dhParams),
new DHPrivateKeyParameters(x, dhParams));
new DHPublicKeyParameters(y, dhp),
new DHPrivateKeyParameters(x, dhp));
}
}
}

View File

@ -2,6 +2,7 @@ using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Generators
{
@ -208,7 +209,7 @@ namespace Org.BouncyCastle.Crypto.Generators
// Handbook of Applied Cryptography 4.86
do
{
g = CreateInRange(BigInteger.Two, pMinusTwo, random);
g = BigIntegers.CreateRandomInRange(BigInteger.Two, pMinusTwo, random);
}
while (g.ModPow(BigInteger.Two, p).Equals(BigInteger.One)
|| g.ModPow(q, p).Equals(BigInteger.One));
@ -226,19 +227,5 @@ namespace Org.BouncyCastle.Crypto.Generators
return g;
}
private static BigInteger CreateInRange(
BigInteger min,
BigInteger max,
SecureRandom random)
{
BigInteger x;
do
{
x = new BigInteger(max.BitLength, random);
}
while (x.CompareTo(min) < 0 || x.CompareTo(max) > 0);
return x;
}
}
}

View File

@ -29,7 +29,8 @@ namespace Org.BouncyCastle.Crypto.Generators
protected override void engineInit(
KeyGenerationParameters parameters)
{
base.engineInit(parameters);
this.random = parameters.Random;
this.strength = (parameters.Strength + 7) / 8;
if (strength == 0 || strength == (168 / 8))
{

View File

@ -17,6 +17,29 @@ namespace Org.BouncyCastle.Crypto.Generators
{
}
/**
* initialise the key generator - if strength is set to zero
* the key generated will be 64 bits in size, otherwise
* strength can be 64 or 56 bits (if you don't count the parity bits).
*
* @param param the parameters to be used for key generation
*/
protected override void engineInit(
KeyGenerationParameters parameters)
{
base.engineInit(parameters);
if (strength == 0 || strength == (56 / 8))
{
strength = DesParameters.DesKeyLength;
}
else if (strength != DesParameters.DesKeyLength)
{
throw new ArgumentException(
"DES key must be " + (DesParameters.DesKeyLength * 8) + " bits long.");
}
}
protected override byte[] engineGenerateKey()
{
byte[] newKey;

View File

@ -2,6 +2,7 @@ using System;
using System.Globalization;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
@ -59,12 +60,21 @@ namespace Org.BouncyCastle.Crypto.Generators
case 192:
oid = X9ObjectIdentifiers.Prime192v1;
break;
case 224:
oid = SecObjectIdentifiers.SecP224r1;
break;
case 239:
oid = X9ObjectIdentifiers.Prime239v1;
break;
case 256:
oid = X9ObjectIdentifiers.Prime256v1;
break;
case 384:
oid = SecObjectIdentifiers.SecP384r1;
break;
case 521:
oid = SecObjectIdentifiers.SecP521r1;
break;
default:
throw new InvalidParameterException("unknown key size.");
}

View File

@ -25,15 +25,15 @@ namespace Org.BouncyCastle.Crypto.Generators
public AsymmetricCipherKeyPair GenerateKeyPair()
{
DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.Instance;
ElGamalParameters elParams = param.Parameters;
ElGamalParameters egp = param.Parameters;
DHParameters dhp = new DHParameters(egp.P, egp.G, null, 0, egp.L);
BigInteger p = elParams.P;
BigInteger x = helper.CalculatePrivate(p, param.Random, elParams.L);
BigInteger y = helper.CalculatePublic(p, elParams.G, x);
BigInteger x = helper.CalculatePrivate(dhp, param.Random);
BigInteger y = helper.CalculatePublic(dhp, x);
return new AsymmetricCipherKeyPair(
new ElGamalPublicKeyParameters(y, elParams),
new ElGamalPrivateKeyParameters(x, elParams));
new ElGamalPublicKeyParameters(y, egp),
new ElGamalPrivateKeyParameters(x, egp));
}
}

View File

@ -1,116 +1,137 @@
using System;
using System.IO;
using Org.BouncyCastle.Crypto;
namespace Org.BouncyCastle.Crypto.IO
{
public class DigestStream : Stream
{
internal Stream stream;
internal IDigest inDigest;
internal IDigest outDigest;
public class DigestStream
: Stream
{
protected readonly Stream stream;
protected readonly IDigest inDigest;
protected readonly IDigest outDigest;
public DigestStream(
Stream stream,
IDigest readDigest,
IDigest writeDigest)
{
this.stream = stream;
this.inDigest = readDigest;
this.outDigest = writeDigest;
}
public IDigest ReadDigest()
{
return inDigest;
}
public IDigest WriteDigest()
{
return outDigest;
}
public override int ReadByte()
{
int b = stream.ReadByte();
if (inDigest != null)
{
if (b >= 0)
{
inDigest.Update((byte)b);
}
}
return b;
}
public DigestStream(
Stream stream,
IDigest readDigest,
IDigest writeDigest)
{
this.stream = stream;
this.inDigest = readDigest;
this.outDigest = writeDigest;
}
public override int Read(byte[] buffer, int offset, int count)
{
int n = stream.Read(buffer, offset, count);
if (inDigest != null)
{
if (n > 0)
{
inDigest.BlockUpdate(buffer, offset, n);
}
}
return n;
}
public override void Write(
byte[] buffer,
int offset,
int count)
{
if (outDigest != null)
{
if (count > 0)
{
outDigest.BlockUpdate(buffer, offset, count);
}
}
stream.Write(buffer, offset, count);
}
public override void WriteByte(byte value)
{
if (outDigest != null)
{
outDigest.Update(value);
}
stream.WriteByte(value);
}
public override bool CanRead
{
get { return stream.CanRead && (inDigest != null); }
}
public override bool CanWrite
{
get { return stream.CanWrite && (outDigest != null); }
}
public override bool CanSeek
{
get { return stream.CanSeek; }
}
public override long Length
{
get { return stream.Length; }
}
public override long Position
{
get { return stream.Position; }
set { stream.Position = value; }
}
public override void Close()
{
stream.Close();
}
public override void Flush()
{
stream.Flush();
}
public override long Seek(
long offset,
SeekOrigin origin)
{
return stream.Seek(offset,origin);
}
public override void SetLength(long value)
{
stream.SetLength(value);
}
}
public virtual IDigest ReadDigest()
{
return inDigest;
}
public virtual IDigest WriteDigest()
{
return outDigest;
}
public override int Read(
byte[] buffer,
int offset,
int count)
{
int n = stream.Read(buffer, offset, count);
if (inDigest != null)
{
if (n > 0)
{
inDigest.BlockUpdate(buffer, offset, n);
}
}
return n;
}
public override int ReadByte()
{
int b = stream.ReadByte();
if (inDigest != null)
{
if (b >= 0)
{
inDigest.Update((byte)b);
}
}
return b;
}
public override void Write(
byte[] buffer,
int offset,
int count)
{
if (outDigest != null)
{
if (count > 0)
{
outDigest.BlockUpdate(buffer, offset, count);
}
}
stream.Write(buffer, offset, count);
}
public override void WriteByte(
byte b)
{
if (outDigest != null)
{
outDigest.Update(b);
}
stream.WriteByte(b);
}
public override bool CanRead
{
get { return stream.CanRead; }
}
public override bool CanWrite
{
get { return stream.CanWrite; }
}
public override bool CanSeek
{
get { return stream.CanSeek; }
}
public override long Length
{
get { return stream.Length; }
}
public override long Position
{
get { return stream.Position; }
set { stream.Position = value; }
}
public override void Close()
{
stream.Close();
}
public override void Flush()
{
stream.Flush();
}
public override long Seek(
long offset,
SeekOrigin origin)
{
return stream.Seek(offset, origin);
}
public override void SetLength(
long length)
{
stream.SetLength(length);
}
}
}

View File

@ -1,116 +1,136 @@
using System;
using System.IO;
using Org.BouncyCastle.Crypto;
namespace Org.BouncyCastle.Crypto.IO
{
public class MacStream : Stream
{
internal Stream stream;
internal IMac inMac;
internal IMac outMac;
public class MacStream
: Stream
{
protected readonly Stream stream;
protected readonly IMac inMac;
protected readonly IMac outMac;
public MacStream(
Stream stream,
IMac readMac,
IMac writeMac)
{
this.stream = stream;
this.inMac = readMac;
this.outMac = writeMac;
}
public IMac ReadMac()
{
return inMac;
}
public IMac WriteMac()
{
return outMac;
}
public override int ReadByte()
{
int b = stream.ReadByte();
if (inMac != null)
{
if (b >= 0)
{
inMac.Update((byte)b);
}
}
return b;
}
public MacStream(
Stream stream,
IMac readMac,
IMac writeMac)
{
this.stream = stream;
this.inMac = readMac;
this.outMac = writeMac;
}
public override int Read(byte[] buffer, int offset, int count)
{
int n = stream.Read(buffer, offset, count);
if (inMac != null)
{
if (n > 0)
{
inMac.BlockUpdate(buffer, offset, count);
}
}
return n;
}
public override void Write(
byte[] buffer,
int offset,
int count)
{
if (outMac != null)
{
if (count > 0)
{
outMac.BlockUpdate(buffer, offset, count);
}
}
stream.Write(buffer, offset, count);
}
public override void WriteByte(byte value)
{
if (outMac != null)
{
outMac.Update(value);
}
stream.WriteByte(value);
}
public override bool CanRead
{
get { return stream.CanRead && (inMac != null); }
}
public override bool CanWrite
{
get { return stream.CanWrite && (outMac != null); }
}
public override bool CanSeek
{
get { return stream.CanSeek; }
}
public override long Length
{
get { return stream.Length; }
}
public override long Position
{
get { return stream.Position; }
set { stream.Position = value; }
}
public override void Close()
{
stream.Close();
}
public override void Flush()
{
stream.Flush();
}
public override long Seek(
long offset,
SeekOrigin origin)
{
return stream.Seek(offset,origin);
}
public override void SetLength(long value)
{
stream.SetLength(value);
}
}
public virtual IMac ReadMac()
{
return inMac;
}
public virtual IMac WriteMac()
{
return outMac;
}
public override int Read(
byte[] buffer,
int offset,
int count)
{
int n = stream.Read(buffer, offset, count);
if (inMac != null)
{
if (n > 0)
{
inMac.BlockUpdate(buffer, offset, count);
}
}
return n;
}
public override int ReadByte()
{
int b = stream.ReadByte();
if (inMac != null)
{
if (b >= 0)
{
inMac.Update((byte)b);
}
}
return b;
}
public override void Write(
byte[] buffer,
int offset,
int count)
{
if (outMac != null)
{
if (count > 0)
{
outMac.BlockUpdate(buffer, offset, count);
}
}
stream.Write(buffer, offset, count);
}
public override void WriteByte(byte b)
{
if (outMac != null)
{
outMac.Update(b);
}
stream.WriteByte(b);
}
public override bool CanRead
{
get { return stream.CanRead; }
}
public override bool CanWrite
{
get { return stream.CanWrite; }
}
public override bool CanSeek
{
get { return stream.CanSeek; }
}
public override long Length
{
get { return stream.Length; }
}
public override long Position
{
get { return stream.Position; }
set { stream.Position = value; }
}
public override void Close()
{
stream.Close();
}
public override void Flush()
{
stream.Flush();
}
public override long Seek(
long offset,
SeekOrigin origin)
{
return stream.Seek(offset,origin);
}
public override void SetLength(
long length)
{
stream.SetLength(length);
}
}
}

View File

@ -0,0 +1,137 @@
using System;
using System.IO;
namespace Org.BouncyCastle.Crypto.IO
{
public class SignerStream
: Stream
{
protected readonly Stream stream;
protected readonly ISigner inSigner;
protected readonly ISigner outSigner;
public SignerStream(
Stream stream,
ISigner readSigner,
ISigner writeSigner)
{
this.stream = stream;
this.inSigner = readSigner;
this.outSigner = writeSigner;
}
public virtual ISigner ReadSigner()
{
return inSigner;
}
public virtual ISigner WriteSigner()
{
return outSigner;
}
public override int Read(
byte[] buffer,
int offset,
int count)
{
int n = stream.Read(buffer, offset, count);
if (inSigner != null)
{
if (n > 0)
{
inSigner.BlockUpdate(buffer, offset, n);
}
}
return n;
}
public override int ReadByte()
{
int b = stream.ReadByte();
if (inSigner != null)
{
if (b >= 0)
{
inSigner.Update((byte)b);
}
}
return b;
}
public override void Write(
byte[] buffer,
int offset,
int count)
{
if (outSigner != null)
{
if (count > 0)
{
outSigner.BlockUpdate(buffer, offset, count);
}
}
stream.Write(buffer, offset, count);
}
public override void WriteByte(
byte b)
{
if (outSigner != null)
{
outSigner.Update(b);
}
stream.WriteByte(b);
}
public override bool CanRead
{
get { return stream.CanRead; }
}
public override bool CanWrite
{
get { return stream.CanWrite; }
}
public override bool CanSeek
{
get { return stream.CanSeek; }
}
public override long Length
{
get { return stream.Length; }
}
public override long Position
{
get { return stream.Position; }
set { stream.Position = value; }
}
public override void Close()
{
stream.Close();
}
public override void Flush()
{
stream.Flush();
}
public override long Seek(
long offset,
SeekOrigin origin)
{
return stream.Seek(offset, origin);
}
public override void SetLength(
long length)
{
stream.SetLength(length);
}
}
}

View File

@ -12,7 +12,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
public DHKeyGenerationParameters(
SecureRandom random,
DHParameters parameters)
: base(random, parameters.P.BitLength)
: base(random, GetStrength(parameters))
{
this.parameters = parameters;
}
@ -21,5 +21,11 @@ namespace Org.BouncyCastle.Crypto.Parameters
{
get { return parameters; }
}
internal static int GetStrength(
DHParameters parameters)
{
return parameters.L != 0 ? parameters.L : parameters.P.BitLength;
}
}
}

View File

@ -14,21 +14,19 @@ namespace Org.BouncyCastle.Crypto.Parameters
private readonly int m, l;
private readonly DHValidationParameters validation;
private static int GetDefaultM(
BigInteger p,
int l)
private static int GetDefaultMParam(
int lParam)
{
int effectiveL = l != 0 ? l : p.BitLength - 1;
if (lParam == 0)
return DefaultMinimumLength;
return System.Math.Min(DefaultMinimumLength, effectiveL);
// return DefaultMinimumLength;
return System.Math.Min(lParam, DefaultMinimumLength);
}
public DHParameters(
BigInteger p,
BigInteger g)
: this(p, g, null, GetDefaultM(p, 0), 0, null, null)
: this(p, g, null, 0)
{
}
@ -36,7 +34,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
BigInteger p,
BigInteger g,
BigInteger q)
: this(p, g, q, GetDefaultM(p, 0), 0, null, null)
: this(p, g, q, 0)
{
}
@ -45,9 +43,9 @@ namespace Org.BouncyCastle.Crypto.Parameters
BigInteger g,
BigInteger q,
int l)
: this(p, g, q, GetDefaultM(p, l), l, null, null)
: this(p, g, q, GetDefaultMParam(l), l, null, null)
{
}
}
public DHParameters(
BigInteger p,
@ -65,7 +63,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
BigInteger q,
BigInteger j,
DHValidationParameters validation)
: this(p, g, q, GetDefaultM(p, 0), 0, j, validation)
: this(p, g, q, DefaultMinimumLength, 0, j, validation)
{
}
@ -87,13 +85,22 @@ namespace Org.BouncyCastle.Crypto.Parameters
if (g.CompareTo(BigInteger.Two) < 0
|| g.CompareTo(p.Subtract(BigInteger.Two)) > 0)
throw new ArgumentException("generator must in the range [2, p - 2]", "g");
if (q != null && q.BitLength >= p.BitLength)
throw new ArgumentException("q too big to be a factor of (p-1)", "q");
if (m >= p.BitLength)
throw new ArgumentException("m value must be < bitlength of p", "m");
if (l != 0 && l < m)
throw new ArgumentException("l value must be >= m, or zero", "l");
if (l != 0)
{
if (l >= p.BitLength)
throw new ArgumentException("when l value specified, it must be less than bitlength(p)", "l");
if (l < m)
throw new ArgumentException("when l value specified, it may not be less than m value", "l");
}
if (j != null && j.CompareTo(BigInteger.Two) < 0)
throw new ArgumentException("subgroup factor must be >= 2", "j");
// TODO If q, j both provided, validate p = jq + 1 ?
this.p = p;
this.g = g;
this.q = q;
@ -130,7 +137,6 @@ namespace Org.BouncyCastle.Crypto.Parameters
}
/// <summary>The bitlength of the private value.</summary>
/// <remarks>If zero, bitLength(p) - 1 will be used.</remarks>
public int L
{
get { return l; }

View File

@ -12,7 +12,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
public ElGamalKeyGenerationParameters(
SecureRandom random,
ElGamalParameters parameters)
: base(random, parameters.P.BitLength)
: base(random, GetStrength(parameters))
{
this.parameters = parameters;
}
@ -21,5 +21,11 @@ namespace Org.BouncyCastle.Crypto.Parameters
{
get { return parameters; }
}
internal static int GetStrength(
ElGamalParameters parameters)
{
return parameters.L != 0 ? parameters.L : parameters.P.BitLength;
}
}
}

View File

@ -49,14 +49,10 @@ namespace Org.BouncyCastle.Crypto.Signers
}
if (forSigning && !k.IsPrivate)
{
throw new InvalidKeyException("Signing Requires Private Key.");
}
if (!forSigning && k.IsPrivate)
{
throw new InvalidKeyException("Verification Requires Public Key.");
}
Reset();
@ -95,16 +91,9 @@ namespace Org.BouncyCastle.Crypto.Signers
byte[] hash = new byte[digest.GetDigestSize()];
digest.DoFinal(hash, 0);
try
{
BigInteger[] sig = dsaSigner.GenerateSignature(hash);
BigInteger[] sig = dsaSigner.GenerateSignature(hash);
return DerEncode(sig[0], sig[1]);
}
catch (Exception e)
{
throw new SignatureException(e.Message, e);
}
return DerEncode(sig[0], sig[1]);
}
/// <returns>true if the internal state represents the signature described in the passed in array.</returns>
@ -117,17 +106,15 @@ namespace Org.BouncyCastle.Crypto.Signers
byte[] hash = new byte[digest.GetDigestSize()];
digest.DoFinal(hash, 0);
BigInteger[] sig;
try
{
sig = DerDecode(signature);
BigInteger[] sig = DerDecode(signature);
return dsaSigner.VerifySignature(hash, sig[0], sig[1]);
}
catch (Exception e)
catch (IOException)
{
throw new SignatureException("error decoding signature bytes.", e);
return false;
}
return dsaSigner.VerifySignature(hash, sig[0], sig[1]);
}
/// <summary>Reset the internal state</summary>

View File

@ -0,0 +1,129 @@
using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Signers
{
public class GenericSigner
: ISigner
{
private readonly IAsymmetricBlockCipher engine;
private readonly IDigest digest;
private bool forSigning;
public GenericSigner(
IAsymmetricBlockCipher engine,
IDigest digest)
{
this.engine = engine;
this.digest = digest;
}
public string AlgorithmName
{
get { return "Generic(" + engine.AlgorithmName + "/" + digest.AlgorithmName + ")"; }
}
/**
* initialise the signer for signing or verification.
*
* @param forSigning
* true if for signing, false otherwise
* @param parameters
* necessary parameters.
*/
public void Init(
bool forSigning,
ICipherParameters parameters)
{
this.forSigning = forSigning;
AsymmetricKeyParameter k;
if (parameters is ParametersWithRandom)
{
k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).Parameters;
}
else
{
k = (AsymmetricKeyParameter)parameters;
}
if (forSigning && !k.IsPrivate)
throw new InvalidKeyException("Signing requires private key.");
if (!forSigning && k.IsPrivate)
throw new InvalidKeyException("Verification requires public key.");
Reset();
engine.Init(forSigning, parameters);
}
/**
* update the internal digest with the byte b
*/
public void Update(
byte input)
{
digest.Update(input);
}
/**
* update the internal digest with the byte array in
*/
public void BlockUpdate(
byte[] input,
int inOff,
int length)
{
digest.BlockUpdate(input, inOff, length);
}
/**
* Generate a signature for the message we've been loaded with using the key
* we were initialised with.
*/
public byte[] GenerateSignature()
{
if (!forSigning)
throw new InvalidOperationException("GenericSigner not initialised for signature generation.");
byte[] hash = new byte[digest.GetDigestSize()];
digest.DoFinal(hash, 0);
return engine.ProcessBlock(hash, 0, hash.Length);
}
/**
* return true if the internal state represents the signature described in
* the passed in array.
*/
public bool VerifySignature(
byte[] signature)
{
if (forSigning)
throw new InvalidOperationException("GenericSigner not initialised for verification");
byte[] hash = new byte[digest.GetDigestSize()];
digest.DoFinal(hash, 0);
try
{
byte[] sig = engine.ProcessBlock(signature, 0, signature.Length);
return Arrays.AreEqual(sig, hash);
}
catch (Exception)
{
return false;
}
}
public void Reset()
{
digest.Reset();
}
}
}

View File

@ -14,25 +14,36 @@ namespace Org.BouncyCastle.Crypto.Tls
public class TlsCipherSuiteManager
{
private const int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000a;
private const int TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013;
private const int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016;
private const int TLS_RSA_WITH_AES_128_CBC_SHA = 0x002f;
private const int TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032;
private const int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033;
private const int TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035;
private const int TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038;
private const int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039;
internal static void WriteCipherSuites(
Stream outStr)
{
TlsUtilities.WriteUint16(2 * 6, outStr);
TlsUtilities.WriteUint16(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, outStr);
TlsUtilities.WriteUint16(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, outStr);
TlsUtilities.WriteUint16(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, outStr);
TlsUtilities.WriteUint16(TLS_RSA_WITH_AES_256_CBC_SHA, outStr);
TlsUtilities.WriteUint16(TLS_RSA_WITH_AES_128_CBC_SHA, outStr);
TlsUtilities.WriteUint16(TLS_RSA_WITH_3DES_EDE_CBC_SHA, outStr);
int[] suites = new int[]
{
TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
TLS_RSA_WITH_AES_256_CBC_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA,
TLS_RSA_WITH_3DES_EDE_CBC_SHA,
};
TlsUtilities.WriteUint16(2 * suites.Length, outStr);
for (int i = 0; i < suites.Length; ++i)
{
TlsUtilities.WriteUint16(suites[i], outStr);
}
}
internal static TlsCipherSuite GetCipherSuite(
@ -44,18 +55,27 @@ namespace Org.BouncyCastle.Crypto.Tls
case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new DesEdeEngine()), new CbcBlockCipher(new DesEdeEngine()), new Sha1Digest(), new Sha1Digest(), 24, TlsCipherSuite.KE_RSA);
case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new DesEdeEngine()), new CbcBlockCipher(new DesEdeEngine()), new Sha1Digest(), new Sha1Digest(), 24, TlsCipherSuite.KE_DHE_DSS);
case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new DesEdeEngine()), new CbcBlockCipher(new DesEdeEngine()), new Sha1Digest(), new Sha1Digest(), 24, TlsCipherSuite.KE_DHE_RSA);
case TLS_RSA_WITH_AES_128_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 16, TlsCipherSuite.KE_RSA);
case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 16, TlsCipherSuite.KE_DHE_DSS);
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 16, TlsCipherSuite.KE_DHE_RSA);
case TLS_RSA_WITH_AES_256_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 32, TlsCipherSuite.KE_RSA);
case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 32, TlsCipherSuite.KE_DHE_DSS);
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
return new TlsBlockCipherCipherSuite(new CbcBlockCipher(new AesFastEngine()), new CbcBlockCipher(new AesFastEngine()), new Sha1Digest(), new Sha1Digest(), 32, TlsCipherSuite.KE_DHE_RSA);

View File

@ -0,0 +1,16 @@
using System;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Signers;
namespace Org.BouncyCastle.Crypto.Tls
{
internal class TlsDssSigner
: DsaDigestSigner
{
internal TlsDssSigner()
: base(new DsaSigner(), new Sha1Digest())
{
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
using System;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Signers;
namespace Org.BouncyCastle.Crypto.Tls
{
internal class TlsRsaSigner
: GenericSigner
{
internal TlsRsaSigner()
: base(new Pkcs1Encoding(new RsaBlindedEngine()), new CombinedHash())
{
}
}
}

View File

@ -2101,9 +2101,7 @@ namespace Org.BouncyCastle.Math
return this.sign > 0 ? result : result.Negate();
}
int maxBitLength = this.BitLength + val.BitLength;
int resLength = (maxBitLength + BitsPerInt - 1) / BitsPerInt;
int resLength = (this.BitLength + val.BitLength) / BitsPerInt + 1;
int[] res = new int[resLength];
if (val == this)

View File

@ -36,6 +36,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
get { return data.FileName; }
}
/// Return the file name as an unintrepreted byte array.
public byte[] GetRawFileName()
{
return data.GetRawFileName();
}
/// <summary>The modification time for the file.</summary>
public DateTime ModificationTime
{

View File

@ -0,0 +1,22 @@
using System;
using System.IO;
namespace Org.BouncyCastle.Security
{
public class EncryptionException
: IOException
{
public EncryptionException(
string message)
: base(message)
{
}
public EncryptionException(
string message,
Exception exception)
: base(message, exception)
{
}
}
}

View File

@ -315,12 +315,12 @@ namespace Org.BouncyCastle.OpenSsl
if (procType == "4,ENCRYPTED")
{
if (pFinder == null)
throw new InvalidOperationException("No password finder specified, but a password is required");
throw new PasswordException("No password finder specified, but a password is required");
char[] password = pFinder.GetPassword();
if (password == null)
throw new IOException("Password is null, but a password is required");
throw new PasswordException("Password is null, but a password is required");
string dekInfo = (string) fields["DEK-Info"];
string[] tknz = dekInfo.Split(',');

View File

@ -39,7 +39,7 @@ namespace Org.BouncyCastle.OpenSsl
{
string baseAlg, mode;
if (!ParseDekAlgName(dekAlgName, out baseAlg, out mode))
throw new ArgumentException("Unknown DEK algorithm: " + dekAlgName, "dekAlgName");
throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName);
string padding;
switch (mode)
@ -53,7 +53,7 @@ namespace Org.BouncyCastle.OpenSsl
padding = "NoPadding";
break;
default:
throw new ArgumentException("Unknown DEK algorithm: " + dekAlgName, "dekAlgName");
throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName);
}
string algorithm;
@ -87,7 +87,7 @@ namespace Org.BouncyCastle.OpenSsl
algorithm = "RC2";
break;
default:
throw new ArgumentException("Unknown DEK algorithm: " + dekAlgName, "dekAlgName");
throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName);
}
string cipherName = algorithm + "/" + mode + "/" + padding;

View File

@ -0,0 +1,22 @@
using System;
using System.IO;
namespace Org.BouncyCastle.Security
{
public class PasswordException
: IOException
{
public PasswordException(
string message)
: base(message)
{
}
public PasswordException(
string message,
Exception exception)
: base(message, exception)
{
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using Org.BouncyCastle.Utilities.Date;
namespace Org.BouncyCastle.Pkix
{
public class CertStatus
{
public const int Unrevoked = 11;
public const int Undetermined = 12;
private int status = Unrevoked;
DateTimeObject revocationDate = null;
/// <summary>
/// Returns the revocationDate.
/// </summary>
public DateTimeObject RevocationDate
{
get { return revocationDate; }
set { this.revocationDate = value; }
}
/// <summary>
/// Returns the certStatus.
/// </summary>
public int Status
{
get { return status; }
set { this.status = value; }
}
}
}

View File

@ -0,0 +1,57 @@
using System;
using System.Collections;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.X509;
namespace Org.BouncyCastle.Pkix
{
public abstract class PkixAttrCertChecker
{
/**
* Returns an immutable <code>Set</code> of X.509 attribute certificate
* extensions that this <code>PkixAttrCertChecker</code> supports or
* <code>null</code> if no extensions are supported.
* <p>
* Each element of the set is a <code>String</code> representing the
* Object Identifier (OID) of the X.509 extension that is supported.
* </p>
* <p>
* All X.509 attribute certificate extensions that a
* <code>PkixAttrCertChecker</code> might possibly be able to process
* should be included in the set.
* </p>
*
* @return an immutable <code>Set</code> of X.509 extension OIDs (in
* <code>String</code> format) supported by this
* <code>PkixAttrCertChecker</code>, or <code>null</code> if no
* extensions are supported
*/
public abstract ISet GetSupportedExtensions();
/**
* Performs checks on the specified attribute certificate. Every handled
* extension is rmeoved from the <code>unresolvedCritExts</code>
* collection.
*
* @param attrCert The attribute certificate to be checked.
* @param certPath The certificate path which belongs to the attribute
* certificate issuer public key certificate.
* @param holderCertPath The certificate path which belongs to the holder
* certificate.
* @param unresolvedCritExts a <code>Collection</code> of OID strings
* representing the current set of unresolved critical extensions
* @throws CertPathValidatorException if the specified attribute certificate
* does not pass the check.
*/
public abstract void Check(IX509AttributeCertificate attrCert, PkixCertPath certPath,
PkixCertPath holderCertPath, ICollection unresolvedCritExts);
/**
* Returns a clone of this object.
*
* @return a copy of this <code>PkixAttrCertChecker</code>
*/
public abstract PkixAttrCertChecker Clone();
}
}

View File

@ -0,0 +1,215 @@
using System;
using System.Collections;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Store;
namespace Org.BouncyCastle.Pkix
{
public class PkixAttrCertPathBuilder
{
/**
* Build and validate a CertPath using the given parameter.
*
* @param params PKIXBuilderParameters object containing all information to
* build the CertPath
*/
public virtual PkixCertPathBuilderResult Build(
PkixBuilderParameters pkixParams)
{
// search target certificates
IX509Selector certSelect = pkixParams.GetTargetConstraints();
if (!(certSelect is X509AttrCertStoreSelector))
{
throw new PkixCertPathBuilderException(
"TargetConstraints must be an instance of "
+ typeof(X509AttrCertStoreSelector).FullName
+ " for "
+ typeof(PkixAttrCertPathBuilder).FullName + " class.");
}
ICollection targets;
try
{
targets = PkixCertPathValidatorUtilities.FindCertificates(
(X509AttrCertStoreSelector)certSelect, pkixParams.GetStores());
}
catch (Exception e)
{
throw new PkixCertPathBuilderException("Error finding target attribute certificate.", e);
}
if (targets.Count == 0)
{
throw new PkixCertPathBuilderException(
"No attribute certificate found matching targetContraints.");
}
PkixCertPathBuilderResult result = null;
// check all potential target certificates
foreach (IX509AttributeCertificate cert in targets)
{
X509CertStoreSelector selector = new X509CertStoreSelector();
X509Name[] principals = cert.Issuer.GetPrincipals();
ISet issuers = new HashSet();
for (int i = 0; i < principals.Length; i++)
{
try
{
selector.Subject = principals[i];
issuers.AddAll(PkixCertPathValidatorUtilities.FindCertificates(selector, pkixParams.GetStores()));
issuers.AddAll(PkixCertPathValidatorUtilities.FindCertificates(selector, pkixParams.GetX509Stores()));
}
catch (Exception e)
{
throw new PkixCertPathBuilderException(
"Public key certificate for attribute certificate cannot be searched.",
e);
}
}
if (issuers.IsEmpty)
throw new PkixCertPathBuilderException("Public key certificate for attribute certificate cannot be found.");
IList certPathList = new ArrayList();
foreach (X509Certificate issuer in issuers)
{
result = Build(cert, issuer, pkixParams, certPathList);
if (result != null)
break;
}
if (result != null)
break;
}
if (result == null && certPathException != null)
{
throw new PkixCertPathBuilderException(
"Possible certificate chain could not be validated.",
certPathException);
}
if (result == null && certPathException == null)
{
throw new PkixCertPathBuilderException(
"Unable to find certificate chain.");
}
return result;
}
private Exception certPathException;
private PkixCertPathBuilderResult Build(
IX509AttributeCertificate attrCert,
X509Certificate tbvCert,
PkixBuilderParameters pkixParams,
IList tbvPath)
{
// If tbvCert is readily present in tbvPath, it indicates having run
// into a cycle in the
// PKI graph.
if (tbvPath.Contains(tbvCert))
return null;
// step out, the certificate is not allowed to appear in a certification
// chain
if (pkixParams.GetExcludedCerts().Contains(tbvCert))
return null;
// test if certificate path exceeds maximum length
if (pkixParams.MaxPathLength != -1)
{
if (tbvPath.Count - 1 > pkixParams.MaxPathLength)
return null;
}
tbvPath.Add(tbvCert);
PkixCertPathBuilderResult builderResult = null;
X509CertificateParser certParser = new X509CertificateParser();
PkixAttrCertPathValidator validator = new PkixAttrCertPathValidator();
try
{
// check whether the issuer of <tbvCert> is a TrustAnchor
if (PkixCertPathValidatorUtilities.FindTrustAnchor(tbvCert, pkixParams.GetTrustAnchors()) != null)
{
PkixCertPath certPath = new PkixCertPath(tbvPath);
PkixCertPathValidatorResult result;
try
{
result = validator.Validate(certPath, pkixParams);
}
catch (Exception e)
{
throw new Exception("Certification path could not be validated.", e);
}
return new PkixCertPathBuilderResult(certPath, result.TrustAnchor,
result.PolicyTree, result.SubjectPublicKey);
}
else
{
// add additional X.509 stores from locations in certificate
try
{
PkixCertPathValidatorUtilities.AddAdditionalStoresFromAltNames(tbvCert, pkixParams);
}
catch (CertificateParsingException e)
{
throw new Exception("No additional X.509 stores can be added from certificate locations.", e);
}
// try to get the issuer certificate from one of the stores
ISet issuers = new HashSet();
try
{
issuers.AddAll(PkixCertPathValidatorUtilities.FindIssuerCerts(tbvCert, pkixParams));
}
catch (Exception e)
{
throw new Exception("Cannot find issuer certificate for certificate in certification path.", e);
}
if (issuers.IsEmpty)
throw new Exception("No issuer certificate for certificate in certification path found.");
foreach (X509Certificate issuer in issuers)
{
// if untrusted self signed certificate continue
if (PkixCertPathValidatorUtilities.IsSelfIssued(issuer))
continue;
builderResult = Build(attrCert, issuer, pkixParams, tbvPath);
if (builderResult != null)
break;
}
}
}
catch (Exception e)
{
certPathException = new Exception("No valid certification path could be build.", e);
}
if (builderResult == null)
{
tbvPath.Remove(tbvCert);
}
return builderResult;
}
}
}

View File

@ -0,0 +1,76 @@
using System;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Store;
namespace Org.BouncyCastle.Pkix
{
/**
* CertPathValidatorSpi implementation for X.509 Attribute Certificates la RFC 3281.
*
* @see org.bouncycastle.x509.ExtendedPkixParameters
*/
public class PkixAttrCertPathValidator
// extends CertPathValidatorSpi
{
/**
* Validates an attribute certificate with the given certificate path.
*
* <p>
* <code>params</code> must be an instance of
* <code>ExtendedPkixParameters</code>.
* </p><p>
* The target constraints in the <code>params</code> must be an
* <code>X509AttrCertStoreSelector</code> with at least the attribute
* certificate criterion set. Obey that also target informations may be
* necessary to correctly validate this attribute certificate.
* </p><p>
* The attribute certificate issuer must be added to the trusted attribute
* issuers with {@link ExtendedPkixParameters#setTrustedACIssuers(Set)}.
* </p>
* @param certPath The certificate path which belongs to the attribute
* certificate issuer public key certificate.
* @param params The PKIX parameters.
* @return A <code>PKIXCertPathValidatorResult</code> of the result of
* validating the <code>certPath</code>.
* @throws InvalidAlgorithmParameterException if <code>params</code> is
* inappropriate for this validator.
* @throws CertPathValidatorException if the verification fails.
*/
public virtual PkixCertPathValidatorResult Validate(
PkixCertPath certPath,
PkixParameters pkixParams)
{
IX509Selector certSelect = pkixParams.GetTargetConstraints();
if (!(certSelect is X509AttrCertStoreSelector))
{
throw new ArgumentException(
"TargetConstraints must be an instance of " + typeof(X509AttrCertStoreSelector).FullName,
"pkixParams");
}
IX509AttributeCertificate attrCert = ((X509AttrCertStoreSelector) certSelect).AttributeCert;
PkixCertPath holderCertPath = Rfc3281CertPathUtilities.ProcessAttrCert1(attrCert, pkixParams);
PkixCertPathValidatorResult result = Rfc3281CertPathUtilities.ProcessAttrCert2(certPath, pkixParams);
X509Certificate issuerCert = (X509Certificate)certPath.Certificates[0];
Rfc3281CertPathUtilities.ProcessAttrCert3(issuerCert, pkixParams);
Rfc3281CertPathUtilities.ProcessAttrCert4(issuerCert, pkixParams);
Rfc3281CertPathUtilities.ProcessAttrCert5(attrCert, pkixParams);
// 6 already done in X509AttrCertStoreSelector
Rfc3281CertPathUtilities.ProcessAttrCert7(attrCert, certPath, holderCertPath, pkixParams);
Rfc3281CertPathUtilities.AdditionalChecks(attrCert, pkixParams);
DateTime date;
try
{
date = PkixCertPathValidatorUtilities.GetValidCertDateFromValidityModel(pkixParams, null, -1);
}
catch (Exception e)
{
throw new PkixCertPathValidatorException(
"Could not get validity date from attribute certificate.", e);
}
Rfc3281CertPathUtilities.CheckCrls(attrCert, pkixParams, issuerCert, date, certPath.Certificates);
return result;
}
}
}

View File

@ -0,0 +1,140 @@
using System;
using System.Text;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509.Store;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Pkix
{
/// <summary>
/// Summary description for PkixBuilderParameters.
/// </summary>
public class PkixBuilderParameters
: PkixParameters
{
private int maxPathLength = 5;
private ISet excludedCerts = new HashSet();
/**
* Returns an instance of <code>PkixBuilderParameters</code>.
* <p>
* This method can be used to get a copy from other
* <code>PKIXBuilderParameters</code>, <code>PKIXParameters</code>,
* and <code>ExtendedPKIXParameters</code> instances.
* </p>
*
* @param pkixParams The PKIX parameters to create a copy of.
* @return An <code>PkixBuilderParameters</code> instance.
*/
public static PkixBuilderParameters GetInstance(
PkixParameters pkixParams)
{
PkixBuilderParameters parameters = new PkixBuilderParameters(
pkixParams.GetTrustAnchors(),
new X509CertStoreSelector(pkixParams.GetTargetCertConstraints()));
parameters.SetParams(pkixParams);
return parameters;
}
public PkixBuilderParameters(
ISet trustAnchors,
IX509Selector targetConstraints)
: base(trustAnchors)
{
SetTargetCertConstraints(targetConstraints);
}
public virtual int MaxPathLength
{
get { return maxPathLength; }
set
{
if (value < -1)
{
throw new InvalidParameterException(
"The maximum path length parameter can not be less than -1.");
}
this.maxPathLength = value;
}
}
/// <summary>
/// Excluded certificates are not used for building a certification path.
/// </summary>
/// <returns>the excluded certificates.</returns>
public virtual ISet GetExcludedCerts()
{
return new HashSet(excludedCerts);
}
/// <summary>
/// Sets the excluded certificates which are not used for building a
/// certification path. If the <code>ISet</code> is <code>null</code> an
/// empty set is assumed.
/// </summary>
/// <remarks>
/// The given set is cloned to protect it against subsequent modifications.
/// </remarks>
/// <param name="excludedCerts">The excluded certificates to set.</param>
public virtual void SetExcludedCerts(
ISet excludedCerts)
{
if (excludedCerts == null)
{
excludedCerts = new HashSet();
}
else
{
this.excludedCerts = new HashSet(excludedCerts);
}
}
/**
* Can alse handle <code>ExtendedPKIXBuilderParameters</code> and
* <code>PKIXBuilderParameters</code>.
*
* @param params Parameters to set.
* @see org.bouncycastle.x509.ExtendedPKIXParameters#setParams(java.security.cert.PKIXParameters)
*/
protected override void SetParams(
PkixParameters parameters)
{
base.SetParams(parameters);
if (parameters is PkixBuilderParameters)
{
PkixBuilderParameters _params = (PkixBuilderParameters) parameters;
maxPathLength = _params.maxPathLength;
excludedCerts = new HashSet(_params.excludedCerts);
}
}
/**
* Makes a copy of this <code>PKIXParameters</code> object. Changes to the
* copy will not affect the original and vice versa.
*
* @return a copy of this <code>PKIXParameters</code> object
*/
public override object Clone()
{
PkixBuilderParameters parameters = new PkixBuilderParameters(
GetTrustAnchors(), GetTargetCertConstraints());
parameters.SetParams(this);
return parameters;
}
public override string ToString()
{
string nl = Platform.NewLine;
StringBuilder s = new StringBuilder();
s.Append("PkixBuilderParameters [" + nl);
s.Append(base.ToString());
s.Append(" Maximum Path Length: ");
s.Append(MaxPathLength);
s.Append(nl + "]" + nl);
return s.ToString();
}
}
}

View File

@ -0,0 +1,474 @@
using System;
using System.Collections;
using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Cms;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Pkix
{
/**
* An immutable sequence of certificates (a certification path).<br />
* <br />
* This is an abstract class that defines the methods common to all CertPaths.
* Subclasses can handle different kinds of certificates (X.509, PGP, etc.).<br />
* <br />
* All CertPath objects have a type, a list of Certificates, and one or more
* supported encodings. Because the CertPath class is immutable, a CertPath
* cannot change in any externally visible way after being constructed. This
* stipulation applies to all public fields and methods of this class and any
* added or overridden by subclasses.<br />
* <br />
* The type is a string that identifies the type of Certificates in the
* certification path. For each certificate cert in a certification path
* certPath, cert.getType().equals(certPath.getType()) must be true.<br />
* <br />
* The list of Certificates is an ordered List of zero or more Certificates.
* This List and all of the Certificates contained in it must be immutable.<br />
* <br />
* Each CertPath object must support one or more encodings so that the object
* can be translated into a byte array for storage or transmission to other
* parties. Preferably, these encodings should be well-documented standards
* (such as PKCS#7). One of the encodings supported by a CertPath is considered
* the default encoding. This encoding is used if no encoding is explicitly
* requested (for the {@link #getEncoded()} method, for instance).<br />
* <br />
* All CertPath objects are also Serializable. CertPath objects are resolved
* into an alternate {@link CertPathRep} object during serialization. This
* allows a CertPath object to be serialized into an equivalent representation
* regardless of its underlying implementation.<br />
* <br />
* CertPath objects can be created with a CertificateFactory or they can be
* returned by other classes, such as a CertPathBuilder.<br />
* <br />
* By convention, X.509 CertPaths (consisting of X509Certificates), are ordered
* starting with the target certificate and ending with a certificate issued by
* the trust anchor. That is, the issuer of one certificate is the subject of
* the following one. The certificate representing the
* {@link TrustAnchor TrustAnchor} should not be included in the certification
* path. Unvalidated X.509 CertPaths may not follow these conventions. PKIX
* CertPathValidators will detect any departure from these conventions that
* cause the certification path to be invalid and throw a
* CertPathValidatorException.<br />
* <br />
* <strong>Concurrent Access</strong><br />
* <br />
* All CertPath objects must be thread-safe. That is, multiple threads may
* concurrently invoke the methods defined in this class on a single CertPath
* object (or more than one) with no ill effects. This is also true for the List
* returned by CertPath.getCertificates.<br />
* <br />
* Requiring CertPath objects to be immutable and thread-safe allows them to be
* passed around to various pieces of code without worrying about coordinating
* access. Providing this thread-safety is generally not difficult, since the
* CertPath and List objects in question are immutable.
*
* @see CertificateFactory
* @see CertPathBuilder
*/
/// <summary>
/// CertPath implementation for X.509 certificates.
/// </summary>
public class PkixCertPath
// : CertPath
{
internal static IList certPathEncodings;
static PkixCertPath()
{
IList encodings = new ArrayList();
encodings.Add("PkiPath");
encodings.Add("PEM");
encodings.Add("PKCS7");
certPathEncodings = ArrayList.ReadOnly(encodings);
}
private IList certificates = new ArrayList();
/**
* @param certs
*/
private static IList SortCerts(
IList certs)
{
if (certs.Count < 2)
return certs;
X509Name issuer = ((X509Certificate)certs[0]).IssuerDN;
bool okay = true;
for (int i = 1; i != certs.Count; i++)
{
X509Certificate cert = (X509Certificate)certs[i];
if (issuer.Equivalent(cert.SubjectDN, true))
{
issuer = ((X509Certificate)certs[i]).IssuerDN;
}
else
{
okay = false;
break;
}
}
if (okay)
return certs;
// find end-entity cert
IList retList = new ArrayList(certs.Count);
IList orig = new ArrayList(certs);
for (int i = 0; i < certs.Count; i++)
{
X509Certificate cert = (X509Certificate)certs[i];
bool found = false;
X509Name subject = cert.SubjectDN;
foreach (X509Certificate c in certs)
{
if (c.IssuerDN.Equivalent(subject, true))
{
found = true;
break;
}
}
if (!found)
{
retList.Add(cert);
certs.RemoveAt(i);
}
}
// can only have one end entity cert - something's wrong, give up.
if (retList.Count > 1)
return orig;
for (int i = 0; i != retList.Count; i++)
{
issuer = ((X509Certificate)retList[i]).IssuerDN;
for (int j = 0; j < certs.Count; j++)
{
X509Certificate c = (X509Certificate)certs[j];
if (issuer.Equivalent(c.SubjectDN, true))
{
retList.Add(c);
certs.RemoveAt(j);
break;
}
}
}
// make sure all certificates are accounted for.
if (certs.Count > 0)
return orig;
return retList;
}
/**
* Creates a CertPath of the specified type.
* This constructor is protected because most users should use
* a CertificateFactory to create CertPaths.
* @param type the standard name of the type of Certificatesin this path
**/
public PkixCertPath(
ICollection certificates)
// : base("X.509")
{
this.certificates = SortCerts(new ArrayList(certificates));
}
public PkixCertPath(
Stream inStream)
: this(inStream, "PkiPath")
{
}
/**
* Creates a CertPath of the specified type.
* This constructor is protected because most users should use
* a CertificateFactory to create CertPaths.
*
* @param type the standard name of the type of Certificatesin this path
**/
public PkixCertPath(
Stream inStream,
String encoding)
// : base("X.509")
{
try
{
if (encoding.ToUpper().Equals("PkiPath".ToUpper()))
{
Asn1InputStream derInStream = new Asn1InputStream(inStream);
Asn1Object derObject = derInStream.ReadObject();
if (!(derObject is Asn1Sequence))
{
throw new CertificateException(
"input stream does not contain a ASN1 SEQUENCE while reading PkiPath encoded data to load CertPath");
}
IEnumerator e = ((Asn1Sequence)derObject).GetEnumerator();
Stream certInStream;
MemoryStream outStream;
DerOutputStream derOutStream;
certificates = new ArrayList();
while (e.MoveNext())
{
outStream = new MemoryStream();
derOutStream = new DerOutputStream(outStream);
derOutStream.WriteObject((Asn1Encodable)e.Current);
derOutStream.Close();
certInStream = new MemoryStream(outStream.ToArray(), false);
certificates.Insert(0, new X509CertificateParser().ReadCertificate(certInStream));
}
}
else if (encoding.ToUpper().Equals("PKCS7")
|| encoding.ToUpper().Equals("PEM"))
{
inStream = new BufferedStream(inStream);
certificates = new ArrayList();
X509CertificateParser certParser = new X509CertificateParser();
X509Certificate cert = null;
while ((cert = certParser.ReadCertificate(inStream)) != null)
{
certificates.Add(cert);
}
}
else
{
throw new CertificateException("unsupported encoding: " + encoding);
}
}
catch (IOException ex)
{
throw new CertificateException(
"IOException throw while decoding CertPath:\n"
+ ex.ToString());
}
this.certificates = SortCerts(certificates);
}
/**
* Returns an iteration of the encodings supported by this
* certification path, with the default encoding
* first. Attempts to modify the returned Iterator via its
* remove method result in an UnsupportedOperationException.
*
* @return an Iterator over the names of the supported encodings (as Strings)
**/
public virtual IEnumerable Encodings
{
get { return new EnumerableProxy(certPathEncodings); }
}
/**
* Compares this certification path for equality with the specified object.
* Two CertPaths are equal if and only if their types are equal and their
* certificate Lists (and by implication the Certificates in those Lists)
* are equal. A CertPath is never equal to an object that is not a CertPath.<br />
* <br />
* This algorithm is implemented by this method. If it is overridden, the
* behavior specified here must be maintained.
*
* @param other
* the object to test for equality with this certification path
*
* @return true if the specified object is equal to this certification path,
* false otherwise
*
* @see Object#hashCode() Object.hashCode()
*/
public override bool Equals(
object obj)
{
if (this == obj)
return true;
PkixCertPath other = obj as PkixCertPath;
if (other == null)
return false;
// if (!this.Type.Equals(other.Type))
// return false;
//return this.Certificates.Equals(other.Certificates);
// TODO Extract this to a utility class
IList thisCerts = this.Certificates;
IList otherCerts = other.Certificates;
if (thisCerts.Count != otherCerts.Count)
return false;
IEnumerator e1 = thisCerts.GetEnumerator();
IEnumerator e2 = thisCerts.GetEnumerator();
while (e1.MoveNext())
{
e2.MoveNext();
if (!Platform.Equals(e1.Current, e2.Current))
return false;
}
return true;
}
public override int GetHashCode()
{
// FIXME?
return this.Certificates.GetHashCode();
}
/**
* Returns the encoded form of this certification path, using
* the default encoding.
*
* @return the encoded bytes
* @exception CertificateEncodingException if an encoding error occurs
**/
public virtual byte[] GetEncoded()
{
foreach (object enc in Encodings)
{
if (enc is string)
{
return GetEncoded((string)enc);
}
}
return null;
}
/**
* Returns the encoded form of this certification path, using
* the specified encoding.
*
* @param encoding the name of the encoding to use
* @return the encoded bytes
* @exception CertificateEncodingException if an encoding error
* occurs or the encoding requested is not supported
*
*/
public virtual byte[] GetEncoded(
string encoding)
{
if (String.Compare(encoding, "PkiPath", true) == 0)
{
Asn1EncodableVector v = new Asn1EncodableVector();
for (int i = certificates.Count - 1; i >= 0; i--)
{
v.Add(ToAsn1Object((X509Certificate) certificates[i]));
}
return ToDerEncoded(new DerSequence(v));
}
else if (String.Compare(encoding, "PKCS7", true) == 0)
{
Asn1.Pkcs.ContentInfo encInfo = new Asn1.Pkcs.ContentInfo(
PkcsObjectIdentifiers.Data, null);
Asn1EncodableVector v = new Asn1EncodableVector();
for (int i = 0; i != certificates.Count; i++)
{
v.Add(ToAsn1Object((X509Certificate)certificates[i]));
}
Asn1.Pkcs.SignedData sd = new Asn1.Pkcs.SignedData(
new DerInteger(1),
new DerSet(),
encInfo,
new DerSet(v),
null,
new DerSet());
return ToDerEncoded(new Asn1.Pkcs.ContentInfo(PkcsObjectIdentifiers.SignedData, sd));
}
else if (String.Compare(encoding, "PEM", true) == 0)
{
MemoryStream bOut = new MemoryStream();
PemWriter pWrt = new PemWriter(new StreamWriter(bOut));
try
{
for (int i = 0; i != certificates.Count; i++)
{
pWrt.WriteObject(certificates[i]);
}
pWrt.Writer.Close();
}
catch (Exception)
{
throw new CertificateEncodingException("can't encode certificate for PEM encoded path");
}
return bOut.ToArray();
}
else
{
throw new CertificateEncodingException("unsupported encoding: " + encoding);
}
}
/// <summary>
/// Returns the list of certificates in this certification
/// path.
/// </summary>
public virtual IList Certificates
{
get { return ArrayList.ReadOnly(certificates); }
}
/**
* Return a DERObject containing the encoded certificate.
*
* @param cert the X509Certificate object to be encoded
*
* @return the DERObject
**/
private Asn1Object ToAsn1Object(
X509Certificate cert)
{
try
{
return Asn1Object.FromByteArray(cert.GetEncoded());
}
catch (Exception e)
{
throw new CertificateEncodingException("Exception while encoding certificate", e);
}
}
private byte[] ToDerEncoded(Asn1Encodable obj)
{
try
{
return obj.GetEncoded(Asn1Encodable.Der);
}
catch (IOException e)
{
throw new CertificateEncodingException("Exception thrown", e);
}
}
}
}

View File

@ -0,0 +1,205 @@
using System;
using System.Collections;
using System.Text;
using Org.BouncyCastle.Asn1.IsisMtt;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X500;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Store;
namespace Org.BouncyCastle.Pkix
{
/**
* Implements the PKIX CertPathBuilding algorithm for BouncyCastle.
*
* @see CertPathBuilderSpi
*/
public class PkixCertPathBuilder
// : CertPathBuilderSpi
{
/**
* Build and validate a CertPath using the given parameter.
*
* @param params PKIXBuilderParameters object containing all information to
* build the CertPath
*/
public virtual PkixCertPathBuilderResult Build(
PkixBuilderParameters pkixParams)
{
// search target certificates
IX509Selector certSelect = pkixParams.GetTargetCertConstraints();
if (!(certSelect is X509CertStoreSelector))
{
throw new PkixCertPathBuilderException(
"TargetConstraints must be an instance of "
+ typeof(X509CertStoreSelector).FullName + " for "
+ this.GetType() + " class.");
}
ISet targets = new HashSet();
try
{
targets.AddAll(PkixCertPathValidatorUtilities.FindCertificates((X509CertStoreSelector)certSelect, pkixParams.GetStores()));
targets.AddAll(PkixCertPathValidatorUtilities.FindCertificates((X509CertStoreSelector)certSelect, pkixParams.GetX509Stores()));
// TODO Should this include an entry for pkixParams.GetAdditionalStores() too?
}
catch (Exception e)
{
throw new PkixCertPathBuilderException(
"Error finding target certificate.", e);
}
if (targets.IsEmpty)
throw new PkixCertPathBuilderException("No certificate found matching targetContraints.");
PkixCertPathBuilderResult result = null;
IList certPathList = new ArrayList();
// check all potential target certificates
foreach (X509Certificate cert in targets)
{
result = Build(cert, pkixParams, certPathList);
if (result != null)
break;
}
if (result == null && certPathException != null)
{
throw new PkixCertPathBuilderException(certPathException.Message, certPathException.InnerException);
}
if (result == null && certPathException == null)
{
throw new PkixCertPathBuilderException("Unable to find certificate chain.");
}
return result;
}
private Exception certPathException;
protected virtual PkixCertPathBuilderResult Build(
X509Certificate tbvCert,
PkixBuilderParameters pkixParams,
IList tbvPath)
{
// If tbvCert is readily present in tbvPath, it indicates having run
// into a cycle in the PKI graph.
if (tbvPath.Contains(tbvCert))
return null;
// step out, the certificate is not allowed to appear in a certification
// chain.
if (pkixParams.GetExcludedCerts().Contains(tbvCert))
return null;
// test if certificate path exceeds maximum length
if (pkixParams.MaxPathLength != -1)
{
if (tbvPath.Count - 1 > pkixParams.MaxPathLength)
return null;
}
tbvPath.Add(tbvCert);
X509CertificateParser certParser = new X509CertificateParser();
PkixCertPathBuilderResult builderResult = null;
PkixCertPathValidator validator = new PkixCertPathValidator();
try
{
// check whether the issuer of <tbvCert> is a TrustAnchor
if (PkixCertPathValidatorUtilities.FindTrustAnchor(tbvCert, pkixParams.GetTrustAnchors()) != null)
{
// exception message from possibly later tried certification
// chains
PkixCertPath certPath = null;
try
{
certPath = new PkixCertPath(tbvPath);
}
catch (Exception e)
{
throw new Exception(
"Certification path could not be constructed from certificate list.",
e);
}
PkixCertPathValidatorResult result = null;
try
{
result = (PkixCertPathValidatorResult)validator.Validate(
certPath, pkixParams);
}
catch (Exception e)
{
throw new Exception(
"Certification path could not be validated.", e);
}
return new PkixCertPathBuilderResult(certPath, result.TrustAnchor,
result.PolicyTree, result.SubjectPublicKey);
}
else
{
// add additional X.509 stores from locations in certificate
try
{
PkixCertPathValidatorUtilities.AddAdditionalStoresFromAltNames(
tbvCert, pkixParams);
}
catch (CertificateParsingException e)
{
throw new Exception(
"No additiontal X.509 stores can be added from certificate locations.",
e);
}
// try to get the issuer certificate from one of the stores
HashSet issuers = new HashSet();
try
{
issuers.AddAll(PkixCertPathValidatorUtilities.FindIssuerCerts(tbvCert, pkixParams));
}
catch (Exception e)
{
throw new Exception(
"Cannot find issuer certificate for certificate in certification path.",
e);
}
if (issuers.IsEmpty)
throw new Exception("No issuer certificate for certificate in certification path found.");
foreach (X509Certificate issuer in issuers)
{
builderResult = Build(issuer, pkixParams, tbvPath);
if (builderResult != null)
break;
}
}
}
catch (Exception e)
{
certPathException = e;
}
if (builderResult == null)
{
tbvPath.Remove(tbvCert);
}
return builderResult;
}
}
}

View File

@ -0,0 +1,19 @@
using System;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Pkix
{
/// <summary>
/// Summary description for PkixCertPathBuilderException.
/// </summary>
public class PkixCertPathBuilderException : GeneralSecurityException
{
public PkixCertPathBuilderException() : base() { }
public PkixCertPathBuilderException(string message) : base(message) { }
public PkixCertPathBuilderException(string message, Exception exception) : base(message, exception) { }
}
}

View File

@ -0,0 +1,45 @@
using System;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkix;
namespace Org.BouncyCastle.Pkix
{
/// <summary>
/// Summary description for PkixCertPathBuilderResult.
/// </summary>
public class PkixCertPathBuilderResult
: PkixCertPathValidatorResult//, ICertPathBuilderResult
{
private PkixCertPath certPath;
public PkixCertPathBuilderResult(
PkixCertPath certPath,
TrustAnchor trustAnchor,
PkixPolicyNode policyTree,
AsymmetricKeyParameter subjectPublicKey)
: base(trustAnchor, policyTree, subjectPublicKey)
{
if (certPath == null)
throw new ArgumentNullException("certPath");
this.certPath = certPath;
}
public PkixCertPath CertPath
{
get { return certPath; }
}
public override string ToString()
{
StringBuilder s = new StringBuilder();
s.Append("SimplePKIXCertPathBuilderResult: [\n");
s.Append(" Certification Path: ").Append(CertPath).Append('\n');
s.Append(" Trust Anchor: ").Append(this.TrustAnchor.TrustedCert.IssuerDN.ToString()).Append('\n');
s.Append(" Subject Public Key: ").Append(this.SubjectPublicKey).Append("\n]");
return s.ToString();
}
}
}

View File

@ -0,0 +1,101 @@
using System;
using System.Collections;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.X509;
namespace Org.BouncyCastle.Pkix
{
public abstract class PkixCertPathChecker
{
protected PkixCertPathChecker()
{
}
/**
* Initializes the internal state of this <code>PKIXCertPathChecker</code>.
* <p>
* The <code>forward</code> flag specifies the order that certificates
* will be passed to the {@link #check check} method (forward or reverse). A
* <code>PKIXCertPathChecker</code> <b>must</b> support reverse checking
* and <b>may</b> support forward checking.
* </p>
*
* @param forward
* the order that certificates are presented to the
* <code>check</code> method. If <code>true</code>,
* certificates are presented from target to most-trusted CA
* (forward); if <code>false</code>, from most-trusted CA to
* target (reverse).
* @exception CertPathValidatorException
* if this <code>PKIXCertPathChecker</code> is unable to
* check certificates in the specified order; it should never
* be thrown if the forward flag is false since reverse
* checking must be supported
*/
public abstract void Init(bool forward);
//throws CertPathValidatorException;
/**
* Indicates if forward checking is supported. Forward checking refers to
* the ability of the <code>PKIXCertPathChecker</code> to perform its
* checks when certificates are presented to the <code>check</code> method
* in the forward direction (from target to most-trusted CA).
*
* @return <code>true</code> if forward checking is supported,
* <code>false</code> otherwise
*/
public abstract bool IsForwardCheckingSupported();
/**
* Returns an immutable <code>Set</code> of X.509 certificate extensions
* that this <code>PKIXCertPathChecker</code> supports (i.e. recognizes,
* is able to process), or <code>null</code> if no extensions are
* supported.
* <p>
* Each element of the set is a <code>String</code> representing the
* Object Identifier (OID) of the X.509 extension that is supported. The OID
* is represented by a set of nonnegative integers separated by periods.
* </p><p>
* All X.509 certificate extensions that a <code>PKIXCertPathChecker</code>
* might possibly be able to process should be included in the set.
* </p>
*
* @return an immutable <code>Set</code> of X.509 extension OIDs (in
* <code>String</code> format) supported by this
* <code>PKIXCertPathChecker</code>, or <code>null</code> if no
* extensions are supported
*/
public abstract ISet GetSupportedExtensions();
/**
* Performs the check(s) on the specified certificate using its internal
* state and removes any critical extensions that it processes from the
* specified collection of OID strings that represent the unresolved
* critical extensions. The certificates are presented in the order
* specified by the <code>init</code> method.
*
* @param cert
* the <code>Certificate</code> to be checked
* @param unresolvedCritExts
* a <code>Collection</code> of OID strings representing the
* current set of unresolved critical extensions
* @exception CertPathValidatorException
* if the specified certificate does not pass the check
*/
public abstract void Check(X509Certificate cert, ICollection unresolvedCritExts);
//throws CertPathValidatorException;
/**
* Returns a clone of this object. Calls the <code>Object.clone()</code>
* method. All subclasses which maintain state must support and override
* this method, if necessary.
*
* @return a copy of this <code>PKIXCertPathChecker</code>
*/
public virtual object Clone()
{
// TODO Check this
return base.MemberwiseClone();
}
}
}

View File

@ -0,0 +1,419 @@
using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Store;
namespace Org.BouncyCastle.Pkix
{
/**
* The <i>Service Provider Interface</i> (<b>SPI</b>)
* for the {@link CertPathValidator CertPathValidator} class. All
* <code>CertPathValidator</code> implementations must include a class (the
* SPI class) that extends this class (<code>CertPathValidatorSpi</code>)
* and implements all of its methods. In general, instances of this class
* should only be accessed through the <code>CertPathValidator</code> class.
* For details, see the Java Cryptography Architecture.<br />
* <br />
* <b>Concurrent Access</b><br />
* <br />
* Instances of this class need not be protected against concurrent
* access from multiple threads. Threads that need to access a single
* <code>CertPathValidatorSpi</code> instance concurrently should synchronize
* amongst themselves and provide the necessary locking before calling the
* wrapping <code>CertPathValidator</code> object.<br />
* <br />
* However, implementations of <code>CertPathValidatorSpi</code> may still
* encounter concurrency issues, since multiple threads each
* manipulating a different <code>CertPathValidatorSpi</code> instance need not
* synchronize.
*/
/// <summary>
/// CertPathValidatorSpi implementation for X.509 Certificate validation a la RFC
/// 3280.
/// </summary>
public class PkixCertPathValidator
{
public virtual PkixCertPathValidatorResult Validate(
PkixCertPath certPath,
PkixParameters paramsPkix)
{
if (paramsPkix.GetTrustAnchors() == null)
{
throw new ArgumentException(
"trustAnchors is null, this is not allowed for certification path validation.",
"parameters");
}
//
// 6.1.1 - inputs
//
//
// (a)
//
IList certs = certPath.Certificates;
int n = certs.Count;
if (certs.Count == 0)
throw new PkixCertPathValidatorException("Certification path is empty.", null, certPath, 0);
//
// (b)
//
// DateTime validDate = PkixCertPathValidatorUtilities.GetValidDate(paramsPkix);
//
// (c)
//
ISet userInitialPolicySet = paramsPkix.GetInitialPolicies();
//
// (d)
//
TrustAnchor trust;
try
{
trust = PkixCertPathValidatorUtilities.FindTrustAnchor(
(X509Certificate)certs[certs.Count - 1],
paramsPkix.GetTrustAnchors());
}
catch (Exception e)
{
throw new PkixCertPathValidatorException(e.Message, e, certPath, certs.Count - 1);
}
if (trust == null)
throw new PkixCertPathValidatorException("Trust anchor for certification path not found.", null, certPath, -1);
//
// (e), (f), (g) are part of the paramsPkix object.
//
IEnumerator certIter;
int index = 0;
int i;
// Certificate for each interation of the validation loop
// Signature information for each iteration of the validation loop
//
// 6.1.2 - setup
//
//
// (a)
//
IList[] policyNodes = new ArrayList[n + 1];
for (int j = 0; j < policyNodes.Length; j++)
{
policyNodes[j] = new ArrayList();
}
ISet policySet = new HashSet();
policySet.Add(Rfc3280CertPathUtilities.ANY_POLICY);
PkixPolicyNode validPolicyTree = new PkixPolicyNode(new ArrayList(), 0, policySet, null, new HashSet(),
Rfc3280CertPathUtilities.ANY_POLICY, false);
policyNodes[0].Add(validPolicyTree);
//
// (b) and (c)
//
PkixNameConstraintValidator nameConstraintValidator = new PkixNameConstraintValidator();
// (d)
//
int explicitPolicy;
ISet acceptablePolicies = new HashSet();
if (paramsPkix.IsExplicitPolicyRequired)
{
explicitPolicy = 0;
}
else
{
explicitPolicy = n + 1;
}
//
// (e)
//
int inhibitAnyPolicy;
if (paramsPkix.IsAnyPolicyInhibited)
{
inhibitAnyPolicy = 0;
}
else
{
inhibitAnyPolicy = n + 1;
}
//
// (f)
//
int policyMapping;
if (paramsPkix.IsPolicyMappingInhibited)
{
policyMapping = 0;
}
else
{
policyMapping = n + 1;
}
//
// (g), (h), (i), (j)
//
AsymmetricKeyParameter workingPublicKey;
X509Name workingIssuerName;
X509Certificate sign = trust.TrustedCert;
try
{
if (sign != null)
{
workingIssuerName = sign.SubjectDN;
workingPublicKey = sign.GetPublicKey();
}
else
{
workingIssuerName = new X509Name(trust.CAName);
workingPublicKey = trust.CAPublicKey;
}
}
catch (ArgumentException ex)
{
throw new PkixCertPathValidatorException("Subject of trust anchor could not be (re)encoded.", ex, certPath,
-1);
}
AlgorithmIdentifier workingAlgId = null;
try
{
workingAlgId = PkixCertPathValidatorUtilities.GetAlgorithmIdentifier(workingPublicKey);
}
catch (PkixCertPathValidatorException e)
{
throw new PkixCertPathValidatorException(
"Algorithm identifier of public key of trust anchor could not be read.", e, certPath, -1);
}
DerObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.ObjectID;
Asn1Encodable workingPublicKeyParameters = workingAlgId.Parameters;
//
// (k)
//
int maxPathLength = n;
//
// 6.1.3
//
X509CertStoreSelector certConstraints = paramsPkix.GetTargetCertConstraints();
if (certConstraints != null && !certConstraints.Match((X509Certificate)certs[0]))
{
throw new PkixCertPathValidatorException(
"Target certificate in certification path does not match targetConstraints.", null, certPath, 0);
}
//
// initialize CertPathChecker's
//
IList pathCheckers = paramsPkix.GetCertPathCheckers();
certIter = pathCheckers.GetEnumerator();
while (certIter.MoveNext())
{
((PkixCertPathChecker)certIter.Current).Init(false);
}
X509Certificate cert = null;
for (index = certs.Count - 1; index >= 0; index--)
{
// try
// {
//
// i as defined in the algorithm description
//
i = n - index;
//
// set certificate to be checked in this round
// sign and workingPublicKey and workingIssuerName are set
// at the end of the for loop and initialized the
// first time from the TrustAnchor
//
cert = (X509Certificate)certs[index];
//
// 6.1.3
//
Rfc3280CertPathUtilities.ProcessCertA(certPath, paramsPkix, index, workingPublicKey,
workingIssuerName, sign);
Rfc3280CertPathUtilities.ProcessCertBC(certPath, index, nameConstraintValidator);
validPolicyTree = Rfc3280CertPathUtilities.ProcessCertD(certPath, index,
acceptablePolicies, validPolicyTree, policyNodes, inhibitAnyPolicy);
validPolicyTree = Rfc3280CertPathUtilities.ProcessCertE(certPath, index, validPolicyTree);
Rfc3280CertPathUtilities.ProcessCertF(certPath, index, validPolicyTree, explicitPolicy);
//
// 6.1.4
//
if (i != n)
{
if (cert != null && cert.Version == 1)
{
throw new PkixCertPathValidatorException(
"Version 1 certificates can't be used as CA ones.", null, certPath, index);
}
Rfc3280CertPathUtilities.PrepareNextCertA(certPath, index);
validPolicyTree = Rfc3280CertPathUtilities.PrepareCertB(certPath, index, policyNodes,
validPolicyTree, policyMapping);
Rfc3280CertPathUtilities.PrepareNextCertG(certPath, index, nameConstraintValidator);
// (h)
explicitPolicy = Rfc3280CertPathUtilities.PrepareNextCertH1(certPath, index, explicitPolicy);
policyMapping = Rfc3280CertPathUtilities.PrepareNextCertH2(certPath, index, policyMapping);
inhibitAnyPolicy = Rfc3280CertPathUtilities.PrepareNextCertH3(certPath, index, inhibitAnyPolicy);
//
// (i)
//
explicitPolicy = Rfc3280CertPathUtilities.PrepareNextCertI1(certPath, index, explicitPolicy);
policyMapping = Rfc3280CertPathUtilities.PrepareNextCertI2(certPath, index, policyMapping);
// (j)
inhibitAnyPolicy = Rfc3280CertPathUtilities.PrepareNextCertJ(certPath, index, inhibitAnyPolicy);
// (k)
Rfc3280CertPathUtilities.PrepareNextCertK(certPath, index);
// (l)
maxPathLength = Rfc3280CertPathUtilities.PrepareNextCertL(certPath, index, maxPathLength);
// (m)
maxPathLength = Rfc3280CertPathUtilities.PrepareNextCertM(certPath, index, maxPathLength);
// (n)
Rfc3280CertPathUtilities.PrepareNextCertN(certPath, index);
ISet criticalExtensions1 = cert.GetCriticalExtensionOids();
if (criticalExtensions1 != null)
{
criticalExtensions1 = new HashSet(criticalExtensions1);
// these extensions are handled by the algorithm
criticalExtensions1.Remove(X509Extensions.KeyUsage.Id);
criticalExtensions1.Remove(X509Extensions.CertificatePolicies.Id);
criticalExtensions1.Remove(X509Extensions.PolicyMappings.Id);
criticalExtensions1.Remove(X509Extensions.InhibitAnyPolicy.Id);
criticalExtensions1.Remove(X509Extensions.IssuingDistributionPoint.Id);
criticalExtensions1.Remove(X509Extensions.DeltaCrlIndicator.Id);
criticalExtensions1.Remove(X509Extensions.PolicyConstraints.Id);
criticalExtensions1.Remove(X509Extensions.BasicConstraints.Id);
criticalExtensions1.Remove(X509Extensions.SubjectAlternativeName.Id);
criticalExtensions1.Remove(X509Extensions.NameConstraints.Id);
}
else
{
criticalExtensions1 = new HashSet();
}
// (o)
Rfc3280CertPathUtilities.PrepareNextCertO(certPath, index, criticalExtensions1, pathCheckers);
// set signing certificate for next round
sign = cert;
// (c)
workingIssuerName = sign.SubjectDN;
// (d)
try
{
workingPublicKey = PkixCertPathValidatorUtilities.GetNextWorkingKey(certPath.Certificates, index);
}
catch (PkixCertPathValidatorException e)
{
throw new PkixCertPathValidatorException("Next working key could not be retrieved.", e, certPath, index);
}
workingAlgId = PkixCertPathValidatorUtilities.GetAlgorithmIdentifier(workingPublicKey);
// (f)
workingPublicKeyAlgorithm = workingAlgId.ObjectID;
// (e)
workingPublicKeyParameters = workingAlgId.Parameters;
}
}
//
// 6.1.5 Wrap-up procedure
//
explicitPolicy = Rfc3280CertPathUtilities.WrapupCertA(explicitPolicy, cert);
explicitPolicy = Rfc3280CertPathUtilities.WrapupCertB(certPath, index + 1, explicitPolicy);
//
// (c) (d) and (e) are already done
//
//
// (f)
//
ISet criticalExtensions = cert.GetCriticalExtensionOids();
if (criticalExtensions != null)
{
criticalExtensions = new HashSet(criticalExtensions);
// Requires .Id
// these extensions are handled by the algorithm
criticalExtensions.Remove(X509Extensions.KeyUsage.Id);
criticalExtensions.Remove(X509Extensions.CertificatePolicies.Id);
criticalExtensions.Remove(X509Extensions.PolicyMappings.Id);
criticalExtensions.Remove(X509Extensions.InhibitAnyPolicy.Id);
criticalExtensions.Remove(X509Extensions.IssuingDistributionPoint.Id);
criticalExtensions.Remove(X509Extensions.DeltaCrlIndicator.Id);
criticalExtensions.Remove(X509Extensions.PolicyConstraints.Id);
criticalExtensions.Remove(X509Extensions.BasicConstraints.Id);
criticalExtensions.Remove(X509Extensions.SubjectAlternativeName.Id);
criticalExtensions.Remove(X509Extensions.NameConstraints.Id);
criticalExtensions.Remove(X509Extensions.CrlDistributionPoints.Id);
}
else
{
criticalExtensions = new HashSet();
}
Rfc3280CertPathUtilities.WrapupCertF(certPath, index + 1, pathCheckers, criticalExtensions);
PkixPolicyNode intersection = Rfc3280CertPathUtilities.WrapupCertG(certPath, paramsPkix, userInitialPolicySet,
index + 1, policyNodes, validPolicyTree, acceptablePolicies);
if ((explicitPolicy > 0) || (intersection != null))
{
return new PkixCertPathValidatorResult(trust, intersection, cert.GetPublicKey());
}
throw new PkixCertPathValidatorException("Path processing failed on policy.", null, certPath, index);
}
}
}

View File

@ -0,0 +1,218 @@
using System;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Pkix
{
/**
* An exception indicating one of a variety of problems encountered when
* validating a certification path. <br />
* <br />
* A <code>CertPathValidatorException</code> provides support for wrapping
* exceptions. The {@link #getCause getCause} method returns the throwable,
* if any, that caused this exception to be thrown. <br />
* <br />
* A <code>CertPathValidatorException</code> may also include the
* certification path that was being validated when the exception was thrown
* and the index of the certificate in the certification path that caused the
* exception to be thrown. Use the {@link #getCertPath getCertPath} and
* {@link #getIndex getIndex} methods to retrieve this information.<br />
* <br />
* <b>Concurrent Access</b><br />
* <br />
* Unless otherwise specified, the methods defined in this class are not
* thread-safe. Multiple threads that need to access a single
* object concurrently should synchronize amongst themselves and
* provide the necessary locking. Multiple threads each manipulating
* separate objects need not synchronize.
*
* @see CertPathValidator
**/
public class PkixCertPathValidatorException : GeneralSecurityException
{
private Exception cause;
private PkixCertPath certPath;
private int index = -1;
public PkixCertPathValidatorException() : base() { }
/// <summary>
/// Creates a <code>PkixCertPathValidatorException</code> with the given detail
/// message. A detail message is a <code>String</code> that describes this
/// particular exception.
/// </summary>
/// <param name="message">the detail message</param>
public PkixCertPathValidatorException(string message) : base(message) { }
/// <summary>
/// Creates a <code>PkixCertPathValidatorException</code> with the specified
/// detail message and cause.
/// </summary>
/// <param name="message">the detail message</param>
/// <param name="cause">the cause (which is saved for later retrieval by the
/// {@link #getCause getCause()} method). (A <code>null</code>
/// value is permitted, and indicates that the cause is
/// nonexistent or unknown.)</param>
public PkixCertPathValidatorException(string message, Exception cause) : base(message)
{
this.cause = cause;
}
/// <summary>
/// Creates a <code>PkixCertPathValidatorException</code> with the specified
/// detail message, cause, certification path, and index.
/// </summary>
/// <param name="message">the detail message (or <code>null</code> if none)</param>
/// <param name="cause">the cause (or <code>null</code> if none)</param>
/// <param name="certPath">the certification path that was in the process of being
/// validated when the error was encountered</param>
/// <param name="index">the index of the certificate in the certification path that</param> *
public PkixCertPathValidatorException(
string message,
Exception cause,
PkixCertPath certPath,
int index)
: base(message)
{
if (certPath == null && index != -1)
{
throw new ArgumentNullException(
"certPath = null and index != -1");
}
if (index < -1
|| (certPath != null && index >= certPath.Certificates.Count))
{
throw new IndexOutOfRangeException(
" index < -1 or out of bound of certPath.getCertificates()");
}
this.cause = cause;
this.certPath = certPath;
this.index = index;
}
//
// Prints a stack trace to a <code>PrintWriter</code>, including the
// backtrace of the cause, if any.
//
// @param pw
// the <code>PrintWriter</code> to use for output
//
// public void printStackTrace(PrintWriter pw)
// {
// super.printStackTrace(pw);
// if (getCause() != null)
// {
// getCause().printStackTrace(pw);
// }
// }
//}
// /**
// * Creates a <code>CertPathValidatorException</code> that wraps the
// * specified throwable. This allows any exception to be converted into a
// * <code>CertPathValidatorException</code>, while retaining information
// * about the wrapped exception, which may be useful for debugging. The
// * detail message is set to (<code>cause==null ? null : cause.toString()
// * </code>)
// * (which typically contains the class and detail message of cause).
// *
// * @param cause
// * the cause (which is saved for later retrieval by the
// * {@link #getCause getCause()} method). (A <code>null</code>
// * value is permitted, and indicates that the cause is
// * nonexistent or unknown.)
// */
// public PkixCertPathValidatorException(Throwable cause)
// {
// this.cause = cause;
// }
//
/// <summary>
/// Returns the detail message for this <code>CertPathValidatorException</code>.
/// </summary>
/// <returns>the detail message, or <code>null</code> if neither the message nor cause were specified</returns>
public override string Message
{
get
{
string message = base.Message;
if (message != null)
{
return message;
}
if (cause != null)
{
return cause.Message;
}
return null;
}
}
/**
* Returns the certification path that was being validated when the
* exception was thrown.
*
* @return the <code>CertPath</code> that was being validated when the
* exception was thrown (or <code>null</code> if not specified)
*/
public PkixCertPath CertPath
{
get { return certPath; }
}
/**
* Returns the index of the certificate in the certification path that
* caused the exception to be thrown. Note that the list of certificates in
* a <code>CertPath</code> is zero based. If no index has been set, -1 is
* returned.
*
* @return the index that has been set, or -1 if none has been set
*/
public int Index
{
get { return index; }
}
// /**
// * Returns the cause of this <code>CertPathValidatorException</code> or
// * <code>null</code> if the cause is nonexistent or unknown.
// *
// * @return the cause of this throwable or <code>null</code> if the cause
// * is nonexistent or unknown.
// */
// public Throwable getCause()
// {
// return cause;
// }
//
// /**
// * Returns a string describing this exception, including a description of
// * the internal (wrapped) cause if there is one.
// *
// * @return a string representation of this
// * <code>CertPathValidatorException</code>
// */
// public String toString()
// {
// StringBuffer sb = new StringBuffer();
// String s = getMessage();
// if (s != null)
// {
// sb.append(s);
// }
// if (getIndex() >= 0)
// {
// sb.append("index in certpath: ").append(getIndex()).append('\n');
// sb.append(getCertPath());
// }
// return sb.toString();
// }
}
}

View File

@ -0,0 +1,69 @@
using System;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Pkix
{
/// <summary>
/// Summary description for PkixCertPathValidatorResult.
/// </summary>
public class PkixCertPathValidatorResult
//: ICertPathValidatorResult
{
private TrustAnchor trustAnchor;
private PkixPolicyNode policyTree;
private AsymmetricKeyParameter subjectPublicKey;
public PkixPolicyNode PolicyTree
{
get { return this.policyTree; }
}
public TrustAnchor TrustAnchor
{
get { return this.trustAnchor; }
}
public AsymmetricKeyParameter SubjectPublicKey
{
get { return this.subjectPublicKey; }
}
public PkixCertPathValidatorResult(
TrustAnchor trustAnchor,
PkixPolicyNode policyTree,
AsymmetricKeyParameter subjectPublicKey)
{
if (subjectPublicKey == null)
{
throw new NullReferenceException("subjectPublicKey must be non-null");
}
if (trustAnchor == null)
{
throw new NullReferenceException("trustAnchor must be non-null");
}
this.trustAnchor = trustAnchor;
this.policyTree = policyTree;
this.subjectPublicKey = subjectPublicKey;
}
public object Clone()
{
return new PkixCertPathValidatorResult(this.TrustAnchor, this.PolicyTree, this.SubjectPublicKey);
}
public override String ToString()
{
StringBuilder sB = new StringBuilder();
sB.Append("PKIXCertPathValidatorResult: [ \n");
sB.Append(" Trust Anchor: ").Append(this.TrustAnchor).Append('\n');
sB.Append(" Policy Tree: ").Append(this.PolicyTree).Append('\n');
sB.Append(" Subject Public Key: ").Append(this.SubjectPublicKey).Append("\n]");
return sB.ToString();
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
using System;
namespace Org.BouncyCastle.Pkix
{
public class PkixNameConstraintValidatorException : Exception
{
public PkixNameConstraintValidatorException(String msg)
: base(msg)
{
}
}
}

View File

@ -0,0 +1,948 @@
using System;
using System.Collections;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.Utilities.Date;
using Org.BouncyCastle.X509.Store;
namespace Org.BouncyCastle.Pkix
{
/// <summary>
/// Summary description for PkixParameters.
/// </summary>
public class PkixParameters
// : ICertPathParameters
{
// TODO Put the validity models in an enumeration?
/**
* This is the default PKIX validity model. Actually there are two variants
* of this: The PKIX model and the modified PKIX model. The PKIX model
* verifies that all involved certificates must have been valid at the
* current time. The modified PKIX model verifies that all involved
* certificates were valid at the signing time. Both are indirectly choosen
* with the {@link PKIXParameters#setDate(java.util.Date)} method, so this
* methods sets the Date when <em>all</em> certificates must have been
* valid.
*/
public const int PkixValidityModel = 0;
/**
* This model uses the following validity model. Each certificate must have
* been valid at the moment where is was used. That means the end
* certificate must have been valid at the time the signature was done. The
* CA certificate which signed the end certificate must have been valid,
* when the end certificate was signed. The CA (or Root CA) certificate must
* have been valid, when the CA certificate was signed and so on. So the
* {@link PKIXParameters#setDate(java.util.Date)} method sets the time, when
* the <em>end certificate</em> must have been valid. <p/> It is used e.g.
* in the German signature law.
*/
public const int ChainValidityModel = 1;
private ISet trustAnchors;
private DateTimeObject date;
private IList certPathCheckers;
// TODO Decide whether to separate into certs/crl stores
// TODO ExtendedPkixParameters already has stores?
private ArrayList x509Stores;
private bool revocationEnabled = true;
private ISet initialPolicies;
//private bool checkOnlyEECertificateCrl = false;
private bool explicitPolicyRequired = false;
private bool anyPolicyInhibited = false;
private bool policyMappingInhibited = false;
private bool policyQualifiersRejected = true;
private IX509Selector certSelector;
private IList stores; /// TODO Redundant with other stores above?
private IX509Selector selector;
private bool additionalLocationsEnabled;
private IList additionalStores;
private ISet trustedACIssuers;
private ISet necessaryACAttributes;
private ISet prohibitedACAttributes;
private ISet attrCertCheckers;
private int validityModel = PkixValidityModel;
private bool useDeltas = false;
/**
* Creates an instance of PKIXParameters with the specified Set of
* most-trusted CAs. Each element of the set is a TrustAnchor.<br />
* <br />
* Note that the Set is copied to protect against subsequent modifications.
*
* @param trustAnchors
* a Set of TrustAnchors
*
* @exception InvalidAlgorithmParameterException
* if the specified Set is empty
* <code>(trustAnchors.isEmpty() == true)</code>
* @exception NullPointerException
* if the specified Set is <code>null</code>
* @exception ClassCastException
* if any of the elements in the Set are not of type
* <code>java.security.cert.TrustAnchor</code>
*/
public PkixParameters(
ISet trustAnchors)
{
SetTrustAnchors(trustAnchors);
this.initialPolicies = new HashSet();
this.certPathCheckers = new ArrayList();
this.x509Stores = new ArrayList();
this.stores = new ArrayList();
this.additionalStores = new ArrayList();
this.trustedACIssuers = new HashSet();
this.necessaryACAttributes = new HashSet();
this.prohibitedACAttributes = new HashSet();
this.attrCertCheckers = new HashSet();
}
// TODO implement for Pkcs12Store?
// /**
// * Creates an instance of <code>PKIXParameters</code> that
// * populates the set of most-trusted CAs from the trusted
// * certificate entries contained in the specified <code>KeyStore</code>.
// * Only keystore entries that contain trusted <code>X509Certificates</code>
// * are considered; all other certificate types are ignored.
// *
// * @param keystore a <code>KeyStore</code> from which the set of
// * most-trusted CAs will be populated
// * @throws KeyStoreException if the keystore has not been initialized
// * @throws InvalidAlgorithmParameterException if the keystore does
// * not contain at least one trusted certificate entry
// * @throws NullPointerException if the keystore is <code>null</code>
// */
// public PkixParameters(
// KeyStore keystore)
//// throws KeyStoreException, InvalidAlgorithmParameterException
// {
// if (keystore == null)
// throw new ArgumentNullException("keystore");
// ISet hashSet = new HashSet();
// foreach (string alias in keystore.aliases())
// {
// if (keystore.isCertificateEntry(alias))
// {
// Certificate cert = keystore.getCertificate(alias);
// if (cert is X509Certificate)
// {
// hashSet.add(new TrustAnchor((X509Certificate)cert, null));
// }
// }
// }
// SetTrustAnchors(hashSet);
// this.initialPolicies = new HashSet();
// this.certPathCheckers = new ArrayList();
// this.x509Stores = new ArrayList();
// }
public virtual bool IsRevocationEnabled
{
get { return revocationEnabled; }
set { revocationEnabled = value; }
}
public virtual bool IsExplicitPolicyRequired
{
get { return explicitPolicyRequired; }
set { this.explicitPolicyRequired = value; }
}
public virtual bool IsAnyPolicyInhibited
{
get { return anyPolicyInhibited; }
set { this.anyPolicyInhibited = value; }
}
public virtual bool IsPolicyMappingInhibited
{
get { return policyMappingInhibited; }
set { this.policyMappingInhibited = value; }
}
public virtual bool IsPolicyQualifiersRejected
{
get { return policyQualifiersRejected; }
set { this.policyQualifiersRejected = value; }
}
//public bool IsCheckOnlyEECertificateCrl
//{
// get { return this.checkOnlyEECertificateCrl; }
// set { this.checkOnlyEECertificateCrl = value; }
//}
public virtual DateTimeObject Date
{
get { return this.date; }
set { this.date = value; }
}
// Returns a Set of the most-trusted CAs.
public virtual ISet GetTrustAnchors()
{
return new HashSet(this.trustAnchors);
}
// Sets the set of most-trusted CAs.
// Set is copied to protect against subsequent modifications.
public virtual void SetTrustAnchors(
ISet tas)
{
if (tas == null)
throw new ArgumentNullException("value");
if (tas.IsEmpty)
throw new ArgumentException("non-empty set required", "value");
// Explicit copy to enforce type-safety
this.trustAnchors = new HashSet();
foreach (TrustAnchor ta in tas)
{
if (ta != null)
{
trustAnchors.Add(ta);
}
}
}
/**
* Sets the list of IX509Store's to be used in finding certificates and CRLs.
* May be null, in which case no IX509Store's will be used. The first
* IX509Store's in the list may be preferred to those that appear later.<br />
* <br />
* Note that the IList is copied to protect against subsequent modifications.<br />
* <br />
*
* @param stores
* a IList of IX509Store's (or <code>null</code>)
*
* @exception InvalidCastException
* if any of the elements in the list are not of type
* <code>IX509Store</code>
*
* @see #GetX509Stores()
*/
public virtual void SetX509Stores(
IList stores)
{
ArrayList newStores = new ArrayList();
if (stores != null && stores.Count != 0)
{
foreach (IX509Store obj in stores)
{
newStores.Add(obj);
}
this.x509Stores = newStores;
}
}
public virtual void AddX509Store(
IX509Store x509Store)
{
this.x509Stores.Add(x509Store);
}
/**
* Returns an immutable List of IX509Stores that are used to find certificates.
*
* @return an immutable List of IX509Stores (may be empty, but never
* <code>null</code>)
*
* @see #setCertStores(java.util.List)
*/
public virtual IList GetX509Stores()
{
return new ArrayList(x509Stores);
}
/**
* Returns the required constraints on the target certificate. The
* constraints are returned as an instance of CertSelector. If
* <code>null</code>, no constraints are defined.<br />
* <br />
* Note that the CertSelector returned is cloned to protect against
* subsequent modifications.
*
* @return a CertSelector specifying the constraints on the target
* certificate (or <code>null</code>)
*
* @see #setTargetCertConstraints(CertSelector)
*/
public virtual X509CertStoreSelector GetTargetCertConstraints()
{
if (certSelector == null)
{
return null;
}
return (X509CertStoreSelector)certSelector.Clone();
}
/**
* Sets the required constraints on the target certificate. The constraints
* are specified as an instance of CertSelector. If null, no constraints are
* defined.<br />
* <br />
* Note that the CertSelector specified is cloned to protect against
* subsequent modifications.
*
* @param selector
* a CertSelector specifying the constraints on the target
* certificate (or <code>null</code>)
*
* @see #getTargetCertConstraints()
*/
public virtual void SetTargetCertConstraints(
IX509Selector selector)
{
if (selector == null)
{
certSelector = null;
}
else
{
certSelector = (IX509Selector)selector.Clone();
}
}
/**
* Returns an immutable Set of initial policy identifiers (OID strings),
* indicating that any one of these policies would be acceptable to the
* certificate user for the purposes of certification path processing. The
* default return value is an empty <code>Set</code>, which is
* interpreted as meaning that any policy would be acceptable.
*
* @return an immutable <code>Set</code> of initial policy OIDs in String
* format, or an empty <code>Set</code> (implying any policy is
* acceptable). Never returns <code>null</code>.
*
* @see #setInitialPolicies(java.util.Set)
*/
public virtual ISet GetInitialPolicies()
{
ISet returnSet = initialPolicies;
// TODO Can it really be null?
if (initialPolicies == null)
{
returnSet = new HashSet();
}
return new HashSet(returnSet);
}
/**
* Sets the <code>Set</code> of initial policy identifiers (OID strings),
* indicating that any one of these policies would be acceptable to the
* certificate user for the purposes of certification path processing. By
* default, any policy is acceptable (i.e. all policies), so a user that
* wants to allow any policy as acceptable does not need to call this
* method, or can call it with an empty <code>Set</code> (or
* <code>null</code>).<br />
* <br />
* Note that the Set is copied to protect against subsequent modifications.<br />
* <br />
*
* @param initialPolicies
* a Set of initial policy OIDs in String format (or
* <code>null</code>)
*
* @exception ClassCastException
* if any of the elements in the set are not of type String
*
* @see #getInitialPolicies()
*/
public virtual void SetInitialPolicies(
ISet initialPolicies)
{
this.initialPolicies = new HashSet();
if (initialPolicies != null)
{
foreach (string obj in initialPolicies)
{
if (obj != null)
{
this.initialPolicies.Add(obj);
}
}
}
}
/**
* Sets a <code>List</code> of additional certification path checkers. If
* the specified List contains an object that is not a PKIXCertPathChecker,
* it is ignored.<br />
* <br />
* Each <code>PKIXCertPathChecker</code> specified implements additional
* checks on a certificate. Typically, these are checks to process and
* verify private extensions contained in certificates. Each
* <code>PKIXCertPathChecker</code> should be instantiated with any
* initialization parameters needed to execute the check.<br />
* <br />
* This method allows sophisticated applications to extend a PKIX
* <code>CertPathValidator</code> or <code>CertPathBuilder</code>. Each
* of the specified PKIXCertPathCheckers will be called, in turn, by a PKIX
* <code>CertPathValidator</code> or <code>CertPathBuilder</code> for
* each certificate processed or validated.<br />
* <br />
* Regardless of whether these additional PKIXCertPathCheckers are set, a
* PKIX <code>CertPathValidator</code> or <code>CertPathBuilder</code>
* must perform all of the required PKIX checks on each certificate. The one
* exception to this rule is if the RevocationEnabled flag is set to false
* (see the {@link #setRevocationEnabled(boolean) setRevocationEnabled}
* method).<br />
* <br />
* Note that the List supplied here is copied and each PKIXCertPathChecker
* in the list is cloned to protect against subsequent modifications.
*
* @param checkers
* a List of PKIXCertPathCheckers. May be null, in which case no
* additional checkers will be used.
* @exception ClassCastException
* if any of the elements in the list are not of type
* <code>java.security.cert.PKIXCertPathChecker</code>
* @see #getCertPathCheckers()
*/
public virtual void SetCertPathCheckers(IList checkers)
{
certPathCheckers = new ArrayList();
if (checkers != null)
{
foreach (PkixCertPathChecker obj in checkers)
{
certPathCheckers.Add(obj.Clone());
}
}
}
/**
* Returns the List of certification path checkers. The returned List is
* immutable, and each PKIXCertPathChecker in the List is cloned to protect
* against subsequent modifications.
*
* @return an immutable List of PKIXCertPathCheckers (may be empty, but not
* <code>null</code>)
*
* @see #setCertPathCheckers(java.util.List)
*/
public virtual IList GetCertPathCheckers()
{
IList checkers = new ArrayList();
foreach (PkixCertPathChecker obj in certPathCheckers)
{
checkers.Add(obj.Clone());
}
return ArrayList.ReadOnly(checkers);
}
/**
* Adds a <code>PKIXCertPathChecker</code> to the list of certification
* path checkers. See the {@link #setCertPathCheckers setCertPathCheckers}
* method for more details.
* <p>
* Note that the <code>PKIXCertPathChecker</code> is cloned to protect
* against subsequent modifications.</p>
*
* @param checker a <code>PKIXCertPathChecker</code> to add to the list of
* checks. If <code>null</code>, the checker is ignored (not added to list).
*/
public virtual void AddCertPathChecker(
PkixCertPathChecker checker)
{
if (checker != null)
{
certPathCheckers.Add(checker.Clone());
}
}
public virtual object Clone()
{
// FIXME Check this whole method against the Java implementation!
PkixParameters parameters = new PkixParameters(GetTrustAnchors());
parameters.SetParams(this);
return parameters;
// PkixParameters obj = new PkixParameters(new HashSet());
//// (PkixParameters) this.MemberwiseClone();
// obj.x509Stores = new ArrayList(x509Stores);
// obj.certPathCheckers = new ArrayList(certPathCheckers);
//
// //Iterator iter = certPathCheckers.iterator();
// //obj.certPathCheckers = new ArrayList();
// //while (iter.hasNext())
// //{
// // obj.certPathCheckers.add(((PKIXCertPathChecker)iter.next())
// // .clone());
// //}
// //if (initialPolicies != null)
// //{
// // obj.initialPolicies = new HashSet(initialPolicies);
// //}
//// if (trustAnchors != null)
//// {
//// obj.trustAnchors = new HashSet(trustAnchors);
//// }
//// if (certSelector != null)
//// {
//// obj.certSelector = (X509CertStoreSelector) certSelector.Clone();
//// }
// return obj;
}
/**
* Method to support <code>Clone()</code> under J2ME.
* <code>super.Clone()</code> does not exist and fields are not copied.
*
* @param params Parameters to set. If this are
* <code>ExtendedPkixParameters</code> they are copied to.
*/
protected virtual void SetParams(
PkixParameters parameters)
{
Date = parameters.Date;
SetCertPathCheckers(parameters.GetCertPathCheckers());
SetX509Stores(parameters.GetX509Stores());
IsAnyPolicyInhibited = parameters.IsAnyPolicyInhibited;
IsExplicitPolicyRequired = parameters.IsExplicitPolicyRequired;
IsPolicyMappingInhibited = parameters.IsPolicyMappingInhibited;
IsRevocationEnabled = parameters.IsRevocationEnabled;
SetInitialPolicies(parameters.GetInitialPolicies());
IsPolicyQualifiersRejected = parameters.IsPolicyQualifiersRejected;
SetTargetCertConstraints(parameters.GetTargetCertConstraints());
SetTrustAnchors(parameters.GetTrustAnchors());
validityModel = parameters.validityModel;
useDeltas = parameters.useDeltas;
additionalLocationsEnabled = parameters.additionalLocationsEnabled;
selector = parameters.selector == null ? null
: (IX509Selector) parameters.selector.Clone();
stores = new ArrayList(parameters.stores);
additionalStores = new ArrayList(parameters.additionalStores);
trustedACIssuers = new HashSet(parameters.trustedACIssuers);
prohibitedACAttributes = new HashSet(parameters.prohibitedACAttributes);
necessaryACAttributes = new HashSet(parameters.necessaryACAttributes);
attrCertCheckers = new HashSet(parameters.attrCertCheckers);
}
/**
* Whether delta CRLs should be used for checking the revocation status.
* Defaults to <code>false</code>.
*/
public virtual bool IsUseDeltasEnabled
{
get { return useDeltas; }
set { useDeltas = value; }
}
/**
* The validity model.
* @see #CHAIN_VALIDITY_MODEL
* @see #PKIX_VALIDITY_MODEL
*/
public virtual int ValidityModel
{
get { return validityModel; }
set { validityModel = value; }
}
/**
* Sets the Bouncy Castle Stores for finding CRLs, certificates, attribute
* certificates or cross certificates.
* <p>
* The <code>IList</code> is cloned.
* </p>
*
* @param stores A list of stores to use.
* @see #getStores
* @throws ClassCastException if an element of <code>stores</code> is not
* a {@link Store}.
*/
public virtual void SetStores(
IList stores)
{
if (stores == null)
{
this.stores = new ArrayList();
}
else
{
foreach (object obj in stores)
{
if (!(obj is IX509Store))
{
throw new InvalidCastException(
"All elements of list must be of type " + typeof(IX509Store).FullName);
}
}
this.stores = new ArrayList(stores);
}
}
/**
* Adds a Bouncy Castle {@link Store} to find CRLs, certificates, attribute
* certificates or cross certificates.
* <p>
* This method should be used to add local stores, like collection based
* X.509 stores, if available. Local stores should be considered first,
* before trying to use additional (remote) locations, because they do not
* need possible additional network traffic.
* </p><p>
* If <code>store</code> is <code>null</code> it is ignored.
* </p>
*
* @param store The store to add.
* @see #getStores
*/
public virtual void AddStore(
IX509Store store)
{
if (store != null)
{
stores.Add(store);
}
}
/**
* Adds a additional Bouncy Castle {@link Store} to find CRLs, certificates,
* attribute certificates or cross certificates.
* <p>
* You should not use this method. This method is used for adding additional
* X.509 stores, which are used to add (remote) locations, e.g. LDAP, found
* during X.509 object processing, e.g. in certificates or CRLs. This method
* is used in PKIX certification path processing.
* </p><p>
* If <code>store</code> is <code>null</code> it is ignored.
* </p>
*
* @param store The store to add.
* @see #getStores()
*/
public virtual void AddAddionalStore(
IX509Store store)
{
if (store != null)
{
additionalStores.Add(store);
}
}
/**
* Returns an immutable <code>IList</code> of additional Bouncy Castle
* <code>Store</code>s used for finding CRLs, certificates, attribute
* certificates or cross certificates.
*
* @return an immutable <code>IList</code> of additional Bouncy Castle
* <code>Store</code>s. Never <code>null</code>.
*
* @see #addAddionalStore(Store)
*/
public virtual IList GetAdditionalStores()
{
return ArrayList.ReadOnly(new ArrayList(additionalStores));
}
/**
* Returns an immutable <code>IList</code> of Bouncy Castle
* <code>Store</code>s used for finding CRLs, certificates, attribute
* certificates or cross certificates.
*
* @return an immutable <code>IList</code> of Bouncy Castle
* <code>Store</code>s. Never <code>null</code>.
*
* @see #setStores(IList)
*/
public virtual IList GetStores()
{
return ArrayList.ReadOnly(new ArrayList(stores));
}
/**
* Returns if additional {@link X509Store}s for locations like LDAP found
* in certificates or CRLs should be used.
*
* @return Returns <code>true</code> if additional stores are used.
*/
public virtual bool IsAdditionalLocationsEnabled
{
get { return additionalLocationsEnabled; }
}
/**
* Sets if additional {@link X509Store}s for locations like LDAP found in
* certificates or CRLs should be used.
*
* @param enabled <code>true</code> if additional stores are used.
*/
public virtual void SetAdditionalLocationsEnabled(
bool enabled)
{
additionalLocationsEnabled = enabled;
}
/**
* Returns the required constraints on the target certificate or attribute
* certificate. The constraints are returned as an instance of
* <code>IX509Selector</code>. If <code>null</code>, no constraints are
* defined.
*
* <p>
* The target certificate in a PKIX path may be a certificate or an
* attribute certificate.
* </p><p>
* Note that the <code>IX509Selector</code> returned is cloned to protect
* against subsequent modifications.
* </p>
* @return a <code>IX509Selector</code> specifying the constraints on the
* target certificate or attribute certificate (or <code>null</code>)
* @see #setTargetConstraints
* @see X509CertStoreSelector
* @see X509AttributeCertStoreSelector
*/
public virtual IX509Selector GetTargetConstraints()
{
if (selector != null)
{
return (IX509Selector) selector.Clone();
}
else
{
return null;
}
}
/**
* Sets the required constraints on the target certificate or attribute
* certificate. The constraints are specified as an instance of
* <code>IX509Selector</code>. If <code>null</code>, no constraints are
* defined.
* <p>
* The target certificate in a PKIX path may be a certificate or an
* attribute certificate.
* </p><p>
* Note that the <code>IX509Selector</code> specified is cloned to protect
* against subsequent modifications.
* </p>
*
* @param selector a <code>IX509Selector</code> specifying the constraints on
* the target certificate or attribute certificate (or
* <code>null</code>)
* @see #getTargetConstraints
* @see X509CertStoreSelector
* @see X509AttributeCertStoreSelector
*/
public virtual void SetTargetConstraints(IX509Selector selector)
{
if (selector != null)
{
this.selector = (IX509Selector) selector.Clone();
}
else
{
this.selector = null;
}
}
/**
* Returns the trusted attribute certificate issuers. If attribute
* certificates is verified the trusted AC issuers must be set.
* <p>
* The returned <code>ISet</code> consists of <code>TrustAnchor</code>s.
* </p><p>
* The returned <code>ISet</code> is immutable. Never <code>null</code>
* </p>
*
* @return Returns an immutable set of the trusted AC issuers.
*/
public virtual ISet GetTrustedACIssuers()
{
return new HashSet(trustedACIssuers);
}
/**
* Sets the trusted attribute certificate issuers. If attribute certificates
* is verified the trusted AC issuers must be set.
* <p>
* The <code>trustedACIssuers</code> must be a <code>ISet</code> of
* <code>TrustAnchor</code>
* </p><p>
* The given set is cloned.
* </p>
*
* @param trustedACIssuers The trusted AC issuers to set. Is never
* <code>null</code>.
* @throws ClassCastException if an element of <code>stores</code> is not
* a <code>TrustAnchor</code>.
*/
public virtual void SetTrustedACIssuers(
ISet trustedACIssuers)
{
if (trustedACIssuers == null)
{
this.trustedACIssuers = new HashSet();
}
else
{
foreach (object obj in trustedACIssuers)
{
if (!(obj is TrustAnchor))
{
throw new InvalidCastException("All elements of set must be "
+ "of type " + typeof(TrustAnchor).Name + ".");
}
}
this.trustedACIssuers = new HashSet(trustedACIssuers);
}
}
/**
* Returns the neccessary attributes which must be contained in an attribute
* certificate.
* <p>
* The returned <code>ISet</code> is immutable and contains
* <code>String</code>s with the OIDs.
* </p>
*
* @return Returns the necessary AC attributes.
*/
public virtual ISet GetNecessaryACAttributes()
{
return new HashSet(necessaryACAttributes);
}
/**
* Sets the neccessary which must be contained in an attribute certificate.
* <p>
* The <code>ISet</code> must contain <code>String</code>s with the
* OIDs.
* </p><p>
* The set is cloned.
* </p>
*
* @param necessaryACAttributes The necessary AC attributes to set.
* @throws ClassCastException if an element of
* <code>necessaryACAttributes</code> is not a
* <code>String</code>.
*/
public virtual void SetNecessaryACAttributes(
ISet necessaryACAttributes)
{
if (necessaryACAttributes == null)
{
this.necessaryACAttributes = new HashSet();
}
else
{
foreach (object obj in necessaryACAttributes)
{
if (!(obj is string))
{
throw new InvalidCastException("All elements of set must be "
+ "of type string.");
}
}
this.necessaryACAttributes = new HashSet(necessaryACAttributes);
}
}
/**
* Returns the attribute certificates which are not allowed.
* <p>
* The returned <code>ISet</code> is immutable and contains
* <code>String</code>s with the OIDs.
* </p>
*
* @return Returns the prohibited AC attributes. Is never <code>null</code>.
*/
public virtual ISet GetProhibitedACAttributes()
{
return new HashSet(prohibitedACAttributes);
}
/**
* Sets the attribute certificates which are not allowed.
* <p>
* The <code>ISet</code> must contain <code>String</code>s with the
* OIDs.
* </p><p>
* The set is cloned.
* </p>
*
* @param prohibitedACAttributes The prohibited AC attributes to set.
* @throws ClassCastException if an element of
* <code>prohibitedACAttributes</code> is not a
* <code>String</code>.
*/
public virtual void SetProhibitedACAttributes(
ISet prohibitedACAttributes)
{
if (prohibitedACAttributes == null)
{
this.prohibitedACAttributes = new HashSet();
}
else
{
foreach (object obj in prohibitedACAttributes)
{
if (!(obj is String))
{
throw new InvalidCastException("All elements of set must be "
+ "of type string.");
}
}
this.prohibitedACAttributes = new HashSet(prohibitedACAttributes);
}
}
/**
* Returns the attribute certificate checker. The returned set contains
* {@link PKIXAttrCertChecker}s and is immutable.
*
* @return Returns the attribute certificate checker. Is never
* <code>null</code>.
*/
public virtual ISet GetAttrCertCheckers()
{
return new HashSet(attrCertCheckers);
}
/**
* Sets the attribute certificate checkers.
* <p>
* All elements in the <code>ISet</code> must a {@link PKIXAttrCertChecker}.
* </p>
* <p>
* The given set is cloned.
* </p>
*
* @param attrCertCheckers The attribute certificate checkers to set. Is
* never <code>null</code>.
* @throws ClassCastException if an element of <code>attrCertCheckers</code>
* is not a <code>PKIXAttrCertChecker</code>.
*/
public virtual void SetAttrCertCheckers(
ISet attrCertCheckers)
{
if (attrCertCheckers == null)
{
this.attrCertCheckers = new HashSet();
}
else
{
foreach (object obj in attrCertCheckers)
{
if (!(obj is PkixAttrCertChecker))
{
throw new InvalidCastException("All elements of set must be "
+ "of type " + typeof(PkixAttrCertChecker).FullName + ".");
}
}
this.attrCertCheckers = new HashSet(attrCertCheckers);
}
}
}
}

View File

@ -0,0 +1,156 @@
using System;
using System.Collections;
using System.Text;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Pkix
{
/// <summary>
/// Summary description for PkixPolicyNode.
/// </summary>
public class PkixPolicyNode
// : IPolicyNode
{
protected IList mChildren;
protected int mDepth;
protected ISet mExpectedPolicies;
protected PkixPolicyNode mParent;
protected ISet mPolicyQualifiers;
protected string mValidPolicy;
protected bool mCritical;
public virtual int Depth
{
get { return this.mDepth; }
}
public virtual IEnumerable Children
{
get { return ArrayList.ReadOnly(mChildren); }
}
public virtual bool IsCritical
{
get { return this.mCritical; }
set { this.mCritical = value; }
}
public virtual ISet PolicyQualifiers
{
get { return new HashSet(this.mPolicyQualifiers); }
}
public virtual string ValidPolicy
{
get { return this.mValidPolicy; }
}
public virtual bool HasChildren
{
get { return mChildren.Count != 0; }
}
public virtual ISet ExpectedPolicies
{
get { return new HashSet(this.mExpectedPolicies); }
set { this.mExpectedPolicies = new HashSet(value); }
}
public virtual PkixPolicyNode Parent
{
get { return this.mParent; }
set { this.mParent = value; }
}
/// Constructors
public PkixPolicyNode(
IList children,
int depth,
ISet expectedPolicies,
PkixPolicyNode parent,
ISet policyQualifiers,
string validPolicy,
bool critical)
{
ArrayList newChildren = new ArrayList();
if (children != null)
{
newChildren.AddRange(children);
}
this.mChildren = newChildren;
this.mDepth = depth;
this.mExpectedPolicies = expectedPolicies;
this.mParent = parent;
this.mPolicyQualifiers = policyQualifiers;
this.mValidPolicy = validPolicy;
this.mCritical = critical;
}
public virtual void AddChild(
PkixPolicyNode child)
{
child.Parent = this;
mChildren.Add(child);
}
public virtual void RemoveChild(
PkixPolicyNode child)
{
mChildren.Remove(child);
}
public override string ToString()
{
return ToString("");
}
public virtual string ToString(
string indent)
{
StringBuilder buf = new StringBuilder();
buf.Append(indent);
buf.Append(mValidPolicy);
buf.Append(" {");
buf.Append(Platform.NewLine);
foreach (PkixPolicyNode child in mChildren)
{
buf.Append(child.ToString(indent + " "));
}
buf.Append(indent);
buf.Append("}");
buf.Append(Platform.NewLine);
return buf.ToString();
}
public virtual object Clone()
{
return Copy();
}
public virtual PkixPolicyNode Copy()
{
PkixPolicyNode node = new PkixPolicyNode(
new ArrayList(),
mDepth,
new HashSet(mExpectedPolicies),
null,
new HashSet(mPolicyQualifiers),
mValidPolicy,
mCritical);
foreach (PkixPolicyNode child in mChildren)
{
PkixPolicyNode copy = child.Copy();
copy.Parent = node;
node.AddChild(copy);
}
return node;
}
}
}

View File

@ -0,0 +1,96 @@
using System;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.Pkix
{
/// <summary>
/// This class helps to handle CRL revocation reasons mask. Each CRL handles a
/// certain set of revocation reasons.
/// </summary>
internal class ReasonsMask
{
private int _reasons;
/// <summary>
/// Constructs are reason mask with the reasons.
/// </summary>
/// <param name="reasons">The reasons.</param>
internal ReasonsMask(
int reasons)
{
_reasons = reasons;
}
/// <summary>
/// A reason mask with no reason.
/// </summary>
internal ReasonsMask()
: this(0)
{
}
/// <summary>
/// A mask with all revocation reasons.
/// </summary>
internal static readonly ReasonsMask AllReasons = new ReasonsMask(
ReasonFlags.AACompromise | ReasonFlags.AffiliationChanged | ReasonFlags.CACompromise
| ReasonFlags.CertificateHold | ReasonFlags.CessationOfOperation
| ReasonFlags.KeyCompromise | ReasonFlags.PrivilegeWithdrawn | ReasonFlags.Unused
| ReasonFlags.Superseded);
/**
* Adds all reasons from the reasons mask to this mask.
*
* @param mask The reasons mask to add.
*/
internal void AddReasons(
ReasonsMask mask)
{
_reasons = _reasons | mask.Reasons.IntValue;
}
/// <summary>
/// Returns <code>true</code> if this reasons mask contains all possible
/// reasons.
/// </summary>
/// <returns>true if this reasons mask contains all possible reasons.
/// </returns>
internal bool IsAllReasons
{
get { return _reasons == AllReasons._reasons; }
}
/// <summary>
/// Intersects this mask with the given reasons mask.
/// </summary>
/// <param name="mask">mask The mask to intersect with.</param>
/// <returns>The intersection of this and teh given mask.</returns>
internal ReasonsMask Intersect(
ReasonsMask mask)
{
ReasonsMask _mask = new ReasonsMask();
_mask.AddReasons(new ReasonsMask(_reasons & mask.Reasons.IntValue));
return _mask;
}
/// <summary>
/// Returns <c>true</c> if the passed reasons mask has new reasons.
/// </summary>
/// <param name="mask">The reasons mask which should be tested for new reasons.</param>
/// <returns><c>true</c> if the passed reasons mask has new reasons.</returns>
internal bool HasNewReasons(
ReasonsMask mask)
{
return ((_reasons | mask.Reasons.IntValue ^ _reasons) != 0);
}
/// <summary>
/// Returns the reasons in this mask.
/// </summary>
public ReasonFlags Reasons
{
get { return new ReasonFlags(_reasons); }
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,608 @@
using System;
using System.Collections;
using System.Globalization;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Store;
namespace Org.BouncyCastle.Pkix
{
internal class Rfc3281CertPathUtilities
{
internal static void ProcessAttrCert7(
IX509AttributeCertificate attrCert,
PkixCertPath certPath,
PkixCertPath holderCertPath,
PkixParameters pkixParams)
{
// TODO:
// AA Controls
// Attribute encryption
// Proxy
ISet critExtOids = attrCert.GetCriticalExtensionOids();
// 7.1
// process extensions
// target information checked in step 6 / X509AttributeCertStoreSelector
if (critExtOids.Contains(X509Extensions.TargetInformation.Id))
{
try
{
TargetInformation.GetInstance(PkixCertPathValidatorUtilities
.GetExtensionValue(attrCert, X509Extensions.TargetInformation));
}
catch (Exception e)
{
throw new PkixCertPathValidatorException(
"Target information extension could not be read.", e);
}
}
critExtOids.Remove(X509Extensions.TargetInformation.Id);
foreach (PkixAttrCertChecker checker in pkixParams.GetAttrCertCheckers())
{
checker.Check(attrCert, certPath, holderCertPath, critExtOids);
}
if (!critExtOids.IsEmpty)
{
throw new PkixCertPathValidatorException(
"Attribute certificate contains unsupported critical extensions: "
+ critExtOids);
}
}
/**
* Checks if an attribute certificate is revoked.
*
* @param attrCert Attribute certificate to check if it is revoked.
* @param paramsPKIX PKIX parameters.
* @param issuerCert The issuer certificate of the attribute certificate
* <code>attrCert</code>.
* @param validDate The date when the certificate revocation status should
* be checked.
* @param certPathCerts The certificates of the certification path to be
* checked.
*
* @throws CertPathValidatorException if the certificate is revoked or the
* status cannot be checked or some error occurs.
*/
internal static void CheckCrls(
IX509AttributeCertificate attrCert,
PkixParameters paramsPKIX,
X509Certificate issuerCert,
DateTime validDate,
IList certPathCerts)
{
if (paramsPKIX.IsRevocationEnabled)
{
// check if revocation is available
if (attrCert.GetExtensionValue(X509Extensions.NoRevAvail) == null)
{
CrlDistPoint crldp = null;
try
{
crldp = CrlDistPoint.GetInstance(
PkixCertPathValidatorUtilities.GetExtensionValue(
attrCert, X509Extensions.CrlDistributionPoints));
}
catch (Exception e)
{
throw new PkixCertPathValidatorException(
"CRL distribution point extension could not be read.", e);
}
try
{
PkixCertPathValidatorUtilities
.AddAdditionalStoresFromCrlDistributionPoint(crldp, paramsPKIX);
}
catch (Exception e)
{
throw new PkixCertPathValidatorException(
"No additional CRL locations could be decoded from CRL distribution point extension.", e);
}
CertStatus certStatus = new CertStatus();
ReasonsMask reasonsMask = new ReasonsMask();
Exception lastException = null;
bool validCrlFound = false;
// for each distribution point
if (crldp != null)
{
DistributionPoint[] dps = null;
try
{
dps = crldp.GetDistributionPoints();
}
catch (Exception e)
{
throw new PkixCertPathValidatorException(
"Distribution points could not be read.", e);
}
try
{
for (int i = 0; i < dps.Length
&& certStatus.Status == CertStatus.Unrevoked
&& !reasonsMask.IsAllReasons; i++)
{
PkixParameters paramsPKIXClone = (PkixParameters) paramsPKIX
.Clone();
CheckCrl(dps[i], attrCert, paramsPKIXClone,
validDate, issuerCert, certStatus, reasonsMask,
certPathCerts);
validCrlFound = true;
}
}
catch (Exception e)
{
lastException = new Exception(
"No valid CRL for distribution point found.", e);
}
}
/*
* If the revocation status has not been determined, repeat the
* process above with any available CRLs not specified in a
* distribution point but issued by the certificate issuer.
*/
if (certStatus.Status == CertStatus.Unrevoked
&& !reasonsMask.IsAllReasons)
{
try
{
/*
* assume a DP with both the reasons and the cRLIssuer
* fields omitted and a distribution point name of the
* certificate issuer.
*/
Asn1Object issuer = null;
try
{
issuer = new Asn1InputStream(
attrCert.Issuer.GetPrincipals()[0].GetEncoded()).ReadObject();
}
catch (Exception e)
{
throw new Exception(
"Issuer from certificate for CRL could not be reencoded.",
e);
}
DistributionPoint dp = new DistributionPoint(
new DistributionPointName(0, new GeneralNames(
new GeneralName(GeneralName.DirectoryName, issuer))), null, null);
PkixParameters paramsPKIXClone = (PkixParameters) paramsPKIX.Clone();
CheckCrl(dp, attrCert, paramsPKIXClone, validDate,
issuerCert, certStatus, reasonsMask, certPathCerts);
validCrlFound = true;
}
catch (Exception e)
{
lastException = new Exception(
"No valid CRL for distribution point found.", e);
}
}
if (!validCrlFound)
{
throw new PkixCertPathValidatorException(
"No valid CRL found.", lastException);
}
if (certStatus.Status != CertStatus.Unrevoked)
{
// TODO This format is forced by the NistCertPath tests
string formattedDate = certStatus.RevocationDate.Value.ToString(
"G", CultureInfo.CreateSpecificCulture("en-us"));
string message = "Attribute certificate revocation after "
+ formattedDate;
message += ", reason: "
+ Rfc3280CertPathUtilities.CrlReasons[certStatus.Status];
throw new PkixCertPathValidatorException(message);
}
if (!reasonsMask.IsAllReasons
&& certStatus.Status == CertStatus.Unrevoked)
{
certStatus.Status = CertStatus.Undetermined;
}
if (certStatus.Status == CertStatus.Undetermined)
{
throw new PkixCertPathValidatorException(
"Attribute certificate status could not be determined.");
}
}
else
{
if (attrCert.GetExtensionValue(X509Extensions.CrlDistributionPoints) != null
|| attrCert.GetExtensionValue(X509Extensions.AuthorityInfoAccess) != null)
{
throw new PkixCertPathValidatorException(
"No rev avail extension is set, but also an AC revocation pointer.");
}
}
}
}
internal static void AdditionalChecks(
IX509AttributeCertificate attrCert,
PkixParameters pkixParams)
{
// 1
foreach (string oid in pkixParams.GetProhibitedACAttributes())
{
if (attrCert.GetAttributes(oid) != null)
{
throw new PkixCertPathValidatorException(
"Attribute certificate contains prohibited attribute: "
+ oid + ".");
}
}
foreach (string oid in pkixParams.GetNecessaryACAttributes())
{
if (attrCert.GetAttributes(oid) == null)
{
throw new PkixCertPathValidatorException(
"Attribute certificate does not contain necessary attribute: "
+ oid + ".");
}
}
}
internal static void ProcessAttrCert5(
IX509AttributeCertificate attrCert,
PkixParameters pkixParams)
{
try
{
attrCert.CheckValidity(PkixCertPathValidatorUtilities.GetValidDate(pkixParams));
}
catch (CertificateExpiredException e)
{
throw new PkixCertPathValidatorException(
"Attribute certificate is not valid.", e);
}
catch (CertificateNotYetValidException e)
{
throw new PkixCertPathValidatorException(
"Attribute certificate is not valid.", e);
}
}
internal static void ProcessAttrCert4(
X509Certificate acIssuerCert,
PkixParameters pkixParams)
{
ISet set = pkixParams.GetTrustedACIssuers();
bool trusted = false;
foreach (TrustAnchor anchor in set)
{
if (acIssuerCert.SubjectDN.ToString(false, X509Name.RFC2253Symbols)
.Equals(anchor.CAName)
|| acIssuerCert.Equals(anchor.TrustedCert))
{
trusted = true;
}
}
if (!trusted)
{
throw new PkixCertPathValidatorException(
"Attribute certificate issuer is not directly trusted.");
}
}
internal static void ProcessAttrCert3(
X509Certificate acIssuerCert,
PkixParameters pkixParams)
{
if (acIssuerCert.GetKeyUsage() != null
&& (!acIssuerCert.GetKeyUsage()[0] && !acIssuerCert.GetKeyUsage()[1]))
{
throw new PkixCertPathValidatorException(
"Attribute certificate issuer public key cannot be used to validate digital signatures.");
}
if (acIssuerCert.GetBasicConstraints() != -1)
{
throw new PkixCertPathValidatorException(
"Attribute certificate issuer is also a public key certificate issuer.");
}
}
internal static PkixCertPathValidatorResult ProcessAttrCert2(
PkixCertPath certPath,
PkixParameters pkixParams)
{
PkixCertPathValidator validator = new PkixCertPathValidator();
try
{
return validator.Validate(certPath, pkixParams);
}
catch (PkixCertPathValidatorException e)
{
throw new PkixCertPathValidatorException(
"Certification path for issuer certificate of attribute certificate could not be validated.",
e);
}
}
/**
* Searches for a holder public key certificate and verifies its
* certification path.
*
* @param attrCert the attribute certificate.
* @param pkixParams The PKIX parameters.
* @return The certificate path of the holder certificate.
* @throws Exception if
* <ul>
* <li>no public key certificate can be found although holder
* information is given by an entity name or a base certificate
* ID</li>
* <li>support classes cannot be created</li>
* <li>no certification path for the public key certificate can
* be built</li>
* </ul>
*/
internal static PkixCertPath ProcessAttrCert1(
IX509AttributeCertificate attrCert,
PkixParameters pkixParams)
{
PkixCertPathBuilderResult result = null;
// find holder PKCs
ISet holderPKCs = new HashSet();
if (attrCert.Holder.GetIssuer() != null)
{
X509CertStoreSelector selector = new X509CertStoreSelector();
selector.SerialNumber = attrCert.Holder.SerialNumber;
X509Name[] principals = attrCert.Holder.GetIssuer();
for (int i = 0; i < principals.Length; i++)
{
try
{
// if (principals[i] is X500Principal)
{
selector.Issuer = principals[i];
}
holderPKCs.AddAll(PkixCertPathValidatorUtilities
.FindCertificates(selector, pkixParams.GetStores()));
}
catch (Exception e)
{
throw new PkixCertPathValidatorException(
"Public key certificate for attribute certificate cannot be searched.",
e);
}
}
if (holderPKCs.IsEmpty)
{
throw new PkixCertPathValidatorException(
"Public key certificate specified in base certificate ID for attribute certificate cannot be found.");
}
}
if (attrCert.Holder.GetEntityNames() != null)
{
X509CertStoreSelector selector = new X509CertStoreSelector();
X509Name[] principals = attrCert.Holder.GetEntityNames();
for (int i = 0; i < principals.Length; i++)
{
try
{
// if (principals[i] is X500Principal)
{
selector.Issuer = principals[i];
}
holderPKCs.AddAll(PkixCertPathValidatorUtilities
.FindCertificates(selector, pkixParams.GetStores()));
}
catch (Exception e)
{
throw new PkixCertPathValidatorException(
"Public key certificate for attribute certificate cannot be searched.",
e);
}
}
if (holderPKCs.IsEmpty)
{
throw new PkixCertPathValidatorException(
"Public key certificate specified in entity name for attribute certificate cannot be found.");
}
}
// verify cert paths for PKCs
PkixBuilderParameters parameters = (PkixBuilderParameters)
PkixBuilderParameters.GetInstance(pkixParams);
PkixCertPathValidatorException lastException = null;
foreach (X509Certificate cert in holderPKCs)
{
X509CertStoreSelector selector = new X509CertStoreSelector();
selector.Certificate = cert;
parameters.SetTargetConstraints(selector);
PkixCertPathBuilder builder = new PkixCertPathBuilder();
try
{
result = builder.Build(PkixBuilderParameters.GetInstance(parameters));
}
catch (PkixCertPathBuilderException e)
{
lastException = new PkixCertPathValidatorException(
"Certification path for public key certificate of attribute certificate could not be build.",
e);
}
}
if (lastException != null)
{
throw lastException;
}
return result.CertPath;
}
/**
*
* Checks a distribution point for revocation information for the
* certificate <code>attrCert</code>.
*
* @param dp The distribution point to consider.
* @param attrCert The attribute certificate which should be checked.
* @param paramsPKIX PKIX parameters.
* @param validDate The date when the certificate revocation status should
* be checked.
* @param issuerCert Certificate to check if it is revoked.
* @param reasonMask The reasons mask which is already checked.
* @param certPathCerts The certificates of the certification path to be
* checked.
* @throws Exception if the certificate is revoked or the status
* cannot be checked or some error occurs.
*/
private static void CheckCrl(
DistributionPoint dp,
IX509AttributeCertificate attrCert,
PkixParameters paramsPKIX,
DateTime validDate,
X509Certificate issuerCert,
CertStatus certStatus,
ReasonsMask reasonMask,
IList certPathCerts)
{
/*
* 4.3.6 No Revocation Available
*
* The noRevAvail extension, defined in [X.509-2000], allows an AC
* issuer to indicate that no revocation information will be made
* available for this AC.
*/
if (attrCert.GetExtensionValue(X509Extensions.NoRevAvail) != null)
{
return;
}
DateTime currentDate = DateTime.UtcNow;
if (validDate.CompareTo(currentDate) > 0)
{
throw new Exception("Validation time is in future.");
}
// (a)
/*
* We always get timely valid CRLs, so there is no step (a) (1).
* "locally cached" CRLs are assumed to be in getStore(), additional
* CRLs must be enabled in the ExtendedPkixParameters and are in
* getAdditionalStore()
*/
ISet crls = PkixCertPathValidatorUtilities.GetCompleteCrls(dp, attrCert,
currentDate, paramsPKIX);
bool validCrlFound = false;
Exception lastException = null;
IEnumerator crl_iter = crls.GetEnumerator();
while (crl_iter.MoveNext()
&& certStatus.Status == CertStatus.Unrevoked
&& !reasonMask.IsAllReasons)
{
try
{
X509Crl crl = (X509Crl) crl_iter.Current;
// (d)
ReasonsMask interimReasonsMask = Rfc3280CertPathUtilities.ProcessCrlD(crl, dp);
// (e)
/*
* The reasons mask is updated at the end, so only valid CRLs
* can update it. If this CRL does not contain new reasons it
* must be ignored.
*/
if (!interimReasonsMask.HasNewReasons(reasonMask))
{
continue;
}
// (f)
ISet keys = Rfc3280CertPathUtilities.ProcessCrlF(crl, attrCert,
null, null, paramsPKIX, certPathCerts);
// (g)
AsymmetricKeyParameter pubKey = Rfc3280CertPathUtilities.ProcessCrlG(crl, keys);
X509Crl deltaCRL = null;
if (paramsPKIX.IsUseDeltasEnabled)
{
// get delta CRLs
ISet deltaCRLs = PkixCertPathValidatorUtilities.GetDeltaCrls(
currentDate, paramsPKIX, crl);
// we only want one valid delta CRL
// (h)
deltaCRL = Rfc3280CertPathUtilities.ProcessCrlH(deltaCRLs, pubKey);
}
/*
* CRL must be be valid at the current time, not the validation
* time. If a certificate is revoked with reason keyCompromise,
* cACompromise, it can be used for forgery, also for the past.
* This reason may not be contained in older CRLs.
*/
/*
* in the chain model signatures stay valid also after the
* certificate has been expired, so they do not have to be in
* the CRL vality time
*/
if (paramsPKIX.ValidityModel != PkixParameters.ChainValidityModel)
{
/*
* if a certificate has expired, but was revoked, it is not
* more in the CRL, so it would be regarded as valid if the
* first check is not done
*/
if (attrCert.NotAfter.CompareTo(crl.ThisUpdate) < 0)
{
throw new Exception(
"No valid CRL for current time found.");
}
}
Rfc3280CertPathUtilities.ProcessCrlB1(dp, attrCert, crl);
// (b) (2)
Rfc3280CertPathUtilities.ProcessCrlB2(dp, attrCert, crl);
// (c)
Rfc3280CertPathUtilities.ProcessCrlC(deltaCRL, crl, paramsPKIX);
// (i)
Rfc3280CertPathUtilities.ProcessCrlI(validDate, deltaCRL,
attrCert, certStatus, paramsPKIX);
// (j)
Rfc3280CertPathUtilities.ProcessCrlJ(validDate, crl, attrCert,
certStatus);
// (k)
if (certStatus.Status == CrlReason.RemoveFromCrl)
{
certStatus.Status = CertStatus.Unrevoked;
}
// update reasons mask
reasonMask.AddReasons(interimReasonsMask);
validCrlFound = true;
}
catch (Exception e)
{
lastException = e;
}
}
if (!validCrlFound)
{
throw lastException;
}
}
}
}

View File

@ -0,0 +1,259 @@
using System;
using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509;
namespace Org.BouncyCastle.Pkix
{
/// <summary>
/// A trust anchor or most-trusted Certification Authority (CA).
///
/// This class represents a "most-trusted CA", which is used as a trust anchor
/// for validating X.509 certification paths. A most-trusted CA includes the
/// public key of the CA, the CA's name, and any constraints upon the set of
/// paths which may be validated using this key. These parameters can be
/// specified in the form of a trusted X509Certificate or as individual
/// parameters.
/// </summary>
public class TrustAnchor
{
private readonly AsymmetricKeyParameter pubKey;
private readonly string caName;
private readonly X509Name caPrincipal;
private readonly X509Certificate trustedCert;
private byte[] ncBytes;
private NameConstraints nc;
/// <summary>
/// Creates an instance of TrustAnchor with the specified X509Certificate and
/// optional name constraints, which are intended to be used as additional
/// constraints when validating an X.509 certification path.
/// The name constraints are specified as a byte array. This byte array
/// should contain the DER encoded form of the name constraints, as they
/// would appear in the NameConstraints structure defined in RFC 2459 and
/// X.509. The ASN.1 definition of this structure appears below.
///
/// <pre>
/// NameConstraints ::= SEQUENCE {
/// permittedSubtrees [0] GeneralSubtrees OPTIONAL,
/// excludedSubtrees [1] GeneralSubtrees OPTIONAL }
///
/// GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
///
/// GeneralSubtree ::= SEQUENCE {
/// base GeneralName,
/// minimum [0] BaseDistance DEFAULT 0,
/// maximum [1] BaseDistance OPTIONAL }
///
/// BaseDistance ::= INTEGER (0..MAX)
///
/// GeneralName ::= CHOICE {
/// otherName [0] OtherName,
/// rfc822Name [1] IA5String,
/// dNSName [2] IA5String,
/// x400Address [3] ORAddress,
/// directoryName [4] Name,
/// ediPartyName [5] EDIPartyName,
/// uniformResourceIdentifier [6] IA5String,
/// iPAddress [7] OCTET STRING,
/// registeredID [8] OBJECT IDENTIFIER}
/// </pre>
///
/// Note that the name constraints byte array supplied is cloned to protect
/// against subsequent modifications.
/// </summary>
/// <param name="trustedCert">a trusted X509Certificate</param>
/// <param name="nameConstraints">a byte array containing the ASN.1 DER encoding of a
/// NameConstraints extension to be used for checking name
/// constraints. Only the value of the extension is included, not
/// the OID or criticality flag. Specify null to omit the
/// parameter.</param>
/// <exception cref="ArgumentNullException">if the specified X509Certificate is null</exception>
public TrustAnchor(
X509Certificate trustedCert,
byte[] nameConstraints)
{
if (trustedCert == null)
throw new ArgumentNullException("trustedCert");
this.trustedCert = trustedCert;
this.pubKey = null;
this.caName = null;
this.caPrincipal = null;
setNameConstraints(nameConstraints);
}
/// <summary>
/// Creates an instance of <c>TrustAnchor</c> where the
/// most-trusted CA is specified as an X500Principal and public key.
/// </summary>
/// <remarks>
/// <p>
/// Name constraints are an optional parameter, and are intended to be used
/// as additional constraints when validating an X.509 certification path.
/// </p><p>
/// The name constraints are specified as a byte array. This byte array
/// contains the DER encoded form of the name constraints, as they
/// would appear in the NameConstraints structure defined in RFC 2459
/// and X.509. The ASN.1 notation for this structure is supplied in the
/// documentation for the other constructors.
/// </p><p>
/// Note that the name constraints byte array supplied here is cloned to
/// protect against subsequent modifications.
/// </p>
/// </remarks>
/// <param name="caPrincipal">the name of the most-trusted CA as X509Name</param>
/// <param name="pubKey">the public key of the most-trusted CA</param>
/// <param name="nameConstraints">
/// a byte array containing the ASN.1 DER encoding of a NameConstraints extension to
/// be used for checking name constraints. Only the value of the extension is included,
/// not the OID or criticality flag. Specify <c>null</c> to omit the parameter.
/// </param>
/// <exception cref="ArgumentNullException">
/// if <c>caPrincipal</c> or <c>pubKey</c> is null
/// </exception>
public TrustAnchor(
X509Name caPrincipal,
AsymmetricKeyParameter pubKey,
byte[] nameConstraints)
{
if (caPrincipal == null)
throw new ArgumentNullException("caPrincipal");
if (pubKey == null)
throw new ArgumentNullException("pubKey");
this.trustedCert = null;
this.caPrincipal = caPrincipal;
this.caName = caPrincipal.ToString();
this.pubKey = pubKey;
setNameConstraints(nameConstraints);
}
/// <summary>
/// Creates an instance of <code>TrustAnchor</code> where the most-trusted
/// CA is specified as a distinguished name and public key. Name constraints
/// are an optional parameter, and are intended to be used as additional
/// constraints when validating an X.509 certification path.
/// <br/>
/// The name constraints are specified as a byte array. This byte array
/// contains the DER encoded form of the name constraints, as they would
/// appear in the NameConstraints structure defined in RFC 2459 and X.509.
/// </summary>
/// <param name="caName">the X.500 distinguished name of the most-trusted CA in RFC
/// 2253 string format</param>
/// <param name="pubKey">the public key of the most-trusted CA</param>
/// <param name="nameConstraints">a byte array containing the ASN.1 DER encoding of a
/// NameConstraints extension to be used for checking name
/// constraints. Only the value of the extension is included, not
/// the OID or criticality flag. Specify null to omit the
/// parameter.</param>
/// throws NullPointerException, IllegalArgumentException
public TrustAnchor(
string caName,
AsymmetricKeyParameter pubKey,
byte[] nameConstraints)
{
if (caName == null)
throw new ArgumentNullException("caName");
if (pubKey == null)
throw new ArgumentNullException("pubKey");
if (caName.Length == 0)
throw new ArgumentException("caName can not be an empty string");
this.caPrincipal = new X509Name(caName);
this.pubKey = pubKey;
this.caName = caName;
this.trustedCert = null;
setNameConstraints(nameConstraints);
}
/// <summary>
/// Returns the most-trusted CA certificate.
/// </summary>
public X509Certificate TrustedCert
{
get { return this.trustedCert; }
}
/// <summary>
/// Returns the name of the most-trusted CA as an X509Name.
/// </summary>
public X509Name CA
{
get { return this.caPrincipal; }
}
/// <summary>
/// Returns the name of the most-trusted CA in RFC 2253 string format.
/// </summary>
public string CAName
{
get { return this.caName; }
}
/// <summary>
/// Returns the public key of the most-trusted CA.
/// </summary>
public AsymmetricKeyParameter CAPublicKey
{
get { return this.pubKey; }
}
/// <summary>
/// Decode the name constraints and clone them if not null.
/// </summary>
private void setNameConstraints(
byte[] bytes)
{
if (bytes == null)
{
ncBytes = null;
nc = null;
}
else
{
ncBytes = (byte[]) bytes.Clone();
// validate DER encoding
//nc = new NameConstraintsExtension(Boolean.FALSE, bytes);
nc = NameConstraints.GetInstance(Asn1Object.FromByteArray(bytes));
}
}
public byte[] GetNameConstraints
{
get { return Arrays.Clone(ncBytes); }
}
/// <summary>
/// Returns a formatted string describing the <code>TrustAnchor</code>.
/// </summary>
/// <returns>a formatted string describing the <code>TrustAnchor</code></returns>
public override string ToString()
{
// TODO Some of the sub-objects might not implement ToString() properly
string nl = Platform.NewLine;
StringBuilder sb = new StringBuilder();
sb.Append("[");
sb.Append(nl);
if (this.pubKey != null)
{
sb.Append(" Trusted CA Public Key: ").Append(this.pubKey).Append(nl);
sb.Append(" Trusted CA Issuer Name: ").Append(this.caName).Append(nl);
}
else
{
sb.Append(" Trusted CA cert: ").Append(this.TrustedCert).Append(nl);
}
if (nc != null)
{
sb.Append(" Name Constraints: ").Append(nc).Append(nl);
}
return sb.ToString();
}
}
}

View File

@ -1,210 +1,212 @@
using System;
using System.Collections;
using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.Oiw;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.TeleTrust;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
namespace Org.BouncyCastle.Security
{
public sealed class PrivateKeyFactory
{
private PrivateKeyFactory()
{
}
public static AsymmetricKeyParameter CreateKey(
byte[] privateKeyInfoData)
{
return CreateKey(
PrivateKeyInfo.GetInstance(
Asn1Object.FromByteArray(privateKeyInfoData)));
}
public static AsymmetricKeyParameter CreateKey(
Stream inStr)
{
return CreateKey(
PrivateKeyInfo.GetInstance(
Asn1Object.FromStream(inStr)));
}
public static AsymmetricKeyParameter CreateKey(
PrivateKeyInfo keyInfo)
{
AlgorithmIdentifier algID = keyInfo.AlgorithmID;
DerObjectIdentifier algOid = algID.ObjectID;
if (algOid.Equals(PkcsObjectIdentifiers.RsaEncryption))
{
RsaPrivateKeyStructure keyStructure = new RsaPrivateKeyStructure(
Asn1Sequence.GetInstance(keyInfo.PrivateKey));
return new RsaPrivateCrtKeyParameters(
keyStructure.Modulus,
keyStructure.PublicExponent,
keyStructure.PrivateExponent,
keyStructure.Prime1,
keyStructure.Prime2,
keyStructure.Exponent1,
keyStructure.Exponent2,
keyStructure.Coefficient);
}
else if (algOid.Equals(PkcsObjectIdentifiers.DhKeyAgreement))
{
DHParameter para = new DHParameter(
Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
DerInteger derX = (DerInteger)keyInfo.PrivateKey;
return new DHPrivateKeyParameters(
derX.Value,
new DHParameters(para.P, para.G));
}
else if (algOid.Equals(OiwObjectIdentifiers.ElGamalAlgorithm))
{
ElGamalParameter para = new ElGamalParameter(
Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
DerInteger derX = (DerInteger)keyInfo.PrivateKey;
return new ElGamalPrivateKeyParameters(
derX.Value,
new ElGamalParameters(para.P, para.G));
}
else if (algOid.Equals(X9ObjectIdentifiers.IdDsa))
{
DerInteger derX = (DerInteger) keyInfo.PrivateKey;
Asn1Encodable ae = algID.Parameters;
DsaParameters parameters = null;
if (ae != null)
{
DsaParameter para = DsaParameter.GetInstance(ae.ToAsn1Object());
parameters = new DsaParameters(para.P, para.Q, para.G);
}
return new DsaPrivateKeyParameters(derX.Value, parameters);
}
else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey))
{
X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object());
X9ECParameters ecP;
if (para.IsNamedCurve)
{
// TODO ECGost3410NamedCurves support (returns ECDomainParameters though)
DerObjectIdentifier oid = (DerObjectIdentifier) para.Parameters;
ecP = X962NamedCurves.GetByOid(oid);
if (ecP == null)
{
ecP = SecNamedCurves.GetByOid(oid);
if (ecP == null)
{
ecP = NistNamedCurves.GetByOid(oid);
if (ecP == null)
{
ecP = TeleTrusTNamedCurves.GetByOid(oid);
}
}
}
}
else
{
ecP = new X9ECParameters((Asn1Sequence) para.Parameters);
}
ECDomainParameters dParams = new ECDomainParameters(
ecP.Curve,
ecP.G,
ecP.N,
ecP.H,
ecP.GetSeed());
ECPrivateKeyStructure ec = new ECPrivateKeyStructure(
Asn1Sequence.GetInstance(keyInfo.PrivateKey));
return new ECPrivateKeyParameters(ec.GetKey(), dParams);
}
else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001))
{
Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
ECPrivateKeyStructure ec = new ECPrivateKeyStructure(
Asn1Sequence.GetInstance(keyInfo.PrivateKey));
ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
if (ecP == null)
return null;
return new ECPrivateKeyParameters(ec.GetKey(), gostParams.PublicKeyParamSet);
}
else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94))
{
Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
DerOctetString derX = (DerOctetString) keyInfo.PrivateKey;
byte[] keyEnc = derX.GetOctets();
byte[] keyBytes = new byte[keyEnc.Length];
for (int i = 0; i != keyEnc.Length; i++)
{
keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // was little endian
}
BigInteger x = new BigInteger(1, keyBytes);
return new Gost3410PrivateKeyParameters(x, gostParams.PublicKeyParamSet);
}
else
{
throw new SecurityUtilityException("algorithm identifier in key not recognised");
}
}
public static AsymmetricKeyParameter DecryptKey(
char[] passPhrase,
EncryptedPrivateKeyInfo encInfo)
{
return CreateKey(PrivateKeyInfoFactory.CreatePrivateKeyInfo(passPhrase, encInfo));
}
public static AsymmetricKeyParameter DecryptKey(
char[] passPhrase,
byte[] encryptedPrivateKeyInfoData)
{
return DecryptKey(passPhrase, Asn1Object.FromByteArray(encryptedPrivateKeyInfoData));
}
public static AsymmetricKeyParameter DecryptKey(
char[] passPhrase,
Stream encryptedPrivateKeyInfoStream)
{
return DecryptKey(passPhrase, Asn1Object.FromStream(encryptedPrivateKeyInfoStream));
}
private static AsymmetricKeyParameter DecryptKey(
char[] passPhrase,
Asn1Object asn1Object)
{
return DecryptKey(passPhrase, EncryptedPrivateKeyInfo.GetInstance(asn1Object));
}
}
}
using System;
using System.Collections;
using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.Oiw;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.TeleTrust;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
namespace Org.BouncyCastle.Security
{
public sealed class PrivateKeyFactory
{
private PrivateKeyFactory()
{
}
public static AsymmetricKeyParameter CreateKey(
byte[] privateKeyInfoData)
{
return CreateKey(
PrivateKeyInfo.GetInstance(
Asn1Object.FromByteArray(privateKeyInfoData)));
}
public static AsymmetricKeyParameter CreateKey(
Stream inStr)
{
return CreateKey(
PrivateKeyInfo.GetInstance(
Asn1Object.FromStream(inStr)));
}
public static AsymmetricKeyParameter CreateKey(
PrivateKeyInfo keyInfo)
{
AlgorithmIdentifier algID = keyInfo.AlgorithmID;
DerObjectIdentifier algOid = algID.ObjectID;
if (algOid.Equals(PkcsObjectIdentifiers.RsaEncryption))
{
RsaPrivateKeyStructure keyStructure = new RsaPrivateKeyStructure(
Asn1Sequence.GetInstance(keyInfo.PrivateKey));
return new RsaPrivateCrtKeyParameters(
keyStructure.Modulus,
keyStructure.PublicExponent,
keyStructure.PrivateExponent,
keyStructure.Prime1,
keyStructure.Prime2,
keyStructure.Exponent1,
keyStructure.Exponent2,
keyStructure.Coefficient);
}
else if (algOid.Equals(PkcsObjectIdentifiers.DhKeyAgreement))
{
DHParameter para = new DHParameter(
Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
DerInteger derX = (DerInteger)keyInfo.PrivateKey;
BigInteger lVal = para.L;
int l = lVal == null ? 0 : lVal.IntValue;
DHParameters dhParams = new DHParameters(para.P, para.G, null, l);
return new DHPrivateKeyParameters(derX.Value, dhParams);
}
else if (algOid.Equals(OiwObjectIdentifiers.ElGamalAlgorithm))
{
ElGamalParameter para = new ElGamalParameter(
Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
DerInteger derX = (DerInteger)keyInfo.PrivateKey;
return new ElGamalPrivateKeyParameters(
derX.Value,
new ElGamalParameters(para.P, para.G));
}
else if (algOid.Equals(X9ObjectIdentifiers.IdDsa))
{
DerInteger derX = (DerInteger) keyInfo.PrivateKey;
Asn1Encodable ae = algID.Parameters;
DsaParameters parameters = null;
if (ae != null)
{
DsaParameter para = DsaParameter.GetInstance(ae.ToAsn1Object());
parameters = new DsaParameters(para.P, para.Q, para.G);
}
return new DsaPrivateKeyParameters(derX.Value, parameters);
}
else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey))
{
X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object());
X9ECParameters ecP;
if (para.IsNamedCurve)
{
// TODO ECGost3410NamedCurves support (returns ECDomainParameters though)
DerObjectIdentifier oid = (DerObjectIdentifier) para.Parameters;
ecP = X962NamedCurves.GetByOid(oid);
if (ecP == null)
{
ecP = SecNamedCurves.GetByOid(oid);
if (ecP == null)
{
ecP = NistNamedCurves.GetByOid(oid);
if (ecP == null)
{
ecP = TeleTrusTNamedCurves.GetByOid(oid);
}
}
}
}
else
{
ecP = new X9ECParameters((Asn1Sequence) para.Parameters);
}
ECDomainParameters dParams = new ECDomainParameters(
ecP.Curve,
ecP.G,
ecP.N,
ecP.H,
ecP.GetSeed());
ECPrivateKeyStructure ec = new ECPrivateKeyStructure(
Asn1Sequence.GetInstance(keyInfo.PrivateKey));
return new ECPrivateKeyParameters(ec.GetKey(), dParams);
}
else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001))
{
Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
ECPrivateKeyStructure ec = new ECPrivateKeyStructure(
Asn1Sequence.GetInstance(keyInfo.PrivateKey));
ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
if (ecP == null)
return null;
return new ECPrivateKeyParameters(ec.GetKey(), gostParams.PublicKeyParamSet);
}
else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94))
{
Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
DerOctetString derX = (DerOctetString) keyInfo.PrivateKey;
byte[] keyEnc = derX.GetOctets();
byte[] keyBytes = new byte[keyEnc.Length];
for (int i = 0; i != keyEnc.Length; i++)
{
keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // was little endian
}
BigInteger x = new BigInteger(1, keyBytes);
return new Gost3410PrivateKeyParameters(x, gostParams.PublicKeyParamSet);
}
else
{
throw new SecurityUtilityException("algorithm identifier in key not recognised");
}
}
public static AsymmetricKeyParameter DecryptKey(
char[] passPhrase,
EncryptedPrivateKeyInfo encInfo)
{
return CreateKey(PrivateKeyInfoFactory.CreatePrivateKeyInfo(passPhrase, encInfo));
}
public static AsymmetricKeyParameter DecryptKey(
char[] passPhrase,
byte[] encryptedPrivateKeyInfoData)
{
return DecryptKey(passPhrase, Asn1Object.FromByteArray(encryptedPrivateKeyInfoData));
}
public static AsymmetricKeyParameter DecryptKey(
char[] passPhrase,
Stream encryptedPrivateKeyInfoStream)
{
return DecryptKey(passPhrase, Asn1Object.FromStream(encryptedPrivateKeyInfoStream));
}
private static AsymmetricKeyParameter DecryptKey(
char[] passPhrase,
Asn1Object asn1Object)
{
return DecryptKey(passPhrase, EncryptedPrivateKeyInfo.GetInstance(asn1Object));
}
}
}

View File

@ -62,7 +62,11 @@ namespace Org.BouncyCastle.Security
Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
DerInteger derY = (DerInteger) keyInfo.GetPublicKey();
return new DHPublicKeyParameters(derY.Value, new DHParameters(para.P, para.G));
BigInteger lVal = para.L;
int l = lVal == null ? 0 : lVal.IntValue;
DHParameters dhParams = new DHParameters(para.P, para.G, null, l);
return new DHPublicKeyParameters(derY.Value, dhParams);
}
else if (algOid.Equals(OiwObjectIdentifiers.ElGamalAlgorithm))
{
@ -119,7 +123,7 @@ namespace Org.BouncyCastle.Security
}
else
{
ecP = new X9ECParameters((Asn1Sequence)para.Parameters.ToAsn1Object());
ecP = new X9ECParameters((Asn1Sequence)para.Parameters);
}
ECDomainParameters dParams = new ECDomainParameters(

View File

@ -11,6 +11,28 @@ namespace Org.BouncyCastle.Utilities
{
}
public static bool AreEqual(
bool[] a,
bool[] b)
{
if (a == b)
return true;
if (a == null || b == null)
return false;
if (a.Length != b.Length)
return false;
for (int i = 0; i < a.Length; i++)
{
if (a[i] != b[i])
return false;
}
return true;
}
/// <summary>
/// Are two arrays equal.
/// </summary>

View File

@ -1,6 +1,7 @@
using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Utilities
{
@ -9,6 +10,8 @@ namespace Org.BouncyCastle.Utilities
*/
public sealed class BigIntegers
{
private const int MaxIterations = 1000;
private BigIntegers()
{
}
@ -24,5 +27,45 @@ namespace Org.BouncyCastle.Utilities
{
return n.ToByteArrayUnsigned();
}
/**
* Return a random BigInteger not less than 'min' and not greater than 'max'
*
* @param min the least value that may be generated
* @param max the greatest value that may be generated
* @param random the source of randomness
* @return a random BigInteger value in the range [min,max]
*/
public static BigInteger CreateRandomInRange(
BigInteger min,
BigInteger max,
SecureRandom random)
{
int cmp = min.CompareTo(max);
if (cmp >= 0)
{
if (cmp > 0)
throw new ArgumentException("'min' may not be greater than 'max'");
return min;
}
if (min.BitLength > max.BitLength / 2)
{
return CreateRandomInRange(BigInteger.Zero, max.Subtract(min), random).Add(min);
}
for (int i = 0; i < MaxIterations; ++i)
{
BigInteger x = new BigInteger(max.BitLength, random);
if (x.CompareTo(min) >= 0 && x.CompareTo(max) <= 0)
{
return x;
}
}
// fall back to a faster (restricted) method
return new BigInteger(max.Subtract(min).BitLength - 1, random).Add(min);
}
}
}

View File

@ -157,7 +157,7 @@ namespace Org.BouncyCastle.X509
}
catch (Exception e)
{
throw new CertificateException(e.ToString());
throw new CertificateException("Failed to read certificate", e);
}
}

View File

@ -129,6 +129,49 @@ namespace Org.BouncyCastle.X509
tbsGen.SetSignature(sigAlgId);
}
/// <summary>
/// Set the subject unique ID - note: it is very rare that it is correct to do this.
/// </summary>
/// <param name="uniqueID"/>
public void SetSubjectUniqueID(
bool[] uniqueID)
{
tbsGen.SetSubjectUniqueID(booleanToBitString(uniqueID));
}
/// <summary>
/// Set the issuer unique ID - note: it is very rare that it is correct to do this.
/// </summary>
/// <param name="uniqueID"/>
public void SetIssuerUniqueID(
bool[] uniqueID)
{
tbsGen.SetIssuerUniqueID(booleanToBitString(uniqueID));
}
private DerBitString booleanToBitString(
bool[] id)
{
byte[] bytes = new byte[(id.Length + 7) / 8];
for (int i = 0; i != id.Length; i++)
{
if (id[i])
{
bytes[i / 8] |= (byte)(1 << ((7 - (i % 8))));
}
}
int pad = id.Length % 8;
if (pad == 0)
{
return new DerBitString(bytes);
}
return new DerBitString(bytes, 8 - pad);
}
/// <summary>
/// Add a given extension field for the standard extensions tag (tag 3).
/// </summary>