BouncyCastle update.
git-svn-id: svn://svn.code.sf.net/p/itextsharp/code/trunk@19 820d3149-562b-4f88-9aa4-a8e61a3485cfmaster
parent
f00f5ff42a
commit
9e5c88451d
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1
|
||||
{
|
||||
public class BerApplicationSpecific
|
||||
: DerApplicationSpecific
|
||||
{
|
||||
public BerApplicationSpecific(
|
||||
int tagNo,
|
||||
Asn1EncodableVector vec)
|
||||
: base(tagNo, vec)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Asn1
|
||||
{
|
||||
public interface IAsn1ApplicationSpecificParser
|
||||
: IAsn1Convertible
|
||||
{
|
||||
IAsn1Convertible ReadObject();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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(
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
@ -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");
|
||||
|
|
|
@ -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
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 =
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
@ -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())
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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(',');
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) { }
|
||||
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Pkix
|
||||
{
|
||||
public class PkixNameConstraintValidatorException : Exception
|
||||
{
|
||||
public PkixNameConstraintValidatorException(String msg)
|
||||
: base(msg)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ namespace Org.BouncyCastle.X509
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new CertificateException(e.ToString());
|
||||
throw new CertificateException("Failed to read certificate", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue