aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/core/src/main/jdk1.1
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/spongycastle/core/src/main/jdk1.1')
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/lang/UnsupportedOperationException.java14
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParameterGenerator.java96
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParameterGeneratorSpi.java16
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParameters.java103
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParametersSpi.java27
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/GeneralSecurityException.java14
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/InvalidAlgorithmParameterException.java13
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyFactory.java89
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyFactorySpi.java24
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyStore.java225
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyStoreException.java14
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyStoreSpi.java59
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/SecurityUtil.java114
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/UnrecoverableKeyException.java14
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRL.java20
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLException.java16
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLSelector.java39
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPath.java283
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilder.java243
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderException.java182
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderResult.java38
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderSpi.java50
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathParameters.java18
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidator.java250
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorException.java248
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorResult.java22
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorSpi.java59
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertSelector.java39
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStore.java352
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreException.java172
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreParameters.java52
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreSpi.java104
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertUtil.java556
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/Certificate.java80
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateEncodingException.java14
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateException.java16
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateExpiredException.java14
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactory.java183
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactorySpi.java111
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateNotYetValidException.java14
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateParsingException.java14
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CollectionCertStoreParameters.java117
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/LDAPCertStoreParameters.java130
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXBuilderParameters.java179
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathBuilderResult.java93
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathChecker.java155
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathValidatorResult.java136
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXParameters.java770
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyNode.java107
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyQualifierInfo.java196
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/TrustAnchor.java293
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRL.java77
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLEntry.java56
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java717
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java2461
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Certificate.java33
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Extension.java12
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java67
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAPrivateCrtKey.java16
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAPrivateKey.java13
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAPublicKey.java13
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/AlgorithmParameterSpec.java6
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/DSAParameterSpec.java34
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/DSAPrivateKeySpec.java40
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/DSAPublicKeySpec.java40
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/EncodedKeySpec.java19
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/InvalidKeySpecException.java16
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/InvalidParameterSpecException.java16
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/KeySpec.java6
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/PKCS8EncodedKeySpec.java20
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/PSSParameterSpec.java45
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAKeyGenParameterSpec.java35
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java159
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAOtherPrimeInfo.java80
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAPrivateCrtKeySpec.java64
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAPrivateKeySpec.java28
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAPublicKeySpec.java28
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/X509EncodedKeySpec.java20
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractCollection.java242
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractList.java281
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractMap.java164
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractSet.java42
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/ArrayList.java107
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/Arrays.java90
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/Collection.java21
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/Collections.java376
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/HashMap.java285
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/HashSet.java83
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/Iterator.java9
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/List.java15
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/ListIterator.java19
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/Map.java37
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/Set.java26
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/java/util/Sublist.java125
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1InputStream.java466
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1StreamParser.java247
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/DERApplicationSpecific.java276
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/BCStyle.java481
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/RFC4519Style.java380
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java573
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java122
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/digests/SkeinEngine.java817
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/encodings/PKCS1Encoding.java238
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/engines/NullEngine.java96
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/params/DSAParameterGenerationParameters.java80
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/params/HKDFParameters.java123
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/prng/BasicEntropySourceProvider.java57
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/prng/SP800SecureRandomBuilder.java289
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/signers/RSADigestSigner.java238
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReassembler.java136
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReliableHandshake.java457
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/UDPTransport.java106
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/i18n/LocalizedMessage.java464
-rw-r--r--libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/i18n/MissingEntryException.java63
114 files changed, 17939 insertions, 0 deletions
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/lang/UnsupportedOperationException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/lang/UnsupportedOperationException.java
new file mode 100644
index 000000000..86529c82b
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/lang/UnsupportedOperationException.java
@@ -0,0 +1,14 @@
+
+package java.lang;
+
+public class UnsupportedOperationException extends RuntimeException
+{
+ public UnsupportedOperationException()
+ {
+ }
+
+ public UnsupportedOperationException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParameterGenerator.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParameterGenerator.java
new file mode 100644
index 000000000..048108490
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParameterGenerator.java
@@ -0,0 +1,96 @@
+package java.security;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+public class AlgorithmParameterGenerator
+{
+ AlgorithmParameterGeneratorSpi spi;
+ Provider provider;
+ String algorithm;
+
+ protected AlgorithmParameterGenerator(
+ AlgorithmParameterGeneratorSpi paramGenSpi,
+ Provider provider,
+ String algorithm)
+ {
+ this.spi = paramGenSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ public final AlgorithmParameters generateParameters()
+ {
+ return spi.engineGenerateParameters();
+ }
+
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ public static AlgorithmParameterGenerator getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ try
+ {
+ SecurityUtil.Implementation imp = SecurityUtil.getImplementation("AlgorithmParameterGenerator", algorithm, null);
+
+ if (imp != null)
+ {
+ return new AlgorithmParameterGenerator((AlgorithmParameterGeneratorSpi)imp.getEngine(), imp.getProvider(), algorithm);
+ }
+
+ throw new NoSuchAlgorithmException("can't find algorithm " + algorithm);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+ }
+
+ public static AlgorithmParameterGenerator getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ SecurityUtil.Implementation imp = SecurityUtil.getImplementation("AlgorithmParameterGenerator", algorithm, provider);
+
+ if (imp != null)
+ {
+ return new AlgorithmParameterGenerator((AlgorithmParameterGeneratorSpi)imp.getEngine(), imp.getProvider(), algorithm);
+ }
+
+ throw new NoSuchAlgorithmException("can't find algorithm " + algorithm);
+ }
+
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ public final void init(
+ AlgorithmParameterSpec genParamSpec)
+ throws InvalidAlgorithmParameterException
+ {
+ spi.engineInit(genParamSpec, new SecureRandom());
+ }
+
+ public final void init(
+ AlgorithmParameterSpec genParamSpec,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ spi.engineInit(genParamSpec, random);
+ }
+
+ public final void init(
+ int size)
+ {
+ spi.engineInit(size, new SecureRandom());
+ }
+
+ public final void init(
+ int size,
+ SecureRandom random)
+ {
+ spi.engineInit(size, random);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParameterGeneratorSpi.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParameterGeneratorSpi.java
new file mode 100644
index 000000000..446f53bdb
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParameterGeneratorSpi.java
@@ -0,0 +1,16 @@
+package java.security;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+public abstract class AlgorithmParameterGeneratorSpi
+{
+ public AlgorithmParameterGeneratorSpi()
+ {
+ }
+
+ protected abstract AlgorithmParameters engineGenerateParameters();
+
+ protected abstract void engineInit(AlgorithmParameterSpec genParamSpec, SecureRandom random) throws InvalidAlgorithmParameterException;
+
+ protected abstract void engineInit(int size, SecureRandom random);
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParameters.java
new file mode 100644
index 000000000..14f2a5ad6
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParameters.java
@@ -0,0 +1,103 @@
+
+package java.security;
+
+import java.io.IOException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
+public class AlgorithmParameters extends Object
+{
+ private AlgorithmParametersSpi spi;
+ private Provider provider;
+ private String algorithm;
+
+ protected AlgorithmParameters(
+ AlgorithmParametersSpi paramSpi,
+ Provider provider,
+ String algorithm)
+ {
+ this.spi = paramSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ public final byte[] getEncoded() throws IOException
+ {
+ return spi.engineGetEncoded();
+ }
+
+ public final byte[] getEncoded(String format) throws IOException
+ {
+ return spi.engineGetEncoded(format);
+ }
+
+ public static AlgorithmParameters getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ try
+ {
+ SecurityUtil.Implementation imp = SecurityUtil.getImplementation("AlgorithmParameters", algorithm, null);
+
+ if (imp != null)
+ {
+ return new AlgorithmParameters((AlgorithmParametersSpi)imp.getEngine(), imp.getProvider(), algorithm);
+ }
+
+ throw new NoSuchAlgorithmException("can't find algorithm " + algorithm);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+ }
+
+ public static AlgorithmParameters getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ SecurityUtil.Implementation imp = SecurityUtil.getImplementation("AlgorithmParameters", algorithm, provider);
+
+ if (imp != null)
+ {
+ return new AlgorithmParameters((AlgorithmParametersSpi)imp.getEngine(), imp.getProvider(), algorithm);
+ }
+
+ throw new NoSuchAlgorithmException("can't find algorithm " + algorithm);
+ }
+
+ public final AlgorithmParameterSpec getParameterSpec(Class paramSpec)
+ throws InvalidParameterSpecException
+ {
+ return spi.engineGetParameterSpec(paramSpec);
+ }
+
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ public final void init(AlgorithmParameterSpec paramSpec)
+ throws InvalidParameterSpecException
+ {
+ spi.engineInit(paramSpec);
+ }
+
+ public final void init(byte[] params) throws IOException
+ {
+ spi.engineInit(params);
+ }
+
+ public final void init(byte[] params, String format) throws IOException
+ {
+ spi.engineInit(params, format);
+ }
+
+ public final String toString()
+ {
+ return spi.engineToString();
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParametersSpi.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParametersSpi.java
new file mode 100644
index 000000000..59519a343
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/AlgorithmParametersSpi.java
@@ -0,0 +1,27 @@
+
+package java.security;
+
+import java.io.IOException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
+public abstract class AlgorithmParametersSpi extends Object
+{
+ public AlgorithmParametersSpi()
+ {
+ }
+
+ protected abstract byte[] engineGetEncoded()
+ throws IOException;
+ protected abstract byte[] engineGetEncoded(String format)
+ throws IOException;
+ protected abstract AlgorithmParameterSpec engineGetParameterSpec(Class paramSpec)
+ throws InvalidParameterSpecException;
+ protected abstract void engineInit(AlgorithmParameterSpec paramSpec)
+ throws InvalidParameterSpecException;
+ protected abstract void engineInit(byte[] params)
+ throws IOException;
+ protected abstract void engineInit(byte[] params, String format)
+ throws IOException;
+ protected abstract String engineToString();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/GeneralSecurityException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/GeneralSecurityException.java
new file mode 100644
index 000000000..fb4a5f4d5
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/GeneralSecurityException.java
@@ -0,0 +1,14 @@
+
+package java.security;
+
+public class GeneralSecurityException extends Exception
+{
+ public GeneralSecurityException()
+ {
+ }
+
+ public GeneralSecurityException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/InvalidAlgorithmParameterException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/InvalidAlgorithmParameterException.java
new file mode 100644
index 000000000..e56228c29
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/InvalidAlgorithmParameterException.java
@@ -0,0 +1,13 @@
+
+package java.security;
+
+public class InvalidAlgorithmParameterException extends GeneralSecurityException {
+ public InvalidAlgorithmParameterException()
+ {
+ }
+
+ public InvalidAlgorithmParameterException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyFactory.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyFactory.java
new file mode 100644
index 000000000..320aac3f8
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyFactory.java
@@ -0,0 +1,89 @@
+
+package java.security;
+
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+
+public class KeyFactory extends Object
+{
+ private KeyFactorySpi keyFacSpi;
+ private Provider provider;
+ private String algorithm;
+
+ protected KeyFactory(
+ KeyFactorySpi keyFacSpi,
+ Provider provider,
+ String algorithm)
+ {
+ this.keyFacSpi = keyFacSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ public final PrivateKey generatePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ return keyFacSpi.engineGeneratePrivate(keySpec);
+ }
+
+ public final PublicKey generatePublic(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ return keyFacSpi.engineGeneratePublic(keySpec);
+ }
+
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ public static KeyFactory getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ try
+ {
+ SecurityUtil.Implementation imp = SecurityUtil.getImplementation("KeyFactory", algorithm, null);
+
+ if (imp != null)
+ {
+ return new KeyFactory((KeyFactorySpi)imp.getEngine(), imp.getProvider(), algorithm);
+ }
+
+ throw new NoSuchAlgorithmException("can't find algorithm " + algorithm);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+ }
+
+ public static KeyFactory getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ SecurityUtil.Implementation imp = SecurityUtil.getImplementation("KeyFactory", algorithm, null);
+
+ if (imp != null)
+ {
+ return new KeyFactory((KeyFactorySpi)imp.getEngine(), imp.getProvider(), algorithm);
+ }
+
+ throw new NoSuchAlgorithmException("can't find algorithm " + algorithm);
+ }
+
+ public final KeySpec getKeySpec(Key key, Class keySpec)
+ throws InvalidKeySpecException
+ {
+ return keyFacSpi.engineGetKeySpec(key, keySpec);
+ }
+
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ public final Key translateKey(Key key)
+ throws InvalidKeyException
+ {
+ return keyFacSpi.engineTranslateKey(key);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyFactorySpi.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyFactorySpi.java
new file mode 100644
index 000000000..6d160e7cf
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyFactorySpi.java
@@ -0,0 +1,24 @@
+
+package java.security;
+
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+
+public abstract class KeyFactorySpi extends Object
+{
+ public KeyFactorySpi()
+ {
+ }
+
+ protected abstract PrivateKey engineGeneratePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException;
+
+ protected abstract PublicKey engineGeneratePublic(KeySpec keySpec)
+ throws InvalidKeySpecException;
+
+ protected abstract KeySpec engineGetKeySpec(Key key, Class keySpec)
+ throws InvalidKeySpecException;
+
+ protected abstract Key engineTranslateKey(Key key)
+ throws InvalidKeyException;
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyStore.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyStore.java
new file mode 100644
index 000000000..0ded759a6
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyStore.java
@@ -0,0 +1,225 @@
+
+package java.security;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.util.Date;
+import java.util.Enumeration;
+
+public class KeyStore extends Object
+{
+ private KeyStoreSpi keyStoreSpi;
+ private Provider provider;
+ private String type;
+ private boolean initialised;
+
+ protected KeyStore(
+ KeyStoreSpi keyStoreSpi,
+ Provider provider,
+ String type)
+ {
+ this.keyStoreSpi = keyStoreSpi;
+ this.provider = provider;
+ this.type = type;
+ this.initialised = false;
+ }
+
+ public final Enumeration aliases() throws KeyStoreException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ return keyStoreSpi.engineAliases();
+ }
+
+ public final boolean containsAlias(String alias) throws KeyStoreException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ return keyStoreSpi.engineContainsAlias(alias);
+ }
+
+ public final void deleteEntry(String alias) throws KeyStoreException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ keyStoreSpi.engineDeleteEntry(alias);
+ }
+
+ public final Certificate getCertificate(String alias)
+ throws KeyStoreException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ return keyStoreSpi.engineGetCertificate(alias);
+ }
+
+ public final String getCertificateAlias(Certificate cert)
+ throws KeyStoreException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ return keyStoreSpi.engineGetCertificateAlias(cert);
+ }
+
+ public final Certificate[] getCertificateChain(String alias)
+ throws KeyStoreException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ return keyStoreSpi.engineGetCertificateChain(alias);
+ }
+
+ public final Date getCreationDate(String alias) throws KeyStoreException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ return keyStoreSpi.engineGetCreationDate(alias);
+ }
+
+ public static final String getDefaultType()
+ {
+ return "JKS";
+ }
+
+ public static KeyStore getInstance(String type) throws KeyStoreException
+ {
+ try
+ {
+ SecurityUtil.Implementation imp = SecurityUtil.getImplementation("KeyStore", type, null);
+
+ if (imp != null)
+ {
+ return new KeyStore((KeyStoreSpi)imp.getEngine(), imp.getProvider(), type);
+ }
+
+ throw new KeyStoreException("can't find type " + type);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new KeyStoreException(type + " not found");
+ }
+ }
+
+ public static KeyStore getInstance(String type, String provider)
+ throws KeyStoreException, NoSuchProviderException
+ {
+ SecurityUtil.Implementation imp = SecurityUtil.getImplementation("KeyStore", type, provider);
+
+ if (imp != null)
+ {
+ return new KeyStore((KeyStoreSpi)imp.getEngine(), imp.getProvider(), type);
+ }
+
+ throw new KeyStoreException("can't find type " + type);
+ }
+
+ public final Key getKey(String alias, char[] password)
+ throws KeyStoreException, NoSuchAlgorithmException,
+ UnrecoverableKeyException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ return keyStoreSpi.engineGetKey(alias, password);
+ }
+
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ public final String getType()
+ {
+ return type;
+ }
+
+ public final boolean isCertificateEntry(String alias)
+ throws KeyStoreException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ return keyStoreSpi.engineIsCertificateEntry(alias);
+ }
+
+ public final boolean isKeyEntry(String alias) throws KeyStoreException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ return keyStoreSpi.engineIsKeyEntry(alias);
+ }
+
+ public final void load(
+ InputStream stream,
+ char[] password)
+ throws IOException, NoSuchAlgorithmException, CertificateException
+ {
+ keyStoreSpi.engineLoad(stream, password);
+ initialised = true;
+ }
+
+ public final void setCertificateEntry(String alias, Certificate cert)
+ throws KeyStoreException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ keyStoreSpi.engineSetCertificateEntry(alias, cert);
+ }
+
+ public final void setKeyEntry(
+ String alias,
+ Key key,
+ char[] password,
+ Certificate[] chain)
+ throws KeyStoreException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
+ }
+
+ public final void setKeyEntry(
+ String alias,
+ byte[] key,
+ Certificate[] chain)
+ throws KeyStoreException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ keyStoreSpi.engineSetKeyEntry(alias, key, chain);
+ }
+
+ public final int size() throws KeyStoreException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ return keyStoreSpi.engineSize();
+ }
+
+ public final void store(
+ OutputStream stream,
+ char[] password)
+ throws KeyStoreException, IOException, NoSuchAlgorithmException,
+ CertificateException
+ {
+ if ( !initialised )
+ throw new KeyStoreException("KeyStore not initialised.");
+
+ keyStoreSpi.engineStore(stream, password);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyStoreException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyStoreException.java
new file mode 100644
index 000000000..2e07503d2
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyStoreException.java
@@ -0,0 +1,14 @@
+
+package java.security;
+
+public class KeyStoreException extends GeneralSecurityException
+{
+ public KeyStoreException()
+ {
+ }
+
+ public KeyStoreException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyStoreSpi.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyStoreSpi.java
new file mode 100644
index 000000000..87c484528
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/KeyStoreSpi.java
@@ -0,0 +1,59 @@
+
+package java.security;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.util.Date;
+import java.util.Enumeration;
+
+public abstract class KeyStoreSpi extends Object
+{
+ public KeyStoreSpi()
+ {
+ }
+
+ public abstract Enumeration engineAliases();
+
+ public abstract boolean engineContainsAlias(String alias);
+
+ public abstract void engineDeleteEntry(String alias)
+ throws KeyStoreException;
+
+ public abstract Certificate engineGetCertificate(String alias);
+
+ public abstract String engineGetCertificateAlias(Certificate cert);
+
+ public abstract Certificate[] engineGetCertificateChain(String alias);
+
+ public abstract Date engineGetCreationDate(String alias);
+
+ public abstract Key engineGetKey(String alias, char[] password)
+ throws NoSuchAlgorithmException, UnrecoverableKeyException;
+
+ public abstract boolean engineIsCertificateEntry(String alias);
+
+ public abstract boolean engineIsKeyEntry(String alias);
+
+ public abstract void engineLoad(InputStream stream, char[] password)
+ throws IOException, NoSuchAlgorithmException, CertificateException;
+
+ public abstract void engineSetCertificateEntry(
+ String alias, Certificate cert)
+ throws KeyStoreException;
+
+ public abstract void engineSetKeyEntry(
+ String alias, Key key, char[] password, Certificate[] chain)
+ throws KeyStoreException;
+
+ public abstract void engineSetKeyEntry(
+ String alias, byte[] key, Certificate[] chain)
+ throws KeyStoreException;
+
+ public abstract int engineSize();
+
+ public abstract void engineStore(OutputStream stream, char[] password)
+ throws IOException, NoSuchAlgorithmException, CertificateException;
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/SecurityUtil.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/SecurityUtil.java
new file mode 100644
index 000000000..13c313cf6
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/SecurityUtil.java
@@ -0,0 +1,114 @@
+package java.security;
+
+
+class SecurityUtil
+{
+ static class Implementation
+ {
+ Object engine;
+ Provider provider;
+
+ Implementation(
+ Object engine,
+ Provider provider)
+ {
+ this.engine = engine;
+ this.provider = provider;
+ }
+
+ Object getEngine()
+ {
+ return engine;
+ }
+
+ Provider getProvider()
+ {
+ return provider;
+ }
+ }
+
+ /**
+ * see if we can find an algorithm (or its alias and what it represents) in
+ * the property table for the given provider.
+ *
+ * @return null if no algorithm found, an Implementation if it is.
+ */
+ static private Implementation getImplementation(
+ String baseName,
+ String algorithm,
+ Provider prov)
+ {
+ String alias;
+
+ while ((alias = prov.getProperty("Alg.Alias." + baseName + "." + algorithm)) != null)
+ {
+ algorithm = alias;
+ }
+
+ String className = prov.getProperty(baseName + "." + algorithm);
+
+ if (className != null)
+ {
+ try
+ {
+ return new Implementation(Class.forName(className).newInstance(), prov);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new IllegalStateException(
+ "algorithm " + algorithm + " in provider " + prov.getName() + " but no class found!");
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException(
+ "algorithm " + algorithm + " in provider " + prov.getName() + " but class inaccessible!");
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * return an implementation for a given algorithm/provider.
+ * If the provider is null, we grab the first avalaible who has the required algorithm.
+ *
+ * @return null if no algorithm found, an Implementation if it is.
+ * @exception NoSuchProviderException if a provider is specified and not found.
+ */
+ static Implementation getImplementation(
+ String baseName,
+ String algorithm,
+ String provider)
+ throws NoSuchProviderException
+ {
+ if (provider == null)
+ {
+ Provider[] prov = Security.getProviders();
+
+ //
+ // search every provider looking for the algorithm we want.
+ //
+ for (int i = 0; i != prov.length; i++)
+ {
+ Implementation imp = getImplementation(baseName, algorithm, prov[i]);
+ if (imp != null)
+ {
+ return imp;
+ }
+ }
+ }
+ else
+ {
+ Provider prov = Security.getProvider(provider);
+
+ if (prov == null)
+ {
+ throw new NoSuchProviderException("Provider " + provider + " not found");
+ }
+
+ return getImplementation(baseName, algorithm, prov);
+ }
+
+ return null;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/UnrecoverableKeyException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/UnrecoverableKeyException.java
new file mode 100644
index 000000000..7a1294a1c
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/UnrecoverableKeyException.java
@@ -0,0 +1,14 @@
+
+package java.security;
+
+public class UnrecoverableKeyException extends GeneralSecurityException
+{
+ public UnrecoverableKeyException()
+ {
+ }
+
+ public UnrecoverableKeyException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRL.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRL.java
new file mode 100644
index 000000000..2eb219e07
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRL.java
@@ -0,0 +1,20 @@
+
+package java.security.cert;
+
+public abstract class CRL
+{
+ private String type;
+
+ protected CRL(String type)
+ {
+ this.type = type;
+ }
+
+ public final String getType()
+ {
+ return type;
+ }
+
+ public abstract boolean isRevoked(Certificate cert);
+ public abstract String toString();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLException.java
new file mode 100644
index 000000000..f079b8beb
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLException.java
@@ -0,0 +1,16 @@
+
+package java.security.cert;
+
+import java.security.GeneralSecurityException;
+
+public class CRLException extends GeneralSecurityException
+{
+ public CRLException()
+ {
+ }
+
+ public CRLException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLSelector.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLSelector.java
new file mode 100644
index 000000000..2e4ff616a
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLSelector.java
@@ -0,0 +1,39 @@
+package java.security.cert;
+
+/**
+ * A selector that defines a set of criteria for selecting <code>CRL</code>s.
+ * Classes that implement this interface are often used to specify
+ * which <code>CRL</code>s should be retrieved from a <code>CertStore</code>.<br />
+ * <br />
+ * <b>Concurrent Access</b><br />
+ * <br />
+ * Unless otherwise specified, the methods defined in this interface 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 CRL
+ * @see CertStore
+ * @see CertStore#getCRLs
+ **/
+public interface CRLSelector extends Cloneable
+{
+ /**
+ * Decides whether a <code>CRL</code> should be selected.
+ *
+ * @param crl the <code>CRL</code> to be checked
+ *
+ * @return <code>true</code> if the <code>CRL</code> should be selected,
+ * <code>false</code> otherwise
+ */
+ public boolean match(CRL crl);
+
+ /**
+ * Makes a copy of this <code>CRLSelector</code>. Changes to the
+ * copy will not affect the original and vice versa.
+ *
+ * @return a copy of this <code>CRLSelector</code>
+ */
+ public Object clone();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPath.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPath.java
new file mode 100644
index 000000000..ceb5cd189
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPath.java
@@ -0,0 +1,283 @@
+package java.security.cert;
+
+import java.io.ByteArrayInputStream;
+import java.io.NotSerializableException;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * 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
+ */
+public abstract class CertPath extends Object implements Serializable
+{
+ private String type;
+
+ /**
+ * Alternate <code>CertPath</code> class for serialization.
+ **/
+ protected static class CertPathRep
+ implements Serializable
+ {
+ private String type;
+ private byte[] data;
+
+ /**
+ * Creates a <code>CertPathRep</code> with the specified
+ * type and encoded form of a certification path.
+ *
+ * @param type the standard name of a CertPath
+ * @param typedata the encoded form of the certification
+ * path
+ **/
+ protected CertPathRep(String type, byte[] data)
+ {
+ this.type = type;
+ this.data = data;
+ }
+
+ /**
+ * Returns a CertPath constructed from the type and data.
+ *
+ * @return the resolved CertPath object
+ * @exception ObjectStreamException if a CertPath could not be constructed
+ **/
+ protected Object readResolve()
+ throws ObjectStreamException
+ {
+ try {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(data);
+ CertificateFactory cf = CertificateFactory.getInstance(type);
+ return cf.generateCertPath(inStream);
+ } catch ( CertificateException ce ) {
+ throw new NotSerializableException(" java.security.cert.CertPath: " + type);
+ }
+ }
+ }
+
+ /**
+ * 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
+ **/
+ protected CertPath(String type)
+ {
+ this.type = type;
+ }
+
+ /**
+ * Returns the type of Certificates in this certification
+ * path. This is the same string that would be returned by
+ * {@link Certificate#getType() cert.getType()} for all
+ * Certificates in the certification path.
+ *
+ * @return the type of Certificates in this certification path (never null)
+ **/
+ public String getType()
+ {
+ return type;
+ }
+
+ /**
+ * 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 abstract Iterator getEncodings();
+
+ /**
+ * 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 boolean equals(Object other)
+ {
+ if (!( other instanceof CertPath ) )
+ return false;
+
+ CertPath otherCertPath = (CertPath)other;
+ if ( ! getType().equals(otherCertPath.getType()) )
+ return false;
+ return getCertificates().equals(otherCertPath.getCertificates());
+ }
+
+ /**
+ * Returns the hashcode for this certification path. The hash
+ * code of a certification path is defined to be the result of
+ * the following calculation:
+ * <pre>
+ * hashCode = path.getType().hashCode();
+ * hashCode = 31 * hashCode + path.getCertificates().hashCode();
+ * </pre>
+ * This ensures that path1.equals(path2) implies that
+ * path1.hashCode()==path2.hashCode() for any two
+ * certification paths, path1 and path2, as required by the
+ * general contract of Object.hashCode.
+ *
+ * @return The hashcode value for this certification path
+ *
+ * @see #equals(Object)
+ **/
+ public int hashCode()
+ {
+ return getType().hashCode() * 31 + getCertificates().hashCode();
+ }
+
+ /**
+ * Returns a string representation of this certification
+ * path. This calls the toString method on each of the
+ * Certificates in the path.
+ *
+ * @return a string representation of this certification path
+ **/
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer();
+ List certs = getCertificates();
+ ListIterator iter = certs.listIterator();
+ s.append('\n').append(getType()).append(" Cert Path: length = ").append(certs.size()).append("\n[\n");
+ while ( iter.hasNext() ) {
+ s.append("=========================================================Certificate ").append(iter.nextIndex()).append('\n');
+ s.append(iter.next()).append('\n');
+ s.append("========================================================Certificate end\n\n\n");
+ }
+ s.append("\n]");
+ return s.toString();
+ }
+
+ /**
+ * Returns the encoded form of this certification path, using
+ * the default encoding.
+ *
+ * @return the encoded bytes
+ *
+ * @exception CertificateEncodingException if an encoding error occurs
+ **/
+ public abstract byte[] getEncoded()
+ throws CertificateEncodingException;
+
+ /**
+ * 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 abstract byte[] getEncoded(String encoding)
+ throws CertificateEncodingException;
+
+ /**
+ * Returns the list of certificates in this certification
+ * path. The List returned must be immutable and thread-safe.
+ *
+ * @return an immutable List of Certificates (may be empty, but not null)
+ **/
+ public abstract List getCertificates();
+
+ /**
+ * Replaces the CertPath to be serialized with a CertPathRep
+ * object.
+ *
+ * @return the CertPathRep to be serialized
+ *
+ * @exception ObjectStreamException if a CertPathRep object
+ * representing this certification path could not be created
+ **/
+ protected Object writeReplace()
+ throws ObjectStreamException
+ {
+ try {
+ return new CertPathRep( getType(), getEncoded() );
+ } catch ( CertificateException ce ) {
+ throw new NotSerializableException( " java.security.cert.CertPath: " + getType() );
+ }
+ }
+}
+
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilder.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilder.java
new file mode 100644
index 000000000..b3adbf15f
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilder.java
@@ -0,0 +1,243 @@
+package java.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.Security;
+
+/**
+ * A class for building certification paths (also known as certificate
+ * chains).<br />
+ * <br />
+ * This class uses a provider-based architecture, as described in the
+ * Java Cryptography Architecture. To create a
+ * <code>CertPathBuilder</code>, call one of the static
+ * <code>getInstance</code> methods, passing in the algorithm name of
+ * the CertPathBuilder desired and optionally the name of the provider
+ * desired.<br />
+ * <br />
+ * Once a <code>CertPathBuilder</code> object has been created,
+ * certification paths can be constructed by calling the
+ * {@link #build build} method and passing it an algorithm-specific set
+ * of parameters. If successful, the result (including the CertPath
+ * that was built) is returned in an object that implements the
+ * <code>CertPathBuilderResult</code> interface.<br />
+ * <br />
+ * <strong>Concurrent Access</strong><br />
+ * <br />
+ * The static methods of this class are guaranteed to be
+ * thread-safe. Multiple threads may concurrently invoke the static
+ * methods defined in this class with no ill effects.<br />
+ * <br />
+ * However, this is not true for the non-static methods defined by
+ * this class. Unless otherwise documented by a specific provider,
+ * threads that need to access a single <code>CertPathBuilder</code>
+ * instance concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating a
+ * different <code>CertPathBuilder</code> instance need not
+ * synchronize.<br />
+ * <br />
+ * Uses {@link CertUtil CertUtil} to actualiy load the SPI classes.
+ *
+ * @see CertUtil
+ **/
+public class CertPathBuilder extends Object
+{
+ private CertPathBuilderSpi builderSpi;
+ private Provider provider;
+ private String algorithm;
+
+ /**
+ * Creates a CertPathBuilder object of the given algorithm, and
+ * encapsulates the given provider implementation (SPI object)
+ * in it.
+ *
+ * @param builderSpi the provider implementation
+ * @param provider the provider
+ * @param algorithm the algorithm name
+ **/
+ protected CertPathBuilder(CertPathBuilderSpi builderSpi,
+ Provider provider,
+ String algorithm)
+ {
+ this.builderSpi = builderSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns a CertPathBuilder object that implements the
+ * specified algorithm.<br />
+ * <br />
+ * If the default provider package provides an implementation
+ * of the specified CertPathBuilder algorithm, an instance of
+ * CertPathBuilder containing that implementation is
+ * returned. If the requested algorithm is not available in
+ * the default package, other packages are searched.<br />
+ * <br />
+ * @param algorithm the name of the requested CertPathBuilder algorithm
+ *
+ * @return a CertPathBuilder object that implements the
+ * specified algorithm
+ *
+ * @exception NoSuchAlgorithmException if the requested
+ * algorithm is not available in the default provider package
+ * or any of the other provider packages that were searched
+ **/
+ public static CertPathBuilder getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ try {
+ CertUtil.Implementation imp =
+ CertUtil.getImplementation("CertPathBuilder", algorithm, (String)null);
+ if (imp != null)
+ {
+ return new CertPathBuilder((CertPathBuilderSpi)imp.getEngine(),
+ imp.getProvider(), algorithm);
+ }
+ } catch ( NoSuchProviderException ex ) {}
+ throw new NoSuchAlgorithmException("can't find type " + algorithm);
+ }
+
+ /**
+ * Returns a CertPathBuilder object that implements the
+ * specified algorithm, as supplied by the specified provider.
+ *
+ * @param algorithm the name of the requested CertPathBuilder
+ * algorithm
+ * @param provider the name of the provider
+ *
+ * @return a CertPathBuilder object that implements the
+ * specified algorithm, as supplied by the specified provider
+ *
+ * @exception NoSuchAlgorithmException if the requested algorithm
+ * is not available from the specified provider
+ * @exception NoSuchProviderException if the provider has not
+ * been configured
+ * @exception IllegalArgumentException if the provider is null
+ **/
+ public static CertPathBuilder getInstance(String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException,
+ NoSuchProviderException
+ {
+ if ( provider == null )
+ throw new IllegalArgumentException("provider must be non-null");
+ CertUtil.Implementation imp =
+ CertUtil.getImplementation("CertPathBuilder", algorithm, provider);
+
+ if (imp != null)
+ {
+ return new CertPathBuilder((CertPathBuilderSpi)imp.getEngine(),
+ imp.getProvider(), algorithm);
+ }
+ throw new NoSuchAlgorithmException("can't find type " + algorithm);
+ }
+
+ /**
+ * Returns a CertPathBuilder object that implements the
+ * specified algorithm, as supplied by the specified
+ * provider. Note: the provider doesn't have to be registered.
+ *
+ * @param algorithm the name of the requested CertPathBuilder
+ * algorithm
+ * @param provider the provider
+ * @return a CertPathBuilder object that implements the
+ * specified algorithm, as supplied by the specified provider
+ *
+ * @exception NoSuchAlgorithmException if the requested algorithm
+ * is not available from the specified provider
+ * @exception IllegalArgumentException if the provider is null.
+ **/
+ public static CertPathBuilder getInstance(String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if ( provider == null )
+ throw new IllegalArgumentException("provider must be non-null");
+ CertUtil.Implementation imp =
+ CertUtil.getImplementation("CertPathBuilder", algorithm, provider);
+
+ if (imp != null)
+ {
+ return new CertPathBuilder((CertPathBuilderSpi)imp.getEngine(),
+ provider, algorithm);
+ }
+ throw new NoSuchAlgorithmException("can't find type " + algorithm);
+ }
+
+ /**
+ * Returns the provider of this <code>CertPathBuilder</code>.
+ *
+ * @return the provider of this <code>CertPathBuilder</code>
+ **/
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Returns the name of the algorithm of this
+ * <code>CertPathBuilder</code>.
+ *
+ * @return the name of the algorithm of this <code>CertPathBuilder</code>
+ **/
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Attempts to build a certification path using the specified algorithm
+ * parameter set.
+ *
+ * @param params the algorithm parameters
+ *
+ * @return the result of the build algorithm
+ *
+ * @exception CertPathBuilderException if the builder is unable to construct
+ * a certification path that satisfies the specified parameters
+ * @exception InvalidAlgorithmParameterException if the specified parameters * are inappropriate for this <code>CertPathBuilder</code>
+ */
+ public final CertPathBuilderResult build(CertPathParameters params)
+ throws CertPathBuilderException,
+ InvalidAlgorithmParameterException
+ {
+ return builderSpi.engineBuild(params);
+ }
+
+
+ /**
+ * Returns the default <code>CertPathBuilder</code> type as specified in
+ * the Java security properties file, or the string &quot;PKIX&quot;
+ * if no such property exists. The Java security properties file is
+ * located in the file named &lt;JAVA_HOME&gt;/lib/security/java.security,
+ * where &lt;JAVA_HOME&gt; refers to the directory where the SDK was
+ * installed.<br />
+ * <br />
+ * The default <code>CertPathBuilder</code> type can be used by
+ * applications that do not want to use a hard-coded type when calling one
+ * of the <code>getInstance</code> methods, and want to provide a default
+ * type in case a user does not specify its own.<br />
+ * <br />
+ * The default <code>CertPathBuilder</code> type can be changed by
+ * setting the value of the "certpathbuilder.type" security property
+ * (in the Java security properties file) to the desired type.
+ *
+ * @return the default <code>CertPathBuilder</code> type as specified
+ * in the Java security properties file, or the string &quot;PKIX&quot;
+ * if no such property exists.
+ */
+ public static final String getDefaultType()
+ {
+ String defaulttype = null;
+ defaulttype = Security.getProperty("certpathbuilder.type");
+
+ if ( defaulttype == null || defaulttype.length() <= 0 )
+ return "PKIX";
+ else
+ return defaulttype;
+ }
+}
+
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderException.java
new file mode 100644
index 000000000..13b60891e
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderException.java
@@ -0,0 +1,182 @@
+package java.security.cert;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.security.GeneralSecurityException;
+
+/**
+ * An exception indicating one of a variety of problems encountered
+ * when building a certification path with a
+ * <code>CertPathBuilder</code>.<br />
+ * <br />
+ * A <code>CertPathBuilderException</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 />
+ * <strong>Concurrent Access</strong><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 CertPathBuilder
+ **/
+public class CertPathBuilderException extends GeneralSecurityException
+{
+ private Throwable cause;
+
+ /**
+ * Creates a <code>CertPathBuilderException</code> with <code>null</code>
+ * as its detail message.
+ */
+ public CertPathBuilderException()
+ {
+ }
+
+ /**
+ * Creates a <code>CertPathBuilderException</code> with the given detail
+ * message. The detail message is a <code>String</code> that describes
+ * this particular exception in more detail.
+ *
+ * @param msg
+ * the detail message
+ */
+ public CertPathBuilderException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Creates a <code>CertPathBuilderException</code> that wraps the
+ * specified throwable. This allows any exception to be converted into a
+ * <code>CertPathBuilderException</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()} method). (A null value is permitted, and
+ * indicates that the cause is nonexistent or unknown.)
+ */
+ public CertPathBuilderException(String message, Throwable cause)
+ {
+ super(message);
+ this.cause = cause;
+ }
+
+ /**
+ * Creates a <code>CertPathBuilderException</code> with the specified
+ * detail message and cause.
+ *
+ * @param msg
+ * the detail message
+ * @param cause
+ * the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A null value is permitted, and
+ * indicates that the cause is nonexistent or unknown.)
+ */
+ public CertPathBuilderException(Throwable cause)
+ {
+ this.cause = cause;
+ }
+
+ /**
+ * Returns the internal (wrapped) cause, or null 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 the detail message for this CertPathBuilderException.
+ *
+ * @return the detail message, or <code>null</code> if neither the message
+ * nor internal cause were specified
+ */
+ public String getMessage()
+ {
+ String message = super.getMessage();
+
+ if (message == null && cause == null)
+ {
+ return null;
+ }
+
+ if (cause != null)
+ {
+ return cause.getMessage();
+ }
+
+ return message;
+ }
+
+ /**
+ * 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>CertPathBuilderException</code>
+ */
+ public String toString()
+ {
+ String message = getMessage();
+ if (message == null)
+ {
+ return "";
+ }
+
+ return message;
+ }
+
+ /**
+ * Prints a stack trace to <code>System.err</code>, including the
+ * backtrace of the cause, if any.
+ */
+ public void printStackTrace()
+ {
+ printStackTrace(System.err);
+ }
+
+ /**
+ * Prints a stack trace to a <code>PrintStream</code>, including the
+ * backtrace of the cause, if any.
+ *
+ * @param ps
+ * the <code>PrintStream</code> to use for output
+ */
+ public void printStackTrace(PrintStream ps)
+ {
+ super.printStackTrace(ps);
+ if (getCause() != null)
+ {
+ getCause().printStackTrace(ps);
+ }
+ }
+
+ /**
+ * Prints a stack trace to a <code>PrintWriter</code>, including the
+ * backtrace of the cause, if any.
+ *
+ * @param ps
+ * the <code>PrintWriter</code> to use for output
+ */
+ public void printStackTrace(PrintWriter pw)
+ {
+ super.printStackTrace(pw);
+ if (getCause() != null)
+ {
+ getCause().printStackTrace(pw);
+ }
+ }
+}
+
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderResult.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderResult.java
new file mode 100644
index 000000000..c0482bc4e
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderResult.java
@@ -0,0 +1,38 @@
+package java.security.cert;
+
+/**
+ * A specification of the result of a certification path builder algorithm.
+ * All results returned by the {@link CertPathBuilder#build CertPathBuilder.build} method
+ * must implement this interface.<br />
+ * <br />
+ * At a minimum, a CertPathBuilderResult contains the CertPath built by the
+ * CertPathBuilder instance. Implementations of this interface may add methods
+ * to return implementation or algorithm specific information, such as
+ * debugging information or certification path validation results.<br />
+ * <br />
+ * <strong>Concurrent Access</strong><br />
+ * <br />
+ * Unless otherwise specified, the methods defined in this interface 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.
+ **/
+public interface CertPathBuilderResult extends Cloneable
+{
+ /**
+ * Returns the built certification path.
+ *
+ * @return the certification path (never <code>null</code>)
+ */
+ public CertPath getCertPath();
+
+ /**
+ * Makes a copy of this <code>CertPathBuilderResult</code>.
+ * Changes to the copy will not affect the original and vice
+ * versa.
+ *
+ * @return a copy of this CertPathBuilderResult
+ */
+ public Object clone();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderSpi.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderSpi.java
new file mode 100644
index 000000000..be044fa30
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderSpi.java
@@ -0,0 +1,50 @@
+package java.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+
+/**
+ * The Service Provider Interface (SPI) for the CertPathBuilder
+ * class. All CertPathBuilder implementations must include a class
+ * (the SPI class) that extends this class (CertPathBuilderSpi) and
+ * implements all of its methods. In general, instances of this class
+ * should only be accessed through the CertPathBuilder 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
+ * CertPathBuilderSpi instance concurrently should synchronize amongst
+ * themselves and provide the necessary locking before calling the
+ * wrapping CertPathBuilder object.<br />
+ * <br />
+ * However, implementations of CertPathBuilderSpi may still encounter
+ * concurrency issues, since multiple threads each manipulating a
+ * different CertPathBuilderSpi instance need not synchronize.
+ **/
+public abstract class CertPathBuilderSpi
+ extends Object
+{
+ /**
+ * The default constructor.
+ */
+ public CertPathBuilderSpi() {}
+
+ /**
+ * Attempts to build a certification path using the specified
+ * algorithm parameter set.
+ *
+ * @param params the algorithm parameters
+ *
+ * @return the result of the build algorithm
+ *
+ * @exception CertPathBuilderException if the builder is unable
+ * to construct a certification path that satisfies the
+ * specified
+ * @exception parametersInvalidAlgorithmParameterException if the
+ * specified parameters are inappropriate for this CertPathBuilder
+ */
+ public abstract CertPathBuilderResult engineBuild( CertPathParameters params )
+ throws CertPathBuilderException,
+ InvalidAlgorithmParameterException;
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathParameters.java
new file mode 100644
index 000000000..caff291a8
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathParameters.java
@@ -0,0 +1,18 @@
+package java.security.cert;
+
+/**
+ * A specification of certification path algorithm parameters. The purpose
+ * of this interface is to group (and provide type safety for) all CertPath
+ * parameter specifications. All <code>CertPath</code> parameter specifications must
+ * implement this interface.
+ **/
+public interface CertPathParameters extends Cloneable
+{
+ /**
+ * Makes a copy of this <code>CertPathParameters</code>. Changes to the
+ * copy will not affect the original and vice versa.
+ *
+ * @return a copy of this <code>CertPathParameters</code>
+ **/
+ public Object clone();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidator.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidator.java
new file mode 100644
index 000000000..aaddbf0e5
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidator.java
@@ -0,0 +1,250 @@
+package java.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.Security;
+
+/**
+ * A class for validating certification paths (also known as certificate
+ * chains).<br />
+ * <br />
+ * This class uses a provider-based architecture, as described in the Java
+ * Cryptography Architecture. To create a <code>CertPathValidator</code>,
+ * call one of the static <code>getInstance</code> methods, passing in the
+ * algorithm name of the <code>CertPathValidator</code> desired and
+ * optionally the name of the provider desired. <br />
+ * <br />
+ * Once a <code>CertPathValidator</code> object has been created, it can
+ * be used to validate certification paths by calling the {@link #validate
+ * validate} method and passing it the <code>CertPath</code> to be validated
+ * and an algorithm-specific set of parameters. If successful, the result is
+ * returned in an object that implements the
+ * <code>CertPathValidatorResult</code> interface.<br />
+ * <br />
+ * <b>Concurrent Access</b><br />
+ * <br />
+ * The static methods of this class are guaranteed to be thread-safe.
+ * Multiple threads may concurrently invoke the static methods defined in
+ * this class with no ill effects.<br />
+ * <br />
+ * However, this is not true for the non-static methods defined by this class.
+ * Unless otherwise documented by a specific provider, threads that need to
+ * access a single <code>CertPathValidator</code> instance concurrently should
+ * synchronize amongst themselves and provide the necessary locking. Multiple
+ * threads each manipulating a different <code>CertPathValidator</code>
+ * instance need not synchronize.<br />
+ * <br />
+ * Uses {@link CertUtil CertUtil} to actualiy load the SPI classes.
+ *
+ * @see CertPath
+ * @see CertUtil
+ **/
+public class CertPathValidator extends Object
+{
+ private CertPathValidatorSpi validatorSpi;
+ private Provider provider;
+ private String algorithm;
+
+ /**
+ * Creates a <code>CertPathValidator</code> object of the given algorithm,
+ * and encapsulates the given provider implementation (SPI object) in it.
+ *
+ * @param validatorSpi the provider implementation
+ * @param provider the provider
+ * @param algorithm the algorithm name
+ */
+ protected CertPathValidator( CertPathValidatorSpi validatorSpi,
+ Provider provider,
+ String algorithm)
+ {
+ this.validatorSpi = validatorSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns a <code>CertPathValidator</code> object that implements the
+ * specified algorithm.<br />
+ * <br />
+ * If the default provider package provides an implementation of the
+ * specified <code>CertPathValidator</code> algorithm, an instance of
+ * <code>CertPathValidator</code> containing that implementation is
+ * returned. If the requested algorithm is not available in the default
+ * package, other packages are searched.
+ *
+ * @param algorithm the name of the requested <code>CertPathValidator</code>
+ * algorithm
+ *
+ * @return a <code>CertPathValidator</code> object that implements the
+ * specified algorithm
+ *
+ * @exception NoSuchAlgorithmException if the requested algorithm
+ * is not available in the default provider package or any of the other
+ * provider packages that were searched
+ */
+ public static CertPathValidator getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ try {
+ CertUtil.Implementation imp =
+ CertUtil.getImplementation("CertPathValidator", algorithm, (String)null );
+ if (imp != null)
+ {
+ return new CertPathValidator((CertPathValidatorSpi)imp.getEngine(), imp.getProvider(), algorithm);
+ }
+ } catch (NoSuchProviderException ex ) {}
+ throw new NoSuchAlgorithmException("can't find algorithm " + algorithm);
+ }
+
+ /**
+ * Returns a <code>CertPathValidator</code> object that implements the
+ * specified algorithm, as supplied by the specified provider.
+ *
+ * @param algorithm the name of the requested <code>CertPathValidator</code>
+ * algorithm
+ * @param provider the name of the provider
+ *
+ * @return a <code>CertPathValidator</code> object that implements the
+ * specified algorithm, as supplied by the specified provider
+ *
+ * @exception NoSuchAlgorithmException if the requested algorithm
+ * is not available from the specified provider
+ * @exception NoSuchProviderException if the provider has not been
+ * configured
+ * @exception IllegalArgumentException if the <code>provider</code> is
+ * null
+ */
+ public static CertPathValidator getInstance(String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException,
+ NoSuchProviderException
+ {
+ if ( provider == null )
+ throw new IllegalArgumentException("provider must be non-null");
+
+ CertUtil.Implementation imp = CertUtil.getImplementation("CertPathValidator", algorithm, provider );
+ if (imp != null)
+ {
+ return new CertPathValidator((CertPathValidatorSpi)imp.getEngine(), imp.getProvider(), algorithm);
+ }
+ throw new NoSuchAlgorithmException("can't find algorithm " + algorithm);
+ }
+
+ /**
+ * Returns a <code>CertPathValidator</code> object that implements the
+ * specified algorithm, as supplied by the specified provider.
+ * Note: the <code>provider</code> doesn't have to be registered.
+ *
+ * @param algorithm the name of the requested
+ * <code>CertPathValidator</code> algorithm
+ * @param provider the provider
+ *
+ * @return a <code>CertPathValidator</code> object that implements the
+ * specified algorithm, as supplied by the specified provider
+ *
+ * @exception NoSuchAlgorithmException if the requested algorithm
+ * is not available from the specified provider
+ * @exception IllegalArgumentException if the <code>provider</code> is
+ * null
+ */
+ public static CertPathValidator getInstance(String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if ( provider == null )
+ throw new IllegalArgumentException("provider must be non-null");
+
+ CertUtil.Implementation imp = CertUtil.getImplementation("CertPathValidator", algorithm, provider );
+ if (imp != null)
+ {
+ return new CertPathValidator((CertPathValidatorSpi)imp.getEngine(), provider, algorithm);
+ }
+ throw new NoSuchAlgorithmException("can't find algorithm " + algorithm);
+ }
+
+ /**
+ * Returns the <code>Provider</code> of this
+ * <code>CertPathValidator</code>.
+ *
+ * @return the <code>Provider</code> of this <code>CertPathValidator</code>
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Returns the algorithm name of this <code>CertPathValidator</code>.
+ *
+ * @return the algorithm name of this <code>CertPathValidator</code>
+ */
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Validates the specified certification path using the specified
+ * algorithm parameter set.<br />
+ * <br />
+ * The <code>CertPath</code> specified must be of a type that is
+ * supported by the validation algorithm, otherwise an
+ * <code>InvalidAlgorithmParameterException</code> will be thrown. For
+ * example, a <code>CertPathValidator</code> that implements the PKIX
+ * algorithm validates <code>CertPath</code> objects of type X.509.
+ *
+ * @param certPath the <code>CertPath</code> to be validated
+ * @param params the algorithm parameters
+ *
+ * @return the result of the validation algorithm
+ *
+ * @exception CertPathValidatorException if the <code>CertPath</code>
+ * does not validate
+ * @exception InvalidAlgorithmParameterException if the specified
+ * parameters or the type of the specified <code>CertPath</code> are
+ * inappropriate for this <code>CertPathValidator</code>
+ */
+ public final CertPathValidatorResult validate( CertPath certPath,
+ CertPathParameters params)
+ throws CertPathValidatorException,
+ InvalidAlgorithmParameterException
+ {
+ return validatorSpi.engineValidate( certPath, params );
+ }
+
+
+ /**
+ * Returns the default <code>CertPathValidator</code> type as specified in
+ * the Java security properties file, or the string &quot;PKIX&quot;
+ * if no such property exists. The Java security properties file is
+ * located in the file named &lt;JAVA_HOME&gt;/lib/security/java.security,
+ * where &lt;JAVA_HOME&gt; refers to the directory where the SDK was
+ * installed.<br />
+ * <br />
+ * The default <code>CertPathValidator</code> type can be used by
+ * applications that do not want to use a hard-coded type when calling one
+ * of the <code>getInstance</code> methods, and want to provide a default
+ * type in case a user does not specify its own.<br />
+ * <br />
+ * The default <code>CertPathValidator</code> type can be changed by
+ * setting the value of the "certpathvalidator.type" security property
+ * (in the Java security properties file) to the desired type.
+ *
+ * @return the default <code>CertPathValidator</code> type as specified
+ * in the Java security properties file, or the string &quot;PKIX&quot;
+ * if no such property exists.
+ */
+ public static final String getDefaultType()
+ {
+ String defaulttype = null;
+ defaulttype = Security.getProperty("certpathvalidator.type");
+
+ if ( defaulttype == null || defaulttype.length() <= 0 )
+ return "PKIX";
+ else
+ return defaulttype;
+ }
+}
+
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorException.java
new file mode 100644
index 000000000..2088ab1a4
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorException.java
@@ -0,0 +1,248 @@
+package java.security.cert;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.security.GeneralSecurityException;
+
+/**
+ * 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 CertPathValidatorException extends GeneralSecurityException
+{
+ private Throwable cause;
+ private CertPath certPath;
+ private int index = -1;
+
+ /**
+ * Creates a <code>CertPathValidatorException</code> with
+ * no detail message.
+ */
+ public CertPathValidatorException()
+ {
+ super();
+ }
+
+ /**
+ * Creates a <code>CertPathValidatorException</code> with the given
+ * detail message. A detail message is a <code>String</code> that
+ * describes this particular exception.
+ *
+ * @param messag the detail message
+ */
+ public CertPathValidatorException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Creates a <code>CertPathValidatorException</code> with the specified
+ * detail message and cause.
+ *
+ * @param msg the detail message
+ * @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 CertPathValidatorException(String message, Throwable cause)
+ {
+ super(message);
+ this.cause = cause;
+ }
+
+ /**
+ * Creates a <code>CertPathValidatorException</code> with the specified
+ * detail message, cause, certification path, and index.
+ *
+ * @param msg the detail message (or <code>null</code> if none)
+ * @param cause the cause (or <code>null</code> if none)
+ * @param certPath the certification path that was in the process of
+ * being validated when the error was encountered
+ * @param index the index of the certificate in the certification path
+ * that caused the error (or -1 if not applicable). Note that
+ * the list of certificates in a <code>CertPath</code> is zero based.
+ *
+ * @exception IndexOutOfBoundsException if the index is out of range
+ * <code>(index < -1 || (certPath != null && index >=
+ * certPath.getCertificates().size())</code>
+ * @exception IllegalArgumentException if <code>certPath</code> is
+ * <code>null</code> and <code>index</code> is not -1
+ */
+ public CertPathValidatorException(String message, Throwable cause, CertPath certPath, int index)
+ {
+ super( message );
+
+ if ( certPath == null && index != -1 )
+ throw new IllegalArgumentException( "certPath = null and index != -1" );
+ if ( index < -1 || ( certPath != null && index >= certPath.getCertificates().size() ) )
+ throw new IndexOutOfBoundsException( " index < -1 or out of bound of certPath.getCertificates()" );
+
+ this.cause = cause;
+ this.certPath = certPath;
+ this.index = index;
+ }
+
+ /**
+ * 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 CertPathValidatorException(Throwable cause)
+ {
+ this.cause = cause;
+ }
+
+ /**
+ * Returns the detail message for this
+ * <code>CertPathValidatorException</code>.
+ *
+ * @return the detail message, or <code>null</code> if neither the message
+ * nor cause were specified
+ */
+ public String getMessage()
+ {
+ String message = super.getMessage();
+
+ if ( message == null && cause == null )
+ return null;
+
+ StringBuffer s = new StringBuffer();
+ if ( message != null )
+ {
+ s.append(message).append('\n');
+ }
+ if ( cause != null )
+ {
+ s.append("Cause:\n").append(cause.getMessage()).append('\n');
+ }
+ return s.toString();
+ }
+
+ /**
+ * 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 CertPath getCertPath()
+ {
+ 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 getIndex()
+ {
+ 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();
+ }
+
+ /**
+ * Prints a stack trace to <code>System.err</code>, including the backtrace
+ * of the cause, if any.
+ */
+ public void printStackTrace()
+ {
+ printStackTrace(System.err);
+ }
+
+ /**
+ * Prints a stack trace to a <code>PrintStream</code>, including the
+ * backtrace of the cause, if any.
+ *
+ * @param ps the <code>PrintStream</code> to use for output
+ */
+ public void printStackTrace(PrintStream ps)
+ {
+ super.printStackTrace(ps);
+ if ( getCause() != null )
+ {
+ getCause().printStackTrace(ps);
+ }
+ }
+
+ /**
+ * 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);
+ }
+ }
+}
+
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorResult.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorResult.java
new file mode 100644
index 000000000..ec09641d5
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorResult.java
@@ -0,0 +1,22 @@
+package java.security.cert;
+
+/**
+ * A specification of the result of a certification path validator algorithm.<br />
+ * <br />
+ * The purpose of this interface is to group (and provide type safety
+ * for) all certification path validator results. All results returned
+ * by the {@link CertPathValidator#validate CertPathValidator.validate}
+ * method must implement this interface.
+ *
+ * @see CertPathValidator
+ **/
+public interface CertPathValidatorResult extends Cloneable
+{
+ /**
+ * Makes a copy of this <code>CertPathValidatorResult</code>. Changes to the
+ * copy will not affect the original and vice versa.
+ *
+ * @return a copy of this <code>CertPathValidatorResult</code>
+ */
+ public Object clone();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorSpi.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorSpi.java
new file mode 100644
index 000000000..c70bc47fc
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorSpi.java
@@ -0,0 +1,59 @@
+package java.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+
+/**
+ *
+ * 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.
+ **/
+public abstract class CertPathValidatorSpi extends Object
+{
+ /**
+ * The default constructor.
+ */
+ public CertPathValidatorSpi() {}
+
+ /**
+ * Validates the specified certification path using the specified
+ * algorithm parameter set.<br />
+ * <br />
+ * The <code>CertPath</code> specified must be of a type that is
+ * supported by the validation algorithm, otherwise an
+ * <code>InvalidAlgorithmParameterException</code> will be thrown. For
+ * example, a <code>CertPathValidator</code> that implements the PKIX
+ * algorithm validates <code>CertPath</code> objects of type X.509.
+ *
+ * @param certPath the <code>CertPath</code> to be validated
+ * @param params the algorithm parameters
+ *
+ * @return the result of the validation algorithm
+ *
+ * @exception CertPathValidatorException if the <code>CertPath</code>
+ * does not validate
+ * @exception InvalidAlgorithmParameterException if the specified
+ * parameters or the type of the specified <code>CertPath</code> are
+ * inappropriate for this <code>CertPathValidator</code>
+ */
+ public abstract CertPathValidatorResult engineValidate(CertPath certPath, CertPathParameters params)
+ throws CertPathValidatorException,
+ InvalidAlgorithmParameterException;
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertSelector.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertSelector.java
new file mode 100644
index 000000000..31bf97448
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertSelector.java
@@ -0,0 +1,39 @@
+package java.security.cert;
+
+/**
+ * A selector that defines a set of criteria for selecting
+ * <code>Certificate</code>s. Classes that implement this interface
+ * are often used to specify which <code>Certificate</code>s should
+ * be retrieved from a <code>CertStore</code>.<br />
+ * <br />
+ * <b>Concurrent Access</b><br />
+ * <br />
+ * Unless otherwise specified, the methods defined in this interface 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 Certificate
+ * @see CertStore
+ * @see CertStore#getCertificates
+ */
+public interface CertSelector extends Cloneable
+{
+ /**
+ * Decides whether a <code>Certificate</code> should be selected.
+ *
+ * @param cert the <code>Certificate</code> to be checked
+ * @return <code>true</code> if the <code>Certificate</code>
+ * should be selected, <code>false</code> otherwise
+ */
+ public boolean match(Certificate cert);
+
+ /**
+ * Makes a copy of this <code>CertSelector</code>. Changes to the
+ * copy will not affect the original and vice versa.
+ *
+ * @return a copy of this <code>CertSelector</code>
+ */
+ public Object clone();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStore.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStore.java
new file mode 100644
index 000000000..0e2c6d2f7
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStore.java
@@ -0,0 +1,352 @@
+package java.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Collection;
+
+/**
+ * A class for retrieving <code>Certificate</code>s and <code>CRL</code>s
+ * from a repository.<br />
+ * <br />
+ * This class uses a provider-based architecture, as described in the
+ * Java Cryptography Architecture.
+ * To create a <code>CertStore</code>, call one of the static
+ * <code>getInstance</code> methods, passing in the type of
+ * <code>CertStore</code> desired, any applicable initialization parameters
+ * and optionally the name of the provider desired. <br />
+ * <br />
+ * Once the <code>CertStore</code> has been created, it can be used to
+ * retrieve <code>Certificate</code>s and <code>CRL</code>s by calling its
+ * {@link #getCertificates(CertSelector selector) getCertificates} and
+ * {@link #getCRLs(CRLSelector selector) getCRLs} methods.<br />
+ * <br />
+ * Unlike a {@link java.security.KeyStore KeyStore}, which provides access
+ * to a cache of private keys and trusted certificates, a
+ * <code>CertStore</code> is designed to provide access to a potentially
+ * vast repository of untrusted certificates and CRLs. For example, an LDAP
+ * implementation of <code>CertStore</code> provides access to certificates
+ * and CRLs stored in one or more directories using the LDAP protocol and the
+ * schema as defined in the RFC service attribute. See Appendix A in the
+ * Java Certification Path API Programmer's Guide for more information about
+ * standard <code>CertStore</code> types.<br />
+ * <br />
+ * <b>Concurrent Access</b><br />
+ * <br />
+ * All public methods of <code>CertStore</code> objects must be thread-safe.
+ * That is, multiple threads may concurrently invoke these methods on a
+ * single <code>CertStore</code> object (or more than one) with no
+ * ill effects. This allows a <code>CertPathBuilder</code> to search for a
+ * CRL while simultaneously searching for further certificates, for instance.<br />
+ * <br />
+ * The static methods of this class are also guaranteed to be thread-safe.
+ * Multiple threads may concurrently invoke the static methods defined in
+ * this class with no ill effects.<br />
+ * <br />
+ * Uses {@link CertUtil CertUtil} to actualiy load the SPI classes.
+ *
+ * @see CertUtil
+ **/
+public class CertStore extends Object
+{
+ private CertStoreSpi storeSpi;
+ private Provider provider;
+ private String type;
+ private CertStoreParameters params;
+
+ /**
+ * Creates a <code>CertStore</code> object of the given type, and
+ * encapsulates the given provider implementation (SPI object) in it.
+ *
+ * @param storeSpi the provider implementation
+ * @param provider the provider
+ * @param type the type
+ * @param params the initialization parameters (may be <code>null</code>)
+ */
+ protected CertStore( CertStoreSpi storeSpi,
+ Provider provider,
+ String type,
+ CertStoreParameters params )
+ {
+ this.storeSpi = storeSpi;
+ this.provider = provider;
+ this.type = type;
+ this.params = params;
+ }
+
+ /**
+ * Returns a <code>Collection</code> of <code>Certificate</code>s that
+ * match the specified selector. If no <code>Certificate</code>s
+ * match the selector, an empty <code>Collection</code> will be returned.<br />
+ * <br />
+ * For some <code>CertStore</code> types, the resulting
+ * <code>Collection</code> may not contain <b>all</b> of the
+ * <code>Certificate</code>s that match the selector. For instance,
+ * an LDAP <code>CertStore</code> may not search all entries in the
+ * directory. Instead, it may just search entries that are likely to
+ * contain the <code>Certificate</code>s it is looking for.<br />
+ * <br />
+ * Some <code>CertStore</code> implementations (especially LDAP
+ * <code>CertStore</code>s) may throw a <code>CertStoreException</code>
+ * unless a non-null <code>CertSelector</code> is provided that
+ * includes specific criteria that can be used to find the certificates.
+ * Issuer and/or subject names are especially useful criteria.
+ *
+ * @param selector A <code>CertSelector</code> used to select which
+ * <code>Certificate</code>s should be returned. Specify <code>null</code>
+ * to return all <code>Certificate</code>s (if supported).
+ *
+ * @return A <code>Collection</code> of <code>Certificate</code>s that
+ * match the specified selector (never <code>null</code>)
+ * @exception CertStoreException if an exception occurs
+ */
+ public final Collection getCertificates( CertSelector selector )
+ throws CertStoreException
+ {
+ return storeSpi.engineGetCertificates( selector );
+ }
+
+ /**
+ * Returns a <code>Collection</code> of <code>CRL</code>s that
+ * match the specified selector. If no <code>CRL</code>s
+ * match the selector, an empty <code>Collection</code> will be returned.<br />
+ * <br />
+ * For some <code>CertStore</code> types, the resulting
+ * <code>Collection</code> may not contain <b>all</b> of the
+ * <code>CRL</code>s that match the selector. For instance,
+ * an LDAP <code>CertStore</code> may not search all entries in the
+ * directory. Instead, it may just search entries that are likely to
+ * contain the <code>CRL</code>s it is looking for.<br />
+ * <br />
+ * Some <code>CertStore</code> implementations (especially LDAP
+ * <code>CertStore</code>s) may throw a <code>CertStoreException</code>
+ * unless a non-null <code>CRLSelector</code> is provided that
+ * includes specific criteria that can be used to find the CRLs.
+ * Issuer names and/or the certificate to be checked are especially useful.
+ *
+ * @param selector A <code>CRLSelector</code> used to select which
+ * <code>CRL</code>s should be returned. Specify <code>null</code>
+ * to return all <code>CRL</code>s (if supported).
+ *
+ * @return A <code>Collection</code> of <code>CRL</code>s that
+ * match the specified selector (never <code>null</code>)
+ *
+ * @exception CertStoreException if an exception occurs
+ */
+ public final Collection getCRLs( CRLSelector selector )
+ throws CertStoreException
+ {
+ return storeSpi.engineGetCRLs( selector );
+ }
+
+ /**
+ * Returns a <code>CertStore</code> object that implements the specified
+ * <code>CertStore</code> type and is initialized with the specified
+ * parameters.<br />
+ * <br />
+ * If the default provider package provides an implementation
+ * of the specified <code>CertStore</code> type, an instance of
+ * <code>CertStore</code> containing that implementation is returned.
+ * If the requested type is not available in the default package, other
+ * packages are searched.<br />
+ * <br />
+ * The <code>CertStore</code> that is returned is initialized with the
+ * specified <code>CertStoreParameters</code>. The type of parameters
+ * needed may vary between different types of <code>CertStore</code>s.
+ * Note that the specified <code>CertStoreParameters</code> object is
+ * cloned.
+ *
+ * @param type the name of the requested <code>CertStore</code> type
+ * @param params the initialization parameters (may be <code>null</code>)
+ *
+ * @return a <code>CertStore</code> object that implements the specified
+ * <code>CertStore</code> type
+ *
+ * @exception NoSuchAlgorithmException if the requested type is not
+ * available in the default provider package or any of the other provider
+ * packages that were searched
+ * @exception InvalidAlgorithmParameterException if the specified
+ * initialization parameters are inappropriate for this
+ * <code>CertStore</code>
+ */
+ public static CertStore getInstance( String type,
+ CertStoreParameters params)
+ throws InvalidAlgorithmParameterException,
+ NoSuchAlgorithmException
+ {
+ try {
+ CertUtil.Implementation imp =
+ CertUtil.getImplementation( "CertStore", type, (String)null,
+ new Class[] { CertStoreParameters.class },
+ new Object[] { params } );
+ if (imp != null)
+ {
+ return new CertStore((CertStoreSpi)imp.getEngine(), imp.getProvider(), type, params );
+ }
+ } catch ( NoSuchProviderException ex ) {}
+ throw new NoSuchAlgorithmException("can't find type " + type);
+ }
+
+ /**
+ * Returns a <code>CertStore</code> object that implements the specified
+ * <code>CertStore</code> type, as supplied by the specified provider
+ * and initialized with the specified parameters.<br />
+ * <br />
+ * The <code>CertStore</code> that is returned is initialized with the
+ * specified <code>CertStoreParameters</code>. The type of parameters
+ * needed may vary between different types of <code>CertStore</code>s.
+ * Note that the specified <code>CertStoreParameters</code> object is
+ * cloned.
+ *
+ * @param type the requested <code>CertStore</code> type
+ * @param params the initialization parameters (may be <code>null</code>)
+ * @param provider the name of the provider
+ *
+ * @return a <code>CertStore</code> object that implements the
+ * specified type, as supplied by the specified provider
+ *
+ * @exception NoSuchAlgorithmException if the requested type is not
+ * available from the specified provider
+ * @exception InvalidAlgorithmParameterException if the specified
+ * initialization parameters are inappropriate for this
+ * <code>CertStore</code>
+ * @exception NoSuchProviderException if the provider has not been configured
+ * @exception IllegalArgumentException if the <code>provider</code> is
+ * null
+ */
+ public static CertStore getInstance( String type,
+ CertStoreParameters params,
+ String provider)
+ throws InvalidAlgorithmParameterException,
+ NoSuchAlgorithmException,
+ NoSuchProviderException,
+ IllegalArgumentException
+ {
+ if ( provider == null )
+ throw new IllegalArgumentException( "provider must be non-null" );
+
+ CertUtil.Implementation imp =
+ CertUtil.getImplementation( "CertStore", type, provider,
+ new Class[] { CertStoreParameters.class },
+ new Object[] { params } );
+ if (imp != null)
+ {
+ return new CertStore((CertStoreSpi)imp.getEngine(), imp.getProvider(), type, params );
+ }
+ throw new NoSuchAlgorithmException("can't find type " + type);
+ }
+
+ /**
+ * Returns a <code>CertStore</code> object that implements the specified
+ * <code>CertStore</code> type, as supplied by the specified provider and
+ * initialized with the specified parameters.
+ * Note: the <code>provider</code> doesn't have to be registered.<br />
+ * <br />
+ * The <code>CertStore</code> that is returned is initialized with the
+ * specified <code>CertStoreParameters</code>. The type of parameters
+ * needed may vary between different types of <code>CertStore</code>s.
+ * Note that the specified <code>CertStoreParameters</code> object is
+ * cloned.
+ *
+ * @param type the requested <code>CertStore</code> type
+ * @param params the initialization parameters (may be <code>null</code>)
+ * @param provider the provider
+ *
+ * @return a <code>CertStore</code> object that implements the
+ * specified type, as supplied by the specified provider
+ *
+ * @exception NoSuchAlgorithmException if the requested type is not
+ * available from the specified provider
+ * @exception InvalidAlgorithmParameterException if the specified
+ * initialization parameters are inappropriate for this
+ * <code>CertStore</code>
+ * @exception IllegalArgumentException if the <code>provider</code> is
+ * null
+ */
+ public static CertStore getInstance( String type,
+ CertStoreParameters params,
+ Provider provider )
+ throws NoSuchAlgorithmException,
+ InvalidAlgorithmParameterException,
+ IllegalArgumentException
+ {
+ if ( provider == null )
+ throw new IllegalArgumentException( "provider must be non-null" );
+ CertUtil.Implementation imp =
+ CertUtil.getImplementation( "CertStore", type, provider,
+ new Class[] { CertStoreParameters.class },
+ new Object[] { params } );
+ if (imp != null)
+ {
+ return new CertStore((CertStoreSpi)imp.getEngine(), provider, type, params );
+ }
+ throw new NoSuchAlgorithmException("can't find type " + type);
+ }
+
+ /**
+ * Returns the parameters used to initialize this <code>CertStore</code>.
+ * Note that the <code>CertStoreParameters</code> object is cloned before
+ * it is returned.
+ *
+ * @return the parameters used to initialize this <code>CertStore</code>
+ * (may be <code>null</code>)
+ */
+ public final CertStoreParameters getCertStoreParameters()
+ {
+ return params;
+ }
+
+ /**
+ * Returns the type of this <code>CertStore</code>.
+ *
+ * @return the type of this <code>CertStore</code>
+ */
+ public final String getType()
+ {
+ return type;
+ }
+
+ /**
+ * Returns the provider of this <code>CertStore</code>.
+ *
+ * @return the provider of this <code>CertStore</code>
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Returns the default <code>CertStore</code> type as specified in the
+ * Java security properties file, or the string &quot;LDAP&quot; if no
+ * such property exists. The Java security properties file is located in
+ * the file named &lt;JAVA_HOME&gt;/lib/security/java.security, where
+ * &lt;JAVA_HOME&gt; refers to the directory where the SDK was installed.<br />
+ * <br />
+ * The default <code>CertStore</code> type can be used by applications
+ * that do not want to use a hard-coded type when calling one of the
+ * <code>getInstance</code> methods, and want to provide a default
+ * <code>CertStore</code> type in case a user does not specify its own.<br />
+ * <br />
+ * The default <code>CertStore</code> type can be changed by setting
+ * the value of the "certstore.type" security property (in the Java
+ * security properties file) to the desired type.
+ *
+ * @return the default <code>CertStore</code> type as specified in the
+ * Java security properties file, or the string &quot;LDAP&quot;
+ * if no such property exists.
+ */
+ public static final String getDefaultType()
+ {
+ String defaulttype = null;
+ defaulttype = Security.getProperty("certstore.type");
+
+ if ( defaulttype == null || defaulttype.length() <= 0 )
+ return "LDAP";
+ else
+ return defaulttype;
+ }
+}
+
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreException.java
new file mode 100644
index 000000000..a15bc3df6
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreException.java
@@ -0,0 +1,172 @@
+package java.security.cert;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.security.GeneralSecurityException;
+
+/**
+ * An exception indicating one of a variety of problems retrieving
+ * certificates and CRLs from a <code>CertStore</code>.<br />
+ * <br />
+ * A <code>CertStoreException</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 />
+ * <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 CertStore
+ **/
+public class CertStoreException extends GeneralSecurityException
+{
+ private Throwable cause;
+
+ /**
+ * Creates a <code>CertStoreException</code> with <code>null</code> as
+ * its detail message.
+ */
+ public CertStoreException()
+ {
+ super();
+ }
+
+ /**
+ * Creates a <code>CertStoreException</code> with the given detail
+ * message. A detail message is a <code>String</code> that describes this
+ * particular exception.
+ *
+ * @param messag the detail message
+ */
+ public CertStoreException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Creates a <code>CertStoreException</code> with the specified detail
+ * message and cause.
+ *
+ * @param messag the detail message
+ * @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 CertStoreException(String message, Throwable cause)
+ {
+ super(message);
+ this.cause = cause;
+ }
+
+ /**
+ * Creates a <code>CertStoreException</code> that wraps the specified
+ * throwable. This allows any exception to be converted into a
+ * <code>CertStoreException</code>, while retaining information about the
+ * cause, 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 CertStoreException(Throwable cause)
+ {
+ this.cause = cause;
+ }
+
+ /**
+ * Returns the detail message for this <code>CertStoreException</code>.
+ *
+ * @return the detail message, or <code>null</code> if neither the message
+ * nor cause were specified
+ */
+ public String getMessage()
+ {
+ String message = super.getMessage();
+
+ if ( message == null && cause == null )
+ return null;
+
+ StringBuffer s = new StringBuffer();
+ if ( message != null )
+ {
+ s.append(message).append('\n');
+ }
+ if ( cause != null )
+ {
+ s.append("Cause:\n").append(cause.getMessage());
+ }
+ return s.toString();
+ }
+
+ /**
+ * Returns the cause of this <code>CertStoreException</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>CertStoreException</code>
+ */
+ public String toString()
+ {
+ String message = getMessage();
+ if ( message == null )
+ return "";
+
+ return message;
+ }
+
+ /**
+ * Prints a stack trace to <code>System.err</code>, including the backtrace
+ * of the cause, if any.
+ */
+ public void printStackTrace() {
+ printStackTrace(System.err);
+ }
+
+ /**
+ * Prints a stack trace to a <code>PrintStream</code>, including the
+ * backtrace of the cause, if any.
+ *
+ * @param ps the <code>PrintStream</code> to use for output
+ */
+ public void printStackTrace(PrintStream ps) {
+ super.printStackTrace(ps);
+ if ( cause != null ) {
+ cause.printStackTrace(ps);
+ }
+ }
+
+ /**
+ * 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) {
+ if ( cause != null ) {
+ cause.printStackTrace(pw);
+ }
+ super.printStackTrace(pw);
+ if ( cause != null ) {
+ cause.printStackTrace(pw);
+ }
+ }
+}
+
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreParameters.java
new file mode 100644
index 000000000..58a70b372
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreParameters.java
@@ -0,0 +1,52 @@
+package java.security.cert;
+
+/**
+ * A specification of <code>CertStore</code> parameters.<br />
+ * <br />
+ * The purpose of this interface is to group (and provide type safety for)
+ * all <code>CertStore</code> parameter specifications. All
+ * <code>CertStore</code> parameter specifications must implement this
+ * interface. <br />
+ * <br />
+ * Typically, a <code>CertStoreParameters</code> object is passed as a parameter
+ * to one of the {@link CertStore#getInstance CertStore.getInstance} methods.
+ * The <code>getInstance</code> method returns a <code>CertStore</code> that
+ * is used for retrieving <code>Certificate</code>s and <code>CRL</code>s. The
+ * <code>CertStore</code> that is returned is initialized with the specified
+ * parameters. The type of parameters needed may vary between different types
+ * of <code>CertStore</code>s.
+ *
+ * @see CertStore#getInstance
+ **/
+public interface CertStoreParameters extends Cloneable
+{
+ /**
+ * Makes a copy of this <code>CertStoreParameters</code>.<br />
+ * <br />
+ * The precise meaning of "copy" may depend on the class of
+ * the <code>CertStoreParameters</code> object. A typical implementation
+ * performs a "deep copy" of this object, but this is not an absolute
+ * requirement. Some implementations may perform a "shallow copy" of some
+ * or all of the fields of this object.<br />
+ * <br />
+ * Note that the <code>CertStore.getInstance</code> methods make a copy
+ * of the specified <code>CertStoreParameters</code>. A deep copy
+ * implementation of <code>clone</code> is safer and more robust, as it
+ * prevents the caller from corrupting a shared <code>CertStore</code> by
+ * subsequently modifying the contents of its initialization parameters.
+ * However, a shallow copy implementation of <code>clone</code> is more
+ * appropriate for applications that need to hold a reference to a
+ * parameter contained in the <code>CertStoreParameters</code>. For example,
+ * a shallow copy clone allows an application to release the resources of
+ * a particular <code>CertStore</code> initialization parameter immediately,
+ * rather than waiting for the garbage collection mechanism. This should
+ * be done with the utmost care, since the <code>CertStore</code> may still
+ * be in use by other threads.<br />
+ * <br />
+ * Each subclass should state the precise behavior of this method so
+ * that users and developers know what to expect.
+ *
+ * @return a copy of this <code>CertStoreParameters</code>
+ */
+ public Object clone();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreSpi.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreSpi.java
new file mode 100644
index 000000000..b92cf4aa5
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreSpi.java
@@ -0,0 +1,104 @@
+package java.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.util.Collection;
+
+/**
+ * The <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@link CertStore CertStore} class. All <code>CertStore</code>
+ * implementations must include a class (the SPI class) that extends
+ * this class (<code>CertStoreSpi</code>), provides a constructor with
+ * a single argument of type <code>CertStoreParameters</code>, and implements
+ * all of its methods. In general, instances of this class should only be
+ * accessed through the <code>CertStore</code> class.
+ * For details, see the Java Cryptography Architecture.<br />
+ * <br />
+ * <b>Concurrent Access</b><br />
+ * <br />
+ * The public methods of all <code>CertStoreSpi</code> objects must be
+ * thread-safe. That is, multiple threads may concurrently invoke these
+ * methods on a single <code>CertStoreSpi</code> object (or more than one)
+ * with no ill effects. This allows a <code>CertPathBuilder</code> to search
+ * for a CRL while simultaneously searching for further certificates, for
+ * instance.<br />
+ * <br />
+ * Simple <code>CertStoreSpi</code> implementations will probably ensure
+ * thread safety by adding a <code>synchronized</code> keyword to their
+ * <code>engineGetCertificates</code> and <code>engineGetCRLs</code> methods.
+ * More sophisticated ones may allow truly concurrent access.
+ **/
+public abstract class CertStoreSpi
+ extends Object
+{
+
+ /**
+ * The sole constructor.
+ *
+ * @param params the initialization parameters (may be <code>null</code>)
+ * @exception InvalidAlgorithmParameterException if the initialization
+ * parameters are inappropriate for this <code>CertStoreSpi</code>
+ */
+ public CertStoreSpi( CertStoreParameters params )
+ throws InvalidAlgorithmParameterException {}
+
+ /**
+ * Returns a <code>Collection</code> of <code>Certificate</code>s that
+ * match the specified selector. If no <code>Certificate</code>s
+ * match the selector, an empty <code>Collection</code> will be returned.<br />
+ * <br />
+ * For some <code>CertStore</code> types, the resulting
+ * <code>Collection</code> may not contain <b>all</b> of the
+ * <code>Certificate</code>s that match the selector. For instance,
+ * an LDAP <code>CertStore</code> may not search all entries in the
+ * directory. Instead, it may just search entries that are likely to
+ * contain the <code>Certificate</code>s it is looking for.<br />
+ * <br />
+ * Some <code>CertStore</code> implementations (especially LDAP
+ * <code>CertStore</code>s) may throw a <code>CertStoreException</code>
+ * unless a non-null <code>CertSelector</code> is provided that includes
+ * specific criteria that can be used to find the certificates. Issuer
+ * and/or subject names are especially useful criteria.
+ *
+ * @param selector A <code>CertSelector</code> used to select which
+ * <code>Certificate</code>s should be returned. Specify <code>null</code>
+ * to return all <code>Certificate</code>s (if supported).
+ *
+ * @return A <code>Collection</code> of <code>Certificate</code>s that
+ * match the specified selector (never <code>null</code>)
+ *
+ * @exception CertStoreException if an exception occurs
+ */
+ public abstract Collection engineGetCertificates( CertSelector selector )
+ throws CertStoreException;
+
+ /**
+ * Returns a <code>Collection</code> of <code>CRL</code>s that
+ * match the specified selector. If no <code>CRL</code>s
+ * match the selector, an empty <code>Collection</code> will be returned.<br />
+ * <br />
+ * For some <code>CertStore</code> types, the resulting
+ * <code>Collection</code> may not contain <b>all</b> of the
+ * <code>CRL</code>s that match the selector. For instance,
+ * an LDAP <code>CertStore</code> may not search all entries in the
+ * directory. Instead, it may just search entries that are likely to
+ * contain the <code>CRL</code>s it is looking for. <br />
+ * <br />
+ * Some <code>CertStore</code> implementations (especially LDAP
+ * <code>CertStore</code>s) may throw a <code>CertStoreException</code>
+ * unless a non-null <code>CRLSelector</code> is provided that includes
+ * specific criteria that can be used to find the CRLs. Issuer names
+ * and/or the certificate to be checked are especially useful.
+ *
+ * @param selector A <code>CRLSelector</code> used to select which
+ * <code>CRL</code>s should be returned. Specify <code>null</code>
+ * to return all <code>CRL</code>s (if supported).
+ *
+ * @return A <code>Collection</code> of <code>CRL</code>s that
+ * match the specified selector (never <code>null</code>)
+ *
+ * @exception CertStoreException if an exception occurs
+ */
+ public abstract Collection engineGetCRLs( CRLSelector selector )
+ throws CertStoreException;
+}
+
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertUtil.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertUtil.java
new file mode 100644
index 000000000..216a8d8e4
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertUtil.java
@@ -0,0 +1,556 @@
+package java.security.cert;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.Security;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DEROutputStream;
+import org.spongycastle.asn1.OIDTokenizer;
+import org.spongycastle.asn1.x509.X509Name;
+import org.spongycastle.util.Strings;
+
+class CertUtil
+{
+ static class Implementation
+ {
+ Object engine;
+ Provider provider;
+
+ Implementation(
+ Object engine,
+ Provider provider)
+ {
+ this.engine = engine;
+ this.provider = provider;
+ }
+
+ Object getEngine()
+ {
+ return engine;
+ }
+
+ Provider getProvider()
+ {
+ return provider;
+ }
+ }
+
+ /**
+ * see if we can find an algorithm (or its alias and what it represents) in
+ * the property table for the given provider.
+ *
+ * @return null if no algorithm found, an Implementation if it is.
+ */
+ static Implementation getImplementation(
+ String baseName,
+ String algorithm,
+ Provider prov)
+ {
+ if (prov == null)
+ {
+ Provider[] provider = Security.getProviders();
+
+ //
+ // search every provider looking for the algorithm we want.
+ //
+ for (int i = 0; i != provider.length; i++)
+ {
+ Implementation imp = getImplementation(baseName, algorithm, provider[i]);
+ if (imp != null)
+ {
+ return imp;
+ }
+ }
+
+ return null;
+ }
+
+ String alias;
+
+ while ((alias = prov.getProperty("Alg.Alias." + baseName + "." + algorithm)) != null)
+ {
+ algorithm = alias;
+ }
+
+ String className = prov.getProperty(baseName + "." + algorithm);
+
+ if (className != null)
+ {
+ try
+ {
+ return new Implementation(Class.forName(className).newInstance(), prov);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new IllegalStateException(
+ "algorithm " + algorithm + " in provider " + prov.getName() + " but no class found!");
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException(
+ "algorithm " + algorithm + " in provider " + prov.getName() + " but class inaccessible: " + e.toString());
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * return an implementation for a given algorithm/provider.
+ * If the provider is null, we grab the first avalaible who has the required algorithm.
+ *
+ * @return null if no algorithm found, an Implementation if it is.
+ * @exception NoSuchProviderException if a provider is specified and not found.
+ */
+ static Implementation getImplementation(
+ String baseName,
+ String algorithm,
+ String provider)
+ throws NoSuchProviderException
+ {
+ if (provider == null)
+ {
+ Provider[] prov = Security.getProviders();
+
+ //
+ // search every provider looking for the algorithm we want.
+ //
+ for (int i = 0; i != prov.length; i++)
+ {
+ Implementation imp = getImplementation(baseName, algorithm, prov[i]);
+ if (imp != null)
+ {
+ return imp;
+ }
+ }
+ }
+ else
+ {
+ Provider prov = Security.getProvider(provider);
+
+ if (prov == null)
+ {
+ throw new NoSuchProviderException("Provider " + provider + " not found");
+ }
+
+ return getImplementation(baseName, algorithm, prov);
+ }
+
+ return null;
+ }
+
+ /**
+ * see if we can find an algorithm (or its alias and what it represents) in
+ * the property table for the given provider.
+ *
+ * @return null if no algorithm found, an Implementation if it is.
+ */
+ static Implementation getImplementation(String baseName, String algorithm,
+ Provider prov, Class[] ctorparamtype, Object[] ctorparam)
+ throws InvalidAlgorithmParameterException
+ {
+ String alias;
+
+ while ((alias = prov.getProperty("Alg.Alias." + baseName + "."
+ + algorithm)) != null)
+ {
+ algorithm = alias;
+ }
+
+ String className = prov.getProperty(baseName + "." + algorithm);
+
+ if (className != null)
+ {
+ try
+ {
+ return new Implementation(Class.forName(className)
+ .getConstructor(ctorparamtype).newInstance(ctorparam),
+ prov);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new IllegalStateException("algorithm " + algorithm
+ + " in provider " + prov.getName()
+ + " but no class found!");
+ }
+ catch (Exception e)
+ {
+ if (e instanceof InvalidAlgorithmParameterException)
+ {
+ throw (InvalidAlgorithmParameterException)e;
+ }
+
+ throw new IllegalStateException("algorithm " + algorithm
+ + " in provider " + prov.getName()
+ + " but class inaccessible!");
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * return an implementation for a given algorithm/provider. If the provider
+ * is null, we grab the first avalaible who has the required algorithm.
+ *
+ * @return null if no algorithm found, an Implementation if it is.
+ *
+ * @exception NoSuchProviderException
+ * if a provider is specified and not found.
+ */
+ static Implementation getImplementation(String baseName, String algorithm,
+ String provider, Class[] ctorparamtype, Object[] ctorparam)
+ throws NoSuchProviderException, InvalidAlgorithmParameterException
+ {
+ if (provider == null)
+ {
+ Provider[] prov = Security.getProviders();
+
+ //
+ // search every provider looking for the algorithm we want.
+ //
+ for (int i = 0; i != prov.length; i++)
+ {
+ Implementation imp = getImplementation(baseName, algorithm,
+ prov[i], ctorparamtype, ctorparam);
+ if (imp != null)
+ {
+ return imp;
+ }
+ }
+ }
+ else
+ {
+ Provider prov = Security.getProvider(provider);
+
+ if (prov == null)
+ {
+ throw new NoSuchProviderException("Provider " + provider
+ + " not found");
+ }
+
+ return getImplementation(baseName, algorithm, prov, ctorparamtype,
+ ctorparam);
+ }
+
+ return null;
+ }
+
+ static byte[] parseGeneralName(int type, String data) throws IOException
+ {
+ byte[] encoded = null;
+
+ switch (type)
+ {
+ case 0:
+ throw new IOException(
+ "unable to parse OtherName String representation");
+ case 1:
+ encoded = parseRfc822(data.trim());
+ break;
+ case 2:
+ encoded = parseDNSName(data.trim());
+ break;
+ case 3:
+ throw new IOException(
+ "unable to parse ORAddress String representation");
+ case 4:
+ encoded = parseX509Name(data.trim());
+ break;
+ case 5:
+ throw new IOException(
+ "unable to parse EDIPartyName String representation");
+ case 6:
+ encoded = parseURI(data.trim());
+ break;
+ case 7:
+ encoded = parseIP(data.trim());
+ break;
+ case 8:
+ encoded = parseOID(data.trim());
+ break;
+ default:
+ throw new IOException(
+ "unable to parse unkown type String representation");
+ }
+ return encoded;
+ }
+
+ /**
+ * Check the format of an OID.<br />
+ * Throw an IOException if the first component is not 0, 1 or 2 or the
+ * second component is greater than 39.<br />
+ * <br />
+ * User {@link org.spongycastle.asn1.OIDTokenizer OIDTokenizer}
+ *
+ * @param the
+ * OID to be checked.
+ *
+ * @exception IOException
+ * if the first component is not 0, 1 or 2 or the second
+ * component is greater than 39.
+ */
+ static byte[] parseOID(String oid) throws IOException
+ {
+ OIDTokenizer tokenizer = new OIDTokenizer(oid);
+ String token;
+ if (!tokenizer.hasMoreTokens())
+ {
+ throw new IOException("OID contains no tokens");
+ }
+ token = tokenizer.nextToken();
+ if (token == null)
+ {
+ throw new IOException("OID contains no tokens");
+ }
+ try
+ {
+ int test = (Integer.valueOf(token)).intValue();
+ if (test < 0 || test > 2)
+ {
+ throw new IOException("first token is not >= 0 and <=2");
+ }
+ if (!tokenizer.hasMoreTokens())
+ {
+ throw new IOException("OID contains only one token");
+ }
+ token = tokenizer.nextToken();
+ if (token == null)
+ {
+ throw new IOException("OID contains only one token");
+ }
+ test = (Integer.valueOf(token)).intValue();
+ if (test < 0 || test > 39)
+ {
+ throw new IOException("secon token is not >= 0 and <=39");
+ }
+ }
+ catch (NumberFormatException ex)
+ {
+ throw new IOException("token: " + token + ": " + ex.toString());
+ }
+ ASN1Object derData = new ASN1ObjectIdentifier(oid);
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ DEROutputStream derOutStream = new DEROutputStream(outStream);
+ derOutStream.writeObject(derData);
+ derOutStream.close();
+ return outStream.toByteArray();
+ }
+
+ /**
+ * Parse the given IPv4 or IPv6 into DER encoded byte array representation.
+ *
+ * @param the
+ * IP in well known String format
+ *
+ * @return the IP as byte array
+ *
+ * @exception IOException
+ * if the String could not be parsed
+ */
+ private static byte[] parseIP(String data) throws IOException
+ {
+ byte[] encoded = parseIPv4(data);
+
+ if (encoded == null)
+ {
+ encoded = parseIPv6(data);
+ }
+
+ if (encoded == null)
+ {
+ throw new IOException(
+ "unable to parse IP to DER encoded byte array");
+ }
+
+ return encoded;
+ }
+
+ /**
+ * Parse the given IPv4 into DER encoded byte array representation.
+ *
+ * @param the
+ * IP in well known String format
+ *
+ * @return the IP as byte array or <code>null</code> if not parseable
+ */
+ private static byte[] parseIPv4(String data)
+ {
+ if (data.length() == 0)
+ {
+ return null;
+ }
+
+ int octet;
+ int octets = 0;
+ byte[] dst = new byte[4];
+
+ int pos = 0;
+ int start = 0;
+ while (start < data.length()
+ && (pos = data.indexOf('.', start)) > start && pos - start > 3)
+ {
+ try
+ {
+ octet = (Integer.valueOf(data.substring(start, pos - start)))
+ .intValue();
+ }
+ catch (NumberFormatException ex)
+ {
+ return null;
+ }
+ if (octet < 0 || octet > 255)
+ {
+ return null;
+ }
+ dst[octets++] = (byte)(octet & 0xff);
+
+ start = pos + 1;
+ }
+
+ if (octets < 4)
+ {
+ return null;
+ }
+
+ return dst;
+ }
+
+ /**
+ * Parse the given IPv6 into DER encoded byte array representation.<br />
+ * <br />
+ * <b>TODO: implement this</b>
+ *
+ * @param the
+ * IP in well known String format
+ *
+ * @return the IP as byte array or <code>null</code> if not parseable
+ */
+ private static byte[] parseIPv6(String data)
+ {
+ return null;
+ }
+
+ /**
+ * Parse the given URI into DER encoded byte array representation.
+ *
+ * @param the
+ * URI in well known String format
+ *
+ * @return the URI as byte array
+ *
+ * @exception IOException
+ * if the String could not be parsed
+ */
+ private static byte[] parseURI(String data) throws IOException
+ {
+ // TODO do parsing test
+ ASN1Object derData = new DERIA5String(data);
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ DEROutputStream derOutStream = new DEROutputStream(outStream);
+ derOutStream.writeObject(derData);
+ derOutStream.close();
+ return outStream.toByteArray();
+ }
+
+ /**
+ * Parse the given rfc822 addr-spec into DER encoded byte array
+ * representation.
+ *
+ * @param the
+ * rfc822 addr-spec in well known String format
+ *
+ * @return the rfc822 addr-spec as byte array
+ *
+ * @exception IOException
+ * if the String could not be parsed
+ */
+ private static byte[] parseRfc822(String data) throws IOException
+ {
+ int tmpInt = data.indexOf('@');
+ if (tmpInt < 0 || tmpInt >= data.length() - 1)
+ {
+ throw new IOException("wrong format of rfc822Name:" + data);
+ }
+ // TODO more test for illegal charateers
+ ASN1Object derData = new DERIA5String(data);
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ DEROutputStream derOutStream = new DEROutputStream(outStream);
+ derOutStream.writeObject(derData);
+ derOutStream.close();
+ return outStream.toByteArray();
+ }
+
+ /**
+ * Parse the given DNS name into DER encoded byte array representation. The
+ * String must be in den preffered name syntax as defined in RFC 1034.
+ *
+ * @param the
+ * DNS name in well known String format
+ *
+ * @return the DNS name as byte array
+ *
+ * @exception IOException
+ * if the String could not be parsed
+ */
+ private static byte[] parseDNSName(String data) throws IOException
+ {
+ // TODO more test for illegal charateers
+ ASN1Object derData = new DERIA5String(data);
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ DEROutputStream derOutStream = new DEROutputStream(outStream);
+ derOutStream.writeObject(derData);
+ derOutStream.close();
+ return outStream.toByteArray();
+ }
+
+ /**
+ * Parse the given X.509 name into DER encoded byte array representation.
+ *
+ * @param the
+ * X.509 name in well known String format
+ *
+ * @return the X.509 name as byte array
+ *
+ * @exception IOException
+ * if the String could not be parsed
+ */
+ private static byte[] parseX509Name(String data) throws IOException
+ {
+ // TODO more test for illegal charateers
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ DEROutputStream derOutStream = new DEROutputStream(outStream);
+ derOutStream.writeObject(new X509Name(trimX509Name(data)));
+ derOutStream.close();
+ return outStream.toByteArray();
+ }
+
+ /**
+ * Returns the given name converted to upper case and all multi spaces squezed
+ * to one space.
+ **/
+ static String trimX509Name(String name)
+ {
+ String data = Strings.toUpperCase(name.trim());
+ int pos;
+ while ((pos = data.indexOf(" ")) >= 0)
+ {
+ data = data.substring(0, pos) + data.substring(pos + 1);
+ }
+ while ((pos = data.indexOf(" =")) >= 0)
+ {
+ data = data.substring(0, pos) + data.substring(pos + 1);
+ }
+ while ((pos = data.indexOf("= ")) >= 0)
+ {
+ data = data.substring(0, pos + 1) + data.substring(pos + 2);
+ }
+ return data;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/Certificate.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/Certificate.java
new file mode 100644
index 000000000..201e209a3
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/Certificate.java
@@ -0,0 +1,80 @@
+
+package java.security.cert;
+
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PublicKey;
+import java.security.SignatureException;
+
+public abstract class Certificate extends Object
+{
+ private String type;
+
+ protected Certificate(String type)
+ {
+ this.type = type;
+ }
+
+ public boolean equals(Object other)
+ {
+ if ( !(other instanceof Certificate) )
+ return false;
+
+ if ( other == this )
+ return true;
+
+ try
+ {
+ byte[] enc1 = getEncoded();
+ byte[] enc2 = ((Certificate)other).getEncoded();
+
+ return MessageDigest.isEqual(enc1, enc2);
+ }
+ catch (CertificateEncodingException e)
+ {
+ return false;
+ }
+ }
+
+ public final String getType()
+ {
+ return type;
+ }
+
+ // XXX
+ public int hashCode()
+ {
+ try
+ {
+ byte[] enc1 = getEncoded();
+ int hc = 0;
+ for (int i = 0; i < enc1.length; i++)
+ {
+ hc += enc1[i];
+ }
+
+ return hc;
+ }
+ catch (CertificateEncodingException e)
+ {
+ return 0;
+ }
+ }
+
+ public abstract byte[] getEncoded()
+ throws CertificateEncodingException;
+
+ public abstract PublicKey getPublicKey();
+
+ public abstract String toString();
+
+ public abstract void verify(PublicKey key)
+ throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException, SignatureException;
+
+ public abstract void verify(PublicKey key, String sigProvider)
+ throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException, SignatureException;
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateEncodingException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateEncodingException.java
new file mode 100644
index 000000000..47545a5c0
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateEncodingException.java
@@ -0,0 +1,14 @@
+
+package java.security.cert;
+
+public class CertificateEncodingException extends CertificateException
+{
+ public CertificateEncodingException()
+ {
+ }
+
+ public CertificateEncodingException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateException.java
new file mode 100644
index 000000000..644c6249f
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateException.java
@@ -0,0 +1,16 @@
+
+package java.security.cert;
+
+import java.security.GeneralSecurityException;
+
+public class CertificateException extends GeneralSecurityException
+{
+ public CertificateException()
+ {
+ }
+
+ public CertificateException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateExpiredException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateExpiredException.java
new file mode 100644
index 000000000..1a9062aa2
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateExpiredException.java
@@ -0,0 +1,14 @@
+
+package java.security.cert;
+
+public class CertificateExpiredException extends CertificateException
+{
+ public CertificateExpiredException()
+ {
+ }
+
+ public CertificateExpiredException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactory.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactory.java
new file mode 100644
index 000000000..e86cd3a03
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactory.java
@@ -0,0 +1,183 @@
+
+package java.security.cert;
+
+import java.io.InputStream;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Uses {@link CertUtil CertUtil} to actualiy load the SPI classes.
+ *
+ * @see CertUtil
+ **/
+public class CertificateFactory
+{
+ private CertificateFactorySpi certFacSpi;
+ private Provider provider;
+ private String type;
+
+ protected CertificateFactory(
+ CertificateFactorySpi certFacSpi,
+ Provider provider,
+ String type)
+ {
+ this.certFacSpi = certFacSpi;
+ this.provider = provider;
+ this.type = type;
+ }
+
+ public final CRL generateCRL(InputStream inStream)
+ throws CRLException
+ {
+ return certFacSpi.engineGenerateCRL(inStream);
+ }
+
+ public final Collection generateCRLs(InputStream inStream)
+ throws CRLException
+ {
+ return certFacSpi.engineGenerateCRLs(inStream);
+ }
+
+ public final Certificate generateCertificate(InputStream inStream)
+ throws CertificateException
+ {
+ return certFacSpi.engineGenerateCertificate(inStream);
+ }
+
+ public final /*Sk13 Vector*/ Collection generateCertificates(InputStream inStream)
+ throws CertificateException
+ {
+ return certFacSpi.engineGenerateCertificates(inStream);
+ }
+
+ /**
+ * Returns an iteration of the <code>CertPath</code> encodings supported
+ * by this certificate factory, with the default encoding first. See
+ * Appendix A in the
+ * Java Certification Path API Programmer's Guide for information about
+ * standard encoding names and their formats.<br />
+ * <br />
+ * Attempts to modify the returned <code>Iterator</code> via its
+ * <code>remove</code> method result in an
+ * <code>UnsupportedOperationException</code>.
+ *
+ * @return an <code>Iterator</code> over the names of the supported
+ * <code>CertPath</code> encodings (as <code>String</code>s)
+ */
+ public final Iterator getCertPathEncodings()
+ {
+ return certFacSpi.engineGetCertPathEncodings();
+ }
+
+ /**
+ * Generates a <code>CertPath</code> object and initializes it with
+ * the data read from the <code>InputStream</code> inStream. The data
+ * is assumed to be in the default encoding. The name of the default
+ * encoding is the first element of the <code>Iterator</code> returned by
+ * the {@link #getCertPathEncodings getCertPathEncodings} method.
+ *
+ * @param inStream an <code>InputStream</code> containing the data
+ *
+ * @return a <code>CertPath</code> initialized with the data from the
+ * <code>InputStream</code>
+ *
+ * @exception CertificateException if an exception occurs while decoding
+ */
+ public final CertPath generateCertPath(InputStream inStream)
+ throws CertificateException
+ {
+ return certFacSpi.engineGenerateCertPath(inStream);
+ }
+
+ /**
+ * Generates a <code>CertPath</code> object and initializes it with
+ * the data read from the <code>InputStream</code> inStream. The data
+ * is assumed to be in the specified encoding. See Appendix A in the
+ * <a href="../../../../guide/security/certpath/CertPathProgGuide.html#AppA">
+ * Java Certification Path API Programmer's Guide</a>
+ * for information about standard encoding names and their formats.
+ *
+ * @param inStream an <code>InputStream</code> containing the data
+ * @param encoding the encoding used for the data
+ *
+ * @return a <code>CertPath</code> initialized with the data from the
+ * <code>InputStream</code>
+ *
+ * @exception CertificateException if an exception occurs while decoding or
+ * the encoding requested is not supported
+ */
+ public final CertPath generateCertPath(InputStream inStream, String encoding)
+ throws CertificateException
+ {
+ return certFacSpi.engineGenerateCertPath(inStream, encoding);
+ }
+
+ /**
+ * Generates a <code>CertPath</code> object and initializes it with
+ * a <code>List</code> of <code>Certificate</code>s.<br />
+ * <br />
+ * The certificates supplied must be of a type supported by the
+ * <code>CertificateFactory</code>. They will be copied out of the supplied
+ * <code>List</code> object.
+ *
+ * @param certificates a <code>List</code> of <code>Certificate</code>s
+ *
+ * @return a <code>CertPath</code> initialized with the supplied list of
+ * certificates
+ *
+ * @exception CertificateException if an exception occurs
+ */
+ public final CertPath generateCertPath(List certificates)
+ throws CertificateException
+ {
+ return certFacSpi.engineGenerateCertPath( certificates );
+ }
+
+ public static final CertificateFactory getInstance(String type)
+ throws CertificateException
+ {
+ try
+ {
+ CertUtil.Implementation imp = CertUtil.getImplementation("CertificateFactory", type, (String)null);
+
+ if (imp != null)
+ {
+ return new CertificateFactory((CertificateFactorySpi)imp.getEngine(), imp.getProvider(), type);
+ }
+
+ throw new CertificateException("can't find type " + type);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CertificateException(type + " not found");
+ }
+ }
+
+ public static final CertificateFactory getInstance(
+ String type,
+ String provider)
+ throws CertificateException, NoSuchProviderException
+ {
+ CertUtil.Implementation imp = CertUtil.getImplementation("CertificateFactory", type, provider);
+
+ if (imp != null)
+ {
+ return new CertificateFactory((CertificateFactorySpi)imp.getEngine(), imp.getProvider(), type);
+ }
+
+ throw new CertificateException("can't find type " + type);
+ }
+
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ public final String getType()
+ {
+ return type;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactorySpi.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactorySpi.java
new file mode 100644
index 000000000..8cc06fc2e
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactorySpi.java
@@ -0,0 +1,111 @@
+
+package java.security.cert;
+
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+public abstract class CertificateFactorySpi
+{
+ public CertificateFactorySpi()
+ {
+ }
+
+ public abstract CRL engineGenerateCRL(InputStream inStream)
+ throws CRLException;
+
+ public abstract Collection engineGenerateCRLs(InputStream inStream)
+ throws CRLException;
+
+ public abstract Certificate engineGenerateCertificate(InputStream inStream)
+ throws CertificateException;
+
+ public abstract /*SK13 Vector*/ Collection engineGenerateCertificates(InputStream inStream)
+ throws CertificateException;
+
+ /**
+ * Returns an iteration of the <code>CertPath</code> encodings supported
+ * by this certificate factory, with the default encoding first. See
+ * Appendix A in the
+ * Java Certification Path API Programmer's Guide
+ * for information about standard encoding names.<br />
+ * <br />
+ * Attempts to modify the returned <code>Iterator</code> via its
+ * <code>remove</code> method result in an
+ * <code>UnsupportedOperationException</code>.<br />
+ * <br />
+ * This method was added to version 1.4 of the Java 2 Platform
+ * Standard Edition. In order to maintain backwards compatibility with
+ * existing service providers, this method cannot be <code>abstract</code>
+ * and by default throws an <code>UnsupportedOperationException</code>.
+ *
+ * @return an <code>Iterator</code> over the names of the supported
+ * <code>CertPath</code> encodings (as <code>String</code>s)
+ *
+ * @exception UnsupportedOperationException if the method is not supported
+ */
+ public abstract Iterator engineGetCertPathEncodings();
+
+ /**
+ * Generates a <code>CertPath</code> object and initializes it with
+ * the data read from the <code>InputStream</code> inStream. The data
+ * is assumed to be in the default encoding.
+ *
+ * @param inStream an <code>InputStream</code> containing the data
+ *
+ * @return a <code>CertPath</code> initialized with the data from the
+ * <code>InputStream</code>
+ *
+ * @exception CertificateException if an exception occurs while decoding
+ */
+ public abstract CertPath engineGenerateCertPath(InputStream inStream)
+ throws CertificateException;
+
+ /**
+ * Generates a <code>CertPath</code> object and initializes it with
+ * the data read from the <code>InputStream</code> inStream. The data
+ * is assumed to be in the specified encoding.<br />
+ * <br />
+ * This method was added to version 1.4 of the Java 2 Platform
+ * Standard Edition. In order to maintain backwards compatibility with
+ * existing service providers, this method cannot be <code>abstract</code>
+ * and by default throws an <code>UnsupportedOperationException</code>.
+ *
+ * @param inStream an <code>InputStream</code> containing the data
+ * @param encoding the encoding used for the data
+ *
+ * @return a <code>CertPath</code> initialized with the data from the
+ * <code>InputStream</code>
+ *
+ * @exception CertificateException if an exception occurs while decoding or
+ * the encoding requested is not supported
+ * @exception UnsupportedOperationException if the method is not supported
+ */
+ public abstract CertPath engineGenerateCertPath(InputStream inStream, String encoding)
+ throws CertificateException;
+
+ /**
+ * Generates a <code>CertPath</code> object and initializes it with
+ * a <code>List</code> of <code>Certificate</code>s.<br />
+ * <br />
+ * The certificates supplied must be of a type supported by the
+ * <code>CertificateFactory</code>. They will be copied out of the supplied
+ * <code>List</code> object.<br />
+ * <br />
+ * This method was added to version 1.4 of the Java 2 Platform
+ * Standard Edition. In order to maintain backwards compatibility with
+ * existing service providers, this method cannot be <code>abstract</code>
+ * and by default throws an <code>UnsupportedOperationException</code>.
+ *
+ * @param certificates a <code>List</code> of <code>Certificate</code>s
+ *
+ * @return a <code>CertPath</code> initialized with the supplied list of
+ * certificates
+ *
+ * @exception CertificateException if an exception occurs
+ * @exception UnsupportedOperationException if the method is not supported
+ */
+ public abstract CertPath engineGenerateCertPath(List certificates)
+ throws CertificateException;
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateNotYetValidException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateNotYetValidException.java
new file mode 100644
index 000000000..ec8d46a3e
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateNotYetValidException.java
@@ -0,0 +1,14 @@
+
+package java.security.cert;
+
+public class CertificateNotYetValidException extends CertificateException
+{
+ public CertificateNotYetValidException()
+ {
+ }
+
+ public CertificateNotYetValidException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateParsingException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateParsingException.java
new file mode 100644
index 000000000..a9f18aae0
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateParsingException.java
@@ -0,0 +1,14 @@
+
+package java.security.cert;
+
+public class CertificateParsingException extends CertificateException
+{
+ public CertificateParsingException()
+ {
+ }
+
+ public CertificateParsingException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CollectionCertStoreParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CollectionCertStoreParameters.java
new file mode 100644
index 000000000..7c31e7b51
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CollectionCertStoreParameters.java
@@ -0,0 +1,117 @@
+package java.security.cert;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Parameters used as input for the Collection <code>CertStore</code>
+ * algorithm.<br />
+ * <br />
+ * This class is used to provide necessary configuration parameters
+ * to implementations of the Collection <code>CertStore</code>
+ * algorithm. The only parameter included in this class is the
+ * <code>Collection</code> from which the <code>CertStore</code> will
+ * retrieve certificates and CRLs.<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 java.util.Collection
+ * @see CertStore
+ **/
+public class CollectionCertStoreParameters implements CertStoreParameters
+{
+ private Collection collection;
+
+ /**
+ * Creates an instance of <code>CollectionCertStoreParameters</code>
+ * which will allow certificates and CRLs to be retrieved from the
+ * specified <code>Collection</code>. If the specified
+ * <code>Collection</code> contains an object that is not a
+ * <code>Certificate</code> or <code>CRL</code>, that object will be
+ * ignored by the Collection <code>CertStore</code>.<br />
+ * <br />
+ * The <code>Collection</code> is <b>not</b> copied. Instead, a
+ * reference is used. This allows the caller to subsequently add or
+ * remove <code>Certificates</code> or <code>CRL</code>s from the
+ * <code>Collection</code>, thus changing the set of
+ * <code>Certificates</code> or <code>CRL</code>s available to the
+ * Collection <code>CertStore</code>. The Collection <code>CertStore</code>
+ * will not modify the contents of the <code>Collection</code>.<br />
+ * <br />
+ * If the <code>Collection</code> will be modified by one thread while
+ * another thread is calling a method of a Collection <code>CertStore</code>
+ * that has been initialized with this <code>Collection</code>, the
+ * <code>Collection</code> must have fail-fast iterators.
+ *
+ * @param collection a <code>Collection</code> of
+ * <code>Certificate</code>s and <code>CRL</code>s
+ *
+ * @exception NullPointerException if <code>collection</code> is
+ * <code>null</code>
+ */
+ public CollectionCertStoreParameters(Collection collection)
+ {
+ if ( collection == null )
+ throw new NullPointerException("collection must be non-null");
+ this.collection = collection;
+ }
+
+ /**
+ * Creates an instance of <code>CollectionCertStoreParameters</code> with
+ * the an empty Collection.
+ */
+ public CollectionCertStoreParameters()
+ {
+ collection = new ArrayList();
+ }
+
+ /**
+ * Returns the <code>Collection</code> from which <code>Certificate</code>s
+ * and <code>CRL</code>s are retrieved. This is <b>not</b> a copy of the
+ * <code>Collection</code>, it is a reference. This allows the caller to
+ * subsequently add or remove <code>Certificates</code> or
+ * <code>CRL</code>s from the <code>Collection</code>.
+ *
+ * @return the <code>Collection</code> (never null)
+ */
+ public Collection getCollection()
+ {
+ return collection;
+ }
+
+ /**
+ * Returns a copy of this object. Note that only a reference to the
+ * <code>Collection</code> is copied, and not the contents.
+ *
+ * @return the copy
+ */
+ public Object clone()
+ {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ /* Cannot happen */
+ throw new InternalError(e.toString());
+ }
+ }
+
+ /**
+ * Returns a formatted string describing the parameters.
+ *
+ * @return a formatted string describing the parameters
+ */
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer();
+ s.append("CollectionCertStoreParameters: [\n collections:\n");
+ s.append( getCollection());
+ s.append("\n]" );
+ return s.toString();
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/LDAPCertStoreParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/LDAPCertStoreParameters.java
new file mode 100644
index 000000000..2e4669975
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/LDAPCertStoreParameters.java
@@ -0,0 +1,130 @@
+package java.security.cert;
+
+/**
+ * Parameters used as input for the LDAP <code>CertStore</code> algorithm.<br />
+ * <br />
+ * This class is used to provide necessary configuration parameters (server
+ * name and port number) to implementations of the LDAP <code>CertStore</code>
+ * algorithm.<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 CertStore
+ **/
+public class LDAPCertStoreParameters implements CertStoreParameters
+{
+ private static final int LDAP_DEFAULT_PORT = 389;
+
+ /**
+ * the port number of the LDAP server
+ */
+ private String serverName;
+
+ /**
+ * the DNS name of the LDAP server
+ */
+ private int port;
+
+ /**
+ * Creates an instance of <code>LDAPCertStoreParameters</code> with the
+ * default parameter values (server name "localhost", port 389).
+ */
+ public LDAPCertStoreParameters()
+ {
+ this("localhost", LDAP_DEFAULT_PORT);
+ }
+
+ /**
+ * Creates an instance of <code>LDAPCertStoreParameters</code> with the
+ * specified server name and a default port of 389.
+ *
+ * @param serverName the DNS name of the LDAP server
+ *
+ * @exception NullPointerException if <code>serverName</code> is
+ * <code>null</code>
+ */
+ public LDAPCertStoreParameters(String serverName)
+ {
+ this(serverName, LDAP_DEFAULT_PORT);
+ }
+
+ /**
+ * Creates an instance of <code>LDAPCertStoreParameters</code> with the
+ * specified parameter values.
+ *
+ * @param serverName the DNS name of the LDAP server
+ * @param port the port number of the LDAP server
+ *
+ * @exception NullPointerException if <code>serverName</code> is
+ * <code>null</code>
+ */
+ public LDAPCertStoreParameters(String serverName, int port)
+ {
+ if (serverName == null)
+ throw new NullPointerException("serverName must be non-null");
+ this.serverName = serverName;
+ this.port = port;
+ }
+
+ /**
+ * Returns the DNS name of the LDAP server.
+ *
+ * @return the name (not <code>null</code>)
+ */
+ public String getServerName()
+ {
+ return serverName;
+ }
+
+ /**
+ * Returns the port number of the LDAP server.
+ *
+ * @return the port number
+ */
+ public int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Returns a copy of this object. Changes to the copy will not affect
+ * the original and vice versa.<br />
+ * <br />
+ * Note: this method currently performs a shallow copy of the object
+ * (simply calls <code>Object.clone()</code>). This may be changed in a
+ * future revision to perform a deep copy if new parameters are added
+ * that should not be shared.
+ *
+ * @return the copy
+ */
+ public Object clone()
+ {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ /* Cannot happen */
+ throw new InternalError(e.toString());
+ }
+ }
+
+ /**
+ * Returns a formatted string describing the parameters.
+ *
+ * @return a formatted string describing the parameters
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("LDAPCertStoreParameters: [\n");
+ sb.append(" serverName: ").append(serverName).append('\n');
+ sb.append(" port: ").append(port).append('\n');
+ sb.append(']');
+ return sb.toString();
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXBuilderParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXBuilderParameters.java
new file mode 100644
index 000000000..b4f7aceb9
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXBuilderParameters.java
@@ -0,0 +1,179 @@
+package java.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.util.Set;
+
+/**
+ * Parameters used as input for the PKIX <code>CertPathBuilder</code>
+ * algorithm.<br />
+ * <br />
+ * A PKIX <code>CertPathBuilder</code> uses these parameters to {@link
+ * CertPathBuilder#build build} a <code>CertPath</code> which has been
+ * validated according to the PKIX certification path validation algorithm.<br />
+ * <br />
+ * To instantiate a <code>PKIXBuilderParameters</code> object, an
+ * application must specify one or more <i>most-trusted CAs</i> as defined by
+ * the PKIX certification path validation algorithm. The most-trusted CA
+ * can be specified using one of two constructors. An application
+ * can call {@link #PKIXBuilderParameters(Set, CertSelector)
+ * PKIXBuilderParameters(Set, CertSelector)}, specifying a
+ * <code>Set</code> of <code>TrustAnchor</code> objects, each of which
+ * identifies a most-trusted CA. Alternatively, an application can call
+ * {@link #PKIXBuilderParameters(KeyStore, CertSelector)
+ * PKIXBuilderParameters(KeyStore, CertSelector)}, specifying a
+ * <code>KeyStore</code> instance containing trusted certificate entries, each
+ * of which will be considered as a most-trusted CA.<br />
+ * <br />
+ * In addition, an application must specify constraints on the target
+ * certificate that the <code>CertPathBuilder</code> will attempt
+ * to build a path to. The constraints are specified as a
+ * <code>CertSelector</code> object. These constraints should provide the
+ * <code>CertPathBuilder</code> with enough search criteria to find the target
+ * certificate. Minimal criteria for an <code>X509Certificate</code> usually
+ * include the subject name and/or one or more subject alternative names.
+ * If enough criteria is not specified, the <code>CertPathBuilder</code>
+ * may throw a <code>CertPathBuilderException</code>.<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 CertPathBuilder
+ **/
+public class PKIXBuilderParameters extends PKIXParameters
+{
+ private int maxPathLength = 5;
+
+ /**
+ * Creates an instance of <code>PKIXBuilderParameters</code> with
+ * the specified <code>Set</code> of most-trusted CAs.
+ * Each element of the set is a {@link TrustAnchor TrustAnchor}.<br />
+ * <br />
+ * Note that the <code>Set</code> is copied to protect against
+ * subsequent modifications.
+ *
+ * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s
+ * @param targetConstraints a <code>CertSelector</code> specifying the
+ * constraints on the target certificate
+ *
+ * @exception InvalidAlgorithmParameterException if <code>trustAnchors</code>
+ * is empty <code>(trustAnchors.isEmpty() == true)</code>
+ * @exception NullPointerException if <code>trustAnchors</code> is
+ * <code>null</code>
+ * @exception ClassCastException if any of the elements of
+ * <code>trustAnchors</code> are not of type
+ * <code>java.security.cert.TrustAnchor</code>
+ */
+ public PKIXBuilderParameters(
+ Set trustAnchors,
+ CertSelector targetConstraints)
+ throws InvalidAlgorithmParameterException
+ {
+ super( trustAnchors );
+ setTargetCertConstraints( targetConstraints );
+ }
+
+ /**
+ * Creates an instance of <code>PKIXBuilderParameters</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>X509Certificate</code>s
+ * 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
+ * @param targetConstraints a <code>CertSelector</code> specifying the
+ * constraints on the target certificate
+ *
+ * @exception KeyStoreException if <code>keystore</code> has not been
+ * initialized
+ * @exception InvalidAlgorithmParameterException if <code>keystore</code> does
+ * not contain at least one trusted certificate entry
+ * @exception NullPointerException if <code>keystore</code> is
+ * <code>null</code>
+ */
+ public PKIXBuilderParameters(KeyStore keystore,
+ CertSelector targetConstraints)
+ throws KeyStoreException,
+ InvalidAlgorithmParameterException
+ {
+ super( keystore );
+ setTargetCertConstraints( targetConstraints );
+ }
+
+ /**
+ * Sets the value of the maximum number of non-self-issued intermediate
+ * certificates that may exist in a certification path. A certificate
+ * is self-issued if the DNs that appear in the subject and issuer
+ * fields are identical and are not empty. Note that the last certificate
+ * in a certification path is not an intermediate certificate, and is not
+ * included in this limit. Usually the last certificate is an end entity
+ * certificate, but it can be a CA certificate. A PKIX
+ * <code>CertPathBuilder</code> instance must not build
+ * paths longer than the length specified.<br />
+ * <br />
+ * A value of 0 implies that the path can only contain
+ * a single certificate. A value of -1 implies that the
+ * path length is unconstrained (i.e. there is no maximum).
+ * The default maximum path length, if not specified, is 5.
+ * Setting a value less than -1 will cause an exception to be thrown.<br />
+ * <br />
+ * If any of the CA certificates contain the
+ * <code>BasicConstraintsExtension</code>, the value of the
+ * <code>pathLenConstraint</code> field of the extension overrides
+ * the maximum path length parameter whenever the result is a
+ * certification path of smaller length.
+ *
+ * @param maxPathLength the maximum number of non-self-issued intermediate
+ * certificates that may exist in a certification path
+ *
+ * @exception InvalidParameterException if <code>maxPathLength</code> is set
+ * to a value less than -1
+ *
+ * @see #getMaxPathLength
+ */
+ public void setMaxPathLength(int maxPathLength)
+ {
+ if ( maxPathLength < -1 )
+ throw new InvalidParameterException("the maximum path length parameter can not be less than -1");
+ this.maxPathLength = maxPathLength;
+ }
+
+ /**
+ * Returns the value of the maximum number of intermediate non-self-issued
+ * certificates that may exist in a certification path. See
+ * the {@link #setMaxPathLength} method for more details.
+ *
+ * @return the maximum number of non-self-issued intermediate certificates
+ * that may exist in a certification path, or -1 if there is no limit
+ *
+ * @see #setMaxPathLength
+ */
+ public int getMaxPathLength()
+ {
+ return maxPathLength;
+ }
+
+ /**
+ * Returns a formatted string describing the parameters.
+ *
+ * @return a formatted string describing the parameters
+ */
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer();
+ s.append( "PKIXBuilderParameters [\n" );
+ s.append( super.toString() );
+ s.append( " Maximum Path Length: " );
+ s.append( getMaxPathLength() );
+ s.append( "\n]\n" );
+ return s.toString();
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathBuilderResult.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathBuilderResult.java
new file mode 100644
index 000000000..2ac791826
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathBuilderResult.java
@@ -0,0 +1,93 @@
+package java.security.cert;
+
+import java.security.PublicKey;
+
+/**
+ * This class represents the successful result of the PKIX certification
+ * path builder algorithm. All certification paths that are built and
+ * returned using this algorithm are also validated according to the PKIX
+ * certification path validation algorithm.<br />
+ * <br />
+ * Instances of <code>PKIXCertPathBuilderResult</code> are returned by
+ * the <code>build</code> method of <code>CertPathBuilder</code>
+ * objects implementing the PKIX algorithm.<br />
+ * <br />
+ * All <code>PKIXCertPathBuilderResult</code> objects contain the
+ * certification path constructed by the build algorithm, the
+ * valid policy tree and subject public key resulting from the build
+ * algorithm, and a <code>TrustAnchor</code> describing the certification
+ * authority (CA) that served as a trust anchor for the certification path.<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 CertPathBuilderResult
+ *
+ **/
+public class PKIXCertPathBuilderResult extends PKIXCertPathValidatorResult
+ implements CertPathBuilderResult
+{
+ private CertPath certPath;
+
+ /**
+ * Creates an instance of <code>PKIXCertPathBuilderResult</code>
+ * containing the specified parameters.
+ *
+ * @param certPath the validated <code>CertPath</code>
+ * @param trustAnchor a <code>TrustAnchor</code> describing the CA that
+ * served as a trust anchor for the certification path
+ * @param policyTree the immutable valid policy tree, or <code>null</code>
+ * if there are no valid policies
+ * @param subjectPublicKey the public key of the subject
+ *
+ * @exception NullPointerException if the <code>certPath</code>,
+ * <code>trustAnchor</code> or <code>subjectPublicKey</code> parameters
+ * are <code>null</code>
+ */
+ public PKIXCertPathBuilderResult(CertPath certPath, TrustAnchor trustAnchor,
+ PolicyNode policyTree, PublicKey subjectPublicKey)
+ {
+ super(trustAnchor, policyTree, subjectPublicKey);
+ if ( certPath == null )
+ throw new NullPointerException( "certPath must be non-null" );
+ this.certPath = certPath;
+ }
+
+ /**
+ * Returns the built and validated certification path. The
+ * <code>CertPath</code> object does not include the trust anchor.
+ * Instead, use the {@link #getTrustAnchor() getTrustAnchor()} method to
+ * obtain the <code>TrustAnchor</code> that served as the trust anchor
+ * for the certification path.
+ *
+ * @return the built and validated <code>CertPath</code> (never
+ * <code>null</code>)
+ */
+ public CertPath getCertPath()
+ {
+ return certPath;
+ }
+
+ /**
+ * Return a printable representation of this
+ * <code>PKIXCertPathBuilderResult</code>.
+ *
+ * @return a <code>String</code> describing the contents of this
+ * <code>PKIXCertPathBuilderResult</code>
+ */
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer();
+ s.append( "PKIXCertPathBuilderResult: [\n" );
+ s.append( " Certification Path: ").append(getCertPath()).append('\n' );
+ s.append( " Trust Anchor: ").append(getTrustAnchor()).append('\n' );
+ s.append( " Policy Tree: ").append(getPolicyTree()).append('\n' );
+ s.append( " Subject Public Key: ").append(getPublicKey()).append("\n]");
+ return s.toString();
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathChecker.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathChecker.java
new file mode 100644
index 000000000..14dec8060
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathChecker.java
@@ -0,0 +1,155 @@
+package java.security.cert;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * An abstract class that performs one or more checks on an
+ * <code>X509Certificate</code>. <br />
+ * <br />
+ * A concrete implementation of the <code>PKIXCertPathChecker</code> class
+ * can be created to extend the PKIX certification path validation algorithm.
+ * For example, an implementation may check for and process a critical private
+ * extension of each certificate in a certification path.<br />
+ * <br />
+ * Instances of <code>PKIXCertPathChecker</code> are passed as parameters
+ * using the {@link PKIXParameters#setCertPathCheckers setCertPathCheckers}
+ * or {@link PKIXParameters#addCertPathChecker addCertPathChecker} methods
+ * of the <code>PKIXParameters</code> and <code>PKIXBuilderParameters</code>
+ * class. Each of the <code>PKIXCertPathChecker</code>s {@link #check check}
+ * methods will be called, in turn, for each certificate processed by a PKIX
+ * <code>CertPathValidator</code> or <code>CertPathBuilder</code>
+ * implementation.<br />
+ * <br />
+ * A <code>PKIXCertPathChecker</code> may be called multiple times on
+ * successive certificates in a certification path. Concrete subclasses
+ * are expected to maintain any internal state that may be necessary to
+ * check successive certificates. The {@link #init init} method is used
+ * to initialize the internal state of the checker so that the certificates
+ * of a new certification path may be checked. A stateful implementation
+ * <b>must</b> override the {@link #clone clone} method if necessary in
+ * order to allow a PKIX <code>CertPathBuilder</code> to efficiently
+ * backtrack and try other paths. In these situations, the
+ * <code>CertPathBuilder</code> is able to restore prior path validation
+ * states by restoring the cloned <code>PKIXCertPathChecker</code>s.<br />
+ * <br />
+ * The order in which the certificates are presented to the
+ * <code>PKIXCertPathChecker</code> may be either in the forward direction
+ * (from target to most-trusted CA) or in the reverse direction (from
+ * most-trusted CA to target). A <code>PKIXCertPathChecker</code> implementation
+ * <b>must</b> support reverse checking (the ability to perform its checks when
+ * it is presented with certificates in the reverse direction) and <b>may</b>
+ * support forward checking (the ability to perform its checks when it is
+ * presented with certificates in the forward direction). The
+ * {@link #isForwardCheckingSupported isForwardCheckingSupported} method
+ * indicates whether forward checking is supported.<br />
+ * <br />
+ * Additional input parameters required for executing the check may be
+ * specified through constructors of concrete implementations of this class.<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 PKIXParameters
+ * @see PKIXBuilderParameters
+ **/
+public abstract class PKIXCertPathChecker implements Cloneable
+{
+
+ /**
+ * Default constructor.
+ */
+ 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.
+ *
+ * @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(boolean 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 boolean 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>
+ * All X.509 certificate extensions that a <code>PKIXCertPathChecker</code>
+ * might possibly be able to process should be included in the set.
+ *
+ * @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 Set 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(
+ Certificate cert,
+ Collection 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 Object clone()
+ {
+ try {
+ return super.clone();
+ } catch ( CloneNotSupportedException ex ) {
+ /* Cannot happen */
+ throw new InternalError( ex.toString() );
+ }
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathValidatorResult.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathValidatorResult.java
new file mode 100644
index 000000000..8ffa25555
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathValidatorResult.java
@@ -0,0 +1,136 @@
+package java.security.cert;
+
+import java.security.PublicKey;
+
+/**
+ * This class represents the successful result of the PKIX certification
+ * path validation algorithm. <br />
+ * <br />
+ * Instances of <code>PKIXCertPathValidatorResult</code> are returned by the
+ * {@link CertPathValidator#validate validate} method of
+ * <code>CertPathValidator</code> objects implementing the PKIX algorithm.<br />
+ * <br />
+ * All <code>PKIXCertPathValidatorResult</code> objects contain the
+ * valid policy tree and subject public key resulting from the
+ * validation algorithm, as well as a <code>TrustAnchor</code> describing
+ * the certification authority (CA) that served as a trust anchor for the
+ * certification path.<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 CertPathValidatorResult
+ **/
+public class PKIXCertPathValidatorResult implements CertPathValidatorResult
+{
+ private TrustAnchor trustAnchor;
+ private PolicyNode policyTree;
+ private PublicKey subjectPublicKey;
+
+ /**
+ * Creates an instance of <code>PKIXCertPathValidatorResult</code>
+ * containing the specified parameters.
+ *
+ * @param trustAnchor a <code>TrustAnchor</code> describing the CA that
+ * served as a trust anchor for the certification path
+ * @param policyTree the immutable valid policy tree, or <code>null</code>
+ * if there are no valid policies
+ * @param subjectPublicKey the public key of the subject
+ *
+ * @exception NullPointerException if the <code>subjectPublicKey</code> or
+ * <code>trustAnchor</code> parameters are <code>null</code>
+ */
+ public PKIXCertPathValidatorResult(TrustAnchor trustAnchor,
+ PolicyNode policyTree,
+ PublicKey subjectPublicKey)
+ {
+ if ( subjectPublicKey == null )
+ throw new NullPointerException( "subjectPublicKey must be non-null" );
+ if ( trustAnchor == null )
+ throw new NullPointerException( "trustAnchor must be non-null" );
+
+ this.trustAnchor = trustAnchor;
+ this.policyTree = policyTree;
+ this.subjectPublicKey = subjectPublicKey;
+ }
+
+ /**
+ * Returns the <code>TrustAnchor</code> describing the CA that served
+ * as a trust anchor for the certification path.
+ *
+ * @return the <code>TrustAnchor</code> (never <code>null</code>)
+ */
+ public TrustAnchor getTrustAnchor()
+ {
+ return trustAnchor;
+ }
+
+ /**
+ * Returns the root node of the valid policy tree resulting from the
+ * PKIX certification path validation algorithm. The
+ * <code>PolicyNode</code> object that is returned and any objects that
+ * it returns through public methods are immutable.<br />
+ * <br />
+ * Most applications will not need to examine the valid policy tree.
+ * They can achieve their policy processing goals by setting the
+ * policy-related parameters in <code>PKIXParameters</code>. However, more
+ * sophisticated applications, especially those that process policy
+ * qualifiers, may need to traverse the valid policy tree using the
+ * {@link PolicyNode#getParent PolicyNode.getParent} and
+ * {@link PolicyNode#getChildren PolicyNode.getChildren} methods.
+ *
+ * @return the root node of the valid policy tree, or <code>null</code>
+ * if there are no valid policies
+ */
+ public PolicyNode getPolicyTree()
+ {
+ return policyTree;
+ }
+
+ /**
+ * Returns the public key of the subject (target) of the certification
+ * path, including any inherited public key parameters if applicable.
+ *
+ * @return the public key of the subject (never <code>null</code>)
+ */
+ public PublicKey getPublicKey()
+ {
+ return subjectPublicKey;
+ }
+
+ /**
+ * Returns a copy of this object.
+ *
+ * @return the copy
+ */
+ public Object clone()
+ {
+ try {
+ return super.clone();
+ } catch ( CloneNotSupportedException ex ) {
+ throw new InternalError( ex.toString() );
+ }
+ }
+
+ /**
+ * Return a printable representation of this
+ * <code>PKIXCertPathValidatorResult</code>.
+ *
+ * @return a <code>String</code> describing the contents of this
+ * <code>PKIXCertPathValidatorResult</code>
+ */
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer();
+ s.append( "PKIXCertPathValidatorResult: [ \n" );
+ s.append( " Trust Anchor: ").append(getTrustAnchor()).append('\n' );
+ s.append( " Policy Tree: ").append(getPolicyTree()).append('\n' );
+ s.append( " Subject Public Key: ").append(getPublicKey()).append("\n]" );
+ return s.toString();
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXParameters.java
new file mode 100644
index 000000000..3c55d7e49
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXParameters.java
@@ -0,0 +1,770 @@
+package java.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Parameters used as input for the PKIX CertPathValidator algorithm.<br />
+ * <br />
+ * A PKIX <code>CertPathValidator</code> uses these parameters to validate a
+ * <code>CertPath</code> according to the PKIX certification path validation
+ * algorithm.<br />
+ * <br />
+ * To instantiate a <code>PKIXParameters</code> object, an application must specify
+ * one or more <i>most-trusted CAs</i> as defined by the PKIX certification
+ * path validation algorithm. The most-trusted CAs can be specified
+ * using one of two constructors. An application can call
+ * {@link #PKIXParameters(Set)}, specifying a Set of <code>TrustAnchor</code> objects, each
+ * of which identify a most-trusted CA. Alternatively, an application
+ * can call {@link #PKIXParameters(KeyStore)}, specifying a <code>KeyStore</code> instance
+ * containing trusted certificate entries, each of which will be
+ * considered as a most-trusted CA.<br />
+ * <br />
+ * Once a <code>PKIXParameters</code> object has been created, other parameters can
+ * be specified (by calling {@link #setInitialPolicies} or {@link #setDate}, for
+ * instance) and then the <code>PKIXParameters</code> is passed along with the
+ * <code>CertPath</code> to be validated to {@link CertPathValidator#validate}.<br />
+ * <br />
+ * Any parameter that is not set (or is set to null) will be set to the
+ * default value for that parameter. The default value for the date
+ * parameter is null, which indicates the current time when the path is
+ * validated. The default for the remaining parameters is the least
+ * constrained.<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 PKIXParameters implements CertPathParameters {
+ private Set trustAnchors;
+ private Set initialPolicies = new HashSet();
+ private List certStores = new ArrayList();
+ private CertSelector certSelector;
+ private List certPathCheckers = new ArrayList();
+ private boolean revocationEnabled = true;
+ private boolean explicitPolicyRequired = false;
+ private boolean policyMappingInhibited = false;
+ private boolean anyPolicyInhibited = false;
+ private boolean policyQualifiersRejected = true;
+ private Date date;
+ private String sigProvider;
+
+ /**
+ * 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(Set trustAnchors)
+ throws InvalidAlgorithmParameterException
+ {
+ setTrustAnchors( trustAnchors );
+ }
+
+ /**
+ * Creates an instance of PKIXParameters that populates the
+ * set of most-trusted CAs from the trusted certificate
+ * entries contained in the specified KeyStore. Only keystore
+ * entries that contain trusted X509Certificates are
+ * considered; all other certificate types are ignored.
+ *
+ * @param keystore a KeyStore from which the set of
+ * most-trusted CAs will be populated
+ *
+ * @exception KeyStoreException if the keystore has not been
+ * initialized
+ * @exception InvalidAlgorithmParameterException if the keystore
+ * does not contain at least one trusted certificate entry
+ * @exception NullPointerException if the keystore is null
+ **/
+ public PKIXParameters(KeyStore keystore)
+ throws KeyStoreException,
+ InvalidAlgorithmParameterException
+ {
+ if ( keystore == null )
+ throw new NullPointerException( "the keystore parameter must be non-null" );
+
+ Set trustAnchors = new HashSet();
+ String alias;
+ Certificate cert;
+ Enumeration enum = keystore.aliases();
+ while ( enum.hasMoreElements() ) {
+ alias = (String)enum.nextElement();
+ if ( keystore.isCertificateEntry( alias ) ) {
+ cert = keystore.getCertificate( alias );
+ if ( cert instanceof X509Certificate )
+ trustAnchors.add( new TrustAnchor( (X509Certificate)cert, null ) );
+ }
+ }
+ setTrustAnchors( trustAnchors );
+ }
+
+ /**
+ * Returns an immutable Set of the most-trusted CAs.
+ *
+ * @return an immutable <code>Set</code> of
+ * <code>TrustAnchors</code> (never <code>null</code>)
+ *
+ * @see #setTrustAnchors
+ **/
+ public Set getTrustAnchors()
+ {
+ return Collections.unmodifiableSet(trustAnchors);
+ }
+
+ /**
+ * Sets the Set of most-trusted CAs.<br />
+ * <br />
+ * Note that the Set is copied to protect against subsequent
+ * modifications.<br />
+ * <br />
+ * @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 java.security.cert.TrustAnchor
+ *
+ * @see #getTrustAnchors
+ **/
+ public void setTrustAnchors(Set trustAnchors)
+ throws InvalidAlgorithmParameterException
+ {
+ if ( trustAnchors == null )
+ throw new NullPointerException("the trustAnchors parameter must be non-null");
+ if ( trustAnchors.isEmpty() )
+ throw new InvalidAlgorithmParameterException("the trustAnchors parameter must be non-empty");
+
+ Iterator iter = trustAnchors.iterator();
+ TrustAnchor obj;
+ this.trustAnchors = new HashSet();
+ while( iter.hasNext() ) {
+ obj = (TrustAnchor)iter.next();
+ if ( obj != null ) {
+ this .trustAnchors.add( obj );
+ }
+ }
+ }
+
+ /**
+ * 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 Set getInitialPolicies()
+ {
+ Set returnSet = initialPolicies;
+ if ( initialPolicies == null )
+ returnSet = new HashSet();
+
+ return Collections.unmodifiableSet( 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 void setInitialPolicies(Set initialPolicies)
+ {
+ if ( initialPolicies == null || initialPolicies.isEmpty() )
+ {
+ this.initialPolicies = null;
+ }
+ else
+ {
+ Iterator iter = initialPolicies.iterator();
+ this.initialPolicies = new HashSet();
+ String obj;
+ while ( iter.hasNext() )
+ {
+ obj = (String)iter.next();
+ if ( obj != null ) {
+ this.initialPolicies.add( obj );
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the list of CertStores to be used in finding
+ * certificates and CRLs. May be null, in which case no
+ * CertStores will be used. The first CertStores in the list
+ * may be preferred to those that appear later.<br />
+ * <br />
+ * Note that the List is copied to protect against subsequent
+ * modifications.<br />
+ * <br />
+ * @param stores a List of CertStores (or <code>null</code>)
+ *
+ * @exception ClassCastException if any of the elements in the
+ * list are not of type <code>java.security.cert.CertStore</code>
+ *
+ * @see #getCertStores()
+ **/
+ public void setCertStores(List stores)
+ {
+ certStores = new ArrayList();
+ if ( stores != null && ! stores.isEmpty() )
+ {
+ Iterator iter = stores.iterator();
+ CertStore obj;
+ while ( iter.hasNext() )
+ {
+ obj = (CertStore)iter.next();
+ if ( obj != null )
+ {
+ certStores.add( obj );
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds a CertStore to the end of the list of CertStores used
+ * in finding certificates and CRLs.
+ *
+ * @param store the <code>CertStore</code> to add. If
+ * <code>null</code<, the store is ignored (not added to
+ * list).
+ **/
+ public void addCertStore(CertStore store)
+ {
+ if ( store != null )
+ certStores.add( store );
+ }
+
+ /**
+ * Returns an immutable List of CertStores that are used to
+ * find certificates and CRLs.
+ *
+ * @return an immutable List of CertStores (may be empty, but never <code>null</code>)
+ *
+ * @see #setCertStores(java.util.List)
+ **/
+ public List getCertStores()
+ {
+ return Collections.unmodifiableList(certStores);
+ }
+
+ /**
+ * Sets the RevocationEnabled flag. If this flag is true, the default
+ * revocation checking mechanism of the underlying PKIX service provider
+ * will be used. If this flag is false, the default revocation checking
+ * mechanism will be disabled (not used).<br />
+ * <br />
+ * When a <code>PKIXParameters</code> object is created, this flag is set
+ * to true. This setting reflects the most common strategy for checking
+ * revocation, since each service provider must support revocation
+ * checking to be PKIX compliant. Sophisticated applications should set
+ * this flag to false when it is not practical to use a PKIX service
+ * provider's default revocation checking mechanism or when an alternative
+ * revocation checking mechanism is to be substituted (by also calling the
+ * {@link #addCertPathChecker addCertPathChecker} or {@link
+ * #setCertPathCheckers setCertPathCheckers} methods).
+ *
+ * @param val the new value of the RevocationEnabled flag
+ **/
+ public void setRevocationEnabled(boolean val)
+ {
+ revocationEnabled = val;
+ }
+
+ /**
+ * Checks the RevocationEnabled flag. If this flag is true,
+ * the default revocation checking mechanism of the underlying
+ * PKIX service provider will be used. If this flag is false,
+ * the default revocation checking mechanism will be disabled
+ * (not used). See the setRevocationEnabled method for more
+ * details on setting the value of this flag.
+ *
+ * @return the current value of the RevocationEnabled flag
+ **/
+ public boolean isRevocationEnabled()
+ {
+ return revocationEnabled;
+ }
+
+ /**
+ * Sets the ExplicitPolicyRequired flag. If this flag is true,
+ * an acceptable policy needs to be explicitly identified in
+ * every certificate. By default, the ExplicitPolicyRequired
+ * flag is false.
+ *
+ * @param val true if explicit policy is to be required, false
+ * otherwise
+ **/
+ public void setExplicitPolicyRequired(boolean val)
+ {
+ explicitPolicyRequired = val;
+ }
+
+ /**
+ * Checks if explicit policy is required. If this flag is
+ * true, an acceptable policy needs to be explicitly
+ * identified in every certificate. By default, the
+ * ExplicitPolicyRequired flag is false.
+ *
+ * @return true if explicit policy is required, false otherwise
+ **/
+ public boolean isExplicitPolicyRequired()
+ {
+ return explicitPolicyRequired;
+ }
+
+ /**
+ * Sets the PolicyMappingInhibited flag. If this flag is true,
+ * policy mapping is inhibited. By default, policy mapping is
+ * not inhibited (the flag is false).
+ *
+ * @param val true if policy mapping is to be inhibited, false otherwise
+ **/
+ public void setPolicyMappingInhibited(boolean val)
+ {
+ policyMappingInhibited = val;
+ }
+
+ /**
+ * Checks if policy mapping is inhibited. If this flag is
+ * true, policy mapping is inhibited. By default, policy
+ * mapping is not inhibited (the flag is false).
+ *
+ * @return true if policy mapping is inhibited, false otherwise
+ **/
+ public boolean isPolicyMappingInhibited()
+ {
+ return policyMappingInhibited;
+ }
+
+ /**
+ * Sets state to determine if the any policy OID should be
+ * processed if it is included in a certificate. By default,
+ * the any policy OID is not inhibited ({@link #isAnyPolicyInhibited()}
+ * returns false).
+ *
+ * @return val - <code>true</code> if the any policy OID is to be inhibited, <code>false</code> otherwise
+ **/
+ public void setAnyPolicyInhibited(boolean val)
+ {
+ anyPolicyInhibited = val;
+ }
+
+ /**
+ * Checks whether the any policy OID should be processed if it
+ * is included in a certificate.
+ *
+ * @return <code>true</code> if the any policy OID is inhibited, <code>false</code> otherwise
+ **/
+ public boolean isAnyPolicyInhibited()
+ {
+ return anyPolicyInhibited;
+ }
+
+ /**
+ * Sets the PolicyQualifiersRejected flag. If this flag is
+ * true, certificates that include policy qualifiers in a
+ * certificate policies extension that is marked critical are
+ * rejected. If the flag is false, certificates are not
+ * rejected on this basis.<br />
+ * <br />
+ * When a <code>PKIXParameters</code> object is created, this flag is set
+ * to true. This setting reflects the most common (and
+ * simplest) strategy for processing policy
+ * qualifiers. Applications that want to use a more
+ * sophisticated policy must set this flag to false.<br />
+ * <br />
+ * Note that the PKIX certification path validation algorithm
+ * specifies that any policy qualifier in a certificate
+ * policies extension that is marked critical must be
+ * processed and validated. Otherwise the certification path
+ * must be rejected. If the policyQualifiersRejected flag is
+ * set to false, it is up to the application to validate all
+ * policy qualifiers in this manner in order to be PKIX
+ * compliant.
+ *
+ * @param qualifiersRejected the new value of the PolicyQualifiersRejected flag
+ *
+ * @see #getPolicyQualifiersRejected()
+ * @see PolicyQualifierInfo
+ **/
+ public void setPolicyQualifiersRejected(boolean qualifiersRejected)
+ {
+ policyQualifiersRejected = qualifiersRejected;
+ }
+
+ /**
+ * Gets the PolicyQualifiersRejected flag. If this flag is
+ * true, certificates that include policy qualifiers in a
+ * certificate policies extension that is marked critical are
+ * rejected. If the flag is false, certificates are not
+ * rejected on this basis.<br />
+ * <br />
+ * When a PKIXParameters object is created, this flag is set to
+ * true. This setting reflects the most common (and simplest)
+ * strategy for processing policy qualifiers. Applications that
+ * want to use a more sophisticated policy must set this flag
+ * to false.
+ *
+ * @return the current value of the PolicyQualifiersRejected flag
+ *
+ * @see #setPolicyQualifiersRejected(boolean)
+ **/
+ public boolean getPolicyQualifiersRejected()
+ {
+ return policyQualifiersRejected;
+ }
+
+ /**
+ * Returns the time for which the validity of the
+ * certification path should be determined. If null, the
+ * current time is used.<br />
+ * <br />
+ * Note that the Date returned is copied to protect against
+ * subsequent modifications.
+ *
+ * @return the Date, or <code>null</code> if not set
+ *
+ * @see #setDate(java.util.Date)
+ **/
+ public Date getDate()
+ {
+ if ( date == null )
+ return null;
+
+ return new Date( date.getTime() );
+ }
+
+ /**
+ * Sets the time for which the validity of the certification
+ * path should be determined. If null, the current time is
+ * used.<br />
+ * <br />
+ * Note that the Date supplied here is copied to protect
+ * against subsequent modifications.
+ *
+ * @param date the Date, or <code>null</code> for the current time
+ *
+ * @see #getDate()
+ **/
+ public void setDate(Date date)
+ {
+ if ( date == null )
+ this.date = null;
+ else
+ this.date = new Date( date.getTime() );
+ }
+
+ /**
+ * 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 void setCertPathCheckers(List checkers)
+ {
+ certPathCheckers = new ArrayList();
+ if ( checkers == null )
+ return;
+ Iterator iter = checkers.iterator();
+ while ( iter.hasNext() )
+ certPathCheckers.add( (PKIXCertPathChecker)((PKIXCertPathChecker)iter.next()).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 List getCertPathCheckers()
+ {
+ List checkers = new ArrayList();
+ Iterator iter = certPathCheckers.iterator();
+ while ( iter.hasNext() )
+ {
+ checkers.add( (PKIXCertPathChecker)((PKIXCertPathChecker)iter.next()).clone() );
+ }
+ return Collections.unmodifiableList(checkers);
+ }
+
+ /**
+ * Adds a PKIXCertPathChecker to the list of certification
+ * path checkers. See the {@link #setCertPathCheckers} method for more
+ * details.<br />
+ * <br />
+ * Note that the <code>PKIXCertPathChecker</code> is cloned to protect
+ * against subsequent modifications.
+ *
+ * @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 void addCertPathChecker( PKIXCertPathChecker checker )
+ {
+ if ( checker != null )
+ {
+ certPathCheckers.add( checker.clone() );
+ }
+ }
+
+ /**
+ * Returns the signature provider's name, or <code>null</code> if not set.
+ *
+ * @return the signature provider's name (or <code>null</code>)
+ *
+ * @see #setSigProvider(java.lang.String)
+ **/
+ public String getSigProvider()
+ {
+ return sigProvider;
+ }
+
+ /**
+ * Sets the signature provider's name. The specified provider
+ * will be preferred when creating Signature objects. If null
+ * or not set, the first provider found supporting the
+ * algorithm will be used.
+ *
+ * @param sigProvider the signature provider's name (or <code>null</code>)
+ *
+ * @see #getSigProvider()
+ **/
+ public void setSigProvider(String sigProvider)
+ {
+ this.sigProvider = sigProvider;
+ }
+
+ /**
+ * 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(java.security.cert.CertSelector)
+ **/
+ public CertSelector getTargetCertConstraints()
+ {
+ if ( certSelector == null )
+ return null;
+
+ return (CertSelector)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 void setTargetCertConstraints(CertSelector selector)
+ {
+ if ( selector == null )
+ certSelector = null;
+ else
+ certSelector = (CertSelector)selector.clone();
+ }
+
+ /**
+ * Makes a copy of this PKIXParameters object. Changes to the
+ * copy will not affect the original and vice versa.
+ *
+ * @return a copy of this <code>PKIXParameters</code> object
+ **/
+ public Object clone()
+ {
+ try {
+ PKIXParameters obj = (PKIXParameters)super.clone();
+ obj.certStores = new ArrayList( certStores );
+ 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 = (CertSelector)certSelector.clone();
+ }
+ return obj;
+ } catch ( CloneNotSupportedException ex ) {
+ throw new InternalError();
+ }
+ }
+
+ /**
+ * Returns a formatted string describing the parameters.
+ *
+ * @return a formatted string describing the parameters.
+ **/
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer();
+ s.append("[\n");
+ if ( trustAnchors != null )
+ {
+ s.append(" Trust Anchors: ").append(trustAnchors).append('\n');
+ }
+ if ( initialPolicies != null )
+ {
+ if ( initialPolicies.isEmpty() )
+ {
+ s.append(" Initial Policy OIDs: any\n" );
+ }
+ else
+ {
+ s.append(" Initial Policy OIDs: [").append(initialPolicies).append("]\n");
+ }
+ }
+ s.append(" Validity Date: ");
+ if ( date != null )
+ s.append(date);
+ else
+ s.append("null");
+ s.append('\n');
+
+ s.append(" Signature Provider: ");
+ if ( sigProvider != null )
+ s.append(sigProvider);
+ else
+ s.append("null");
+ s.append('\n');
+
+ s.append(" Default Revocation Enabled: ");
+ s.append(revocationEnabled);
+ s.append('\n' );
+
+ s.append(" Explicit Policy Required: ");
+ s.append(explicitPolicyRequired);
+ s.append('\n');
+
+ s.append(" Policy Mapping Inhibited: ");
+ s.append(policyMappingInhibited);
+ s.append('\n');
+
+ s.append(" Any Policy Inhibited: ");
+ s.append(anyPolicyInhibited);
+ s.append('\n');
+
+ s.append(" Policy Qualifiers Rejected: ");
+ s.append(policyQualifiersRejected);
+ s.append('\n');
+
+ s.append(" Target Cert Constraints: ");
+ s.append(certSelector);
+ s.append('\n');
+
+ s.append(" Certification Path Checkers: [");
+ s.append(certPathCheckers);
+ s.append( "}\n");
+
+ s.append(" CertStores: [");
+ s.append(certStores);
+ s.append("}\n");
+
+ s.append("]\n");
+
+ return s.toString();
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyNode.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyNode.java
new file mode 100644
index 000000000..cdae45205
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyNode.java
@@ -0,0 +1,107 @@
+package java.security.cert;
+
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * An immutable valid policy tree node as defined by the PKIX certification
+ * path validation algorithm.<br />
+ * <br />
+ * One of the outputs of the PKIX certification path validation
+ * algorithm is a valid policy tree, which includes the policies that
+ * were determined to be valid, how this determination was reached,
+ * and any policy qualifiers encountered. This tree is of depth
+ * <i>n</i>, where <i>n</i> is the length of the certification
+ * path that has been validated.<br />
+ * <br />
+ * Most applications will not need to examine the valid policy tree.
+ * They can achieve their policy processing goals by setting the
+ * policy-related parameters in <code>PKIXParameters</code>. However,
+ * the valid policy tree is available for more sophisticated applications,
+ * especially those that process policy qualifiers.<br />
+ * <br />
+ * {@link PKIXCertPathValidatorResult#getPolicyTree()
+ * PKIXCertPathValidatorResult.getPolicyTree} returns the root node of the
+ * valid policy tree. The tree can be traversed using the
+ * {@link #getChildren getChildren} and {@link #getParent getParent} methods.
+ * Data about a particular node can be retrieved using other methods of
+ * <code>PolicyNode</code>.<br />
+ * <br />
+ * <b>Concurrent Access</b><br />
+ * <br />
+ * All <code>PolicyNode</code> objects must be immutable and
+ * thread-safe. Multiple threads may concurrently invoke the methods defined
+ * in this class on a single <code>PolicyNode</code> object (or more than one)
+ * with no ill effects. This stipulation applies to all public fields and
+ * methods of this class and any added or overridden by subclasses.
+ **/
+public interface PolicyNode
+{
+
+ /**
+ * Returns the parent of this node, or <code>null</code> if this is the
+ * root node.
+ *
+ * @return the parent of this node, or <code>null</code> if this is the
+ * root node
+ */
+ public PolicyNode getParent();
+
+ /**
+ * Returns an iterator over the children of this node. Any attempts to
+ * modify the children of this node through the
+ * <code>Iterator</code>'s remove method must throw an
+ * <code>UnsupportedOperationException</code>.
+ *
+ * @return an iterator over the children of this node
+ */
+ public Iterator getChildren();
+
+ /**
+ * Returns the depth of this node in the valid policy tree.
+ *
+ * @return the depth of this node (0 for the root node, 1 for its
+ * children, and so on)
+ */
+ public int getDepth();
+
+ /**
+ * Returns the valid policy represented by this node.
+ *
+ * @return the <code>String</code> OID of the valid policy
+ * represented by this node, or the special value "any-policy". For
+ * the root node, this method always returns the special value "any-policy".
+ */
+ public String getValidPolicy();
+
+ /**
+ * Returns the set of policy qualifiers associated with the
+ * valid policy represented by this node.
+ *
+ * @return an immutable <code>Set</code> of
+ * <code>PolicyQualifierInfo</code>s. For the root node, this
+ * is always an empty <code>Set</code>.
+ */
+ public Set getPolicyQualifiers();
+
+ /**
+ * Returns the set of expected policies that would satisfy this
+ * node's valid policy in the next certificate to be processed.
+ *
+ * @return an immutable <code>Set</code> of expected policy
+ * <code>String</code> OIDs, or an immutable <code>Set</code> with
+ * the single special value "any-policy". For the root node, this method
+ * always returns a <code>Set</code> with the single value "any-policy".
+ */
+ public Set getExpectedPolicies();
+
+ /**
+ * Returns the criticality indicator of the certificate policy extension
+ * in the most recently processed certificate.
+ *
+ * @return <code>true</code> if extension marked critical,
+ * <code>false</code> otherwise. For the root node, <code>false</code>
+ * is always returned.
+ */
+ public boolean isCritical();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyQualifierInfo.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyQualifierInfo.java
new file mode 100644
index 000000000..a17f49bf4
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyQualifierInfo.java
@@ -0,0 +1,196 @@
+package java.security.cert;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROutputStream;
+import org.spongycastle.asn1.util.ASN1Dump;
+
+/**
+ * An immutable policy qualifier represented by the ASN.1 PolicyQualifierInfo
+ * structure.<br />
+ * <br />
+ * The ASN.1 definition is as follows:<br />
+ * <br />
+ *
+ * <pre>
+ * PolicyQualifierInfo ::= SEQUENCE {
+ * policyQualifierId PolicyQualifierId,
+ * qualifier ANY DEFINED BY policyQualifierId }
+ * </pre>
+ *
+ * <br />
+ * <br />
+ * A certificate policies extension, if present in an X.509 version 3
+ * certificate, contains a sequence of one or more policy information terms,
+ * each of which consists of an object identifier (OID) and optional qualifiers.
+ * In an end-entity certificate, these policy information terms indicate the
+ * policy under which the certificate has been issued and the purposes for which
+ * the certificate may be used. In a CA certificate, these policy information
+ * terms limit the set of policies for certification paths which include this
+ * certificate.<br />
+ * <br />
+ * A <code>Set</code> of <code>PolicyQualifierInfo</code> objects are
+ * returned by the
+ * {@link PolicyNode#getPolicyQualifiers PolicyNode.getPolicyQualifiers} method.
+ * This allows applications with specific policy requirements to process and
+ * validate each policy qualifier. Applications that need to process policy
+ * qualifiers should explicitly set the <code>policyQualifiersRejected</code>
+ * flag to false (by calling the
+ * {@link PKIXParameters#setPolicyQualifiersRejected
+ * PKIXParameters.setPolicyQualifiersRejected} method) before validating a
+ * certification path.<br />
+ * <br />
+ * Note that the PKIX certification path validation algorithm specifies that any
+ * policy qualifier in a certificate policies extension that is marked critical
+ * must be processed and validated. Otherwise the certification path must be
+ * rejected. If the <code>policyQualifiersRejected</code> flag is set to
+ * false, it is up to the application to validate all policy qualifiers in this
+ * manner in order to be PKIX compliant.<br />
+ * <br />
+ * <b>Concurrent Access</b><br />
+ * <br />
+ * All <code>PolicyQualifierInfo</code> objects must be immutable and
+ * thread-safe. That is, multiple threads may concurrently invoke the methods
+ * defined in this class on a single <code>PolicyQualifierInfo</code> object
+ * (or more than one) with no ill effects. Requiring
+ * <code>PolicyQualifierInfo</code> objects to be immutable and thread-safe
+ * allows them to be passed around to various pieces of code without worrying
+ * about coordinating access.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier},
+ * {@link org.spongycastle.asn1.DEROutputStream DEROutputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object}
+ */
+public final class PolicyQualifierInfo
+{
+ private String id;
+
+ private byte[] encoded;
+
+ private byte[] qualifier;
+
+ /**
+ * Creates an instance of <code>PolicyQualifierInfo</code> from the
+ * encoded bytes. The encoded byte array is copied on construction.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier} and
+ * {@link org.spongycastle.asn1.DEROutputStream DEROutputStream}
+ *
+ * @param encoded
+ * a byte array containing the qualifier in DER encoding
+ *
+ * @exception IOException
+ * thrown if the byte array does not represent a valid and
+ * parsable policy qualifier
+ */
+ public PolicyQualifierInfo(byte[] encoded) throws IOException
+ {
+ this.encoded = (byte[])encoded.clone();
+ try
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(
+ this.encoded);
+ ASN1InputStream derInStream = new ASN1InputStream(inStream);
+ ASN1Sequence obj = (ASN1Sequence)derInStream.readObject();
+ id = ((ASN1ObjectIdentifier)obj.getObjectAt(0)).getId();
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ DEROutputStream derOutStream = new DEROutputStream(outStream);
+
+ derOutStream.writeObject(obj.getObjectAt(1));
+ derOutStream.close();
+
+ qualifier = outStream.toByteArray();
+ }
+ catch (Exception ex)
+ {
+ throw new IOException("parsing exception : " + ex.toString());
+ }
+ }
+
+ /**
+ * Returns the <code>policyQualifierId</code> field of this
+ * <code>PolicyQualifierInfo</code>. The <code>policyQualifierId</code>
+ * is an Object Identifier (OID) represented by a set of nonnegative
+ * integers separated by periods.
+ *
+ * @return the OID (never <code>null</code>)
+ */
+ public String getPolicyQualifierId()
+ {
+ return id;
+ }
+
+ /**
+ * Returns the ASN.1 DER encoded form of this
+ * <code>PolicyQualifierInfo</code>.
+ *
+ * @return the ASN.1 DER encoded bytes (never <code>null</code>). Note
+ * that a copy is returned, so the data is cloned each time this
+ * method is called.
+ */
+ public byte[] getEncoded()
+ {
+ return (byte[])encoded.clone();
+ }
+
+ /**
+ * Returns the ASN.1 DER encoded form of the <code>qualifier</code> field
+ * of this <code>PolicyQualifierInfo</code>.
+ *
+ * @return the ASN.1 DER encoded bytes of the <code>qualifier</code>
+ * field. Note that a copy is returned, so the data is cloned each
+ * time this method is called.
+ */
+ public byte[] getPolicyQualifier()
+ {
+ if (qualifier == null)
+ {
+ return null;
+ }
+
+ return (byte[])qualifier.clone();
+ }
+
+ /**
+ * Return a printable representation of this
+ * <code>PolicyQualifierInfo</code>.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object}
+ *
+ * @return a <code>String</code> describing the contents of this
+ * <code>PolicyQualifierInfo</code>
+ */
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer();
+ s.append("PolicyQualifierInfo: [\n");
+ s.append("qualifierID: ").append(id).append('\n');
+ try
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(qualifier);
+ ASN1InputStream derInStream = new ASN1InputStream(inStream);
+ ASN1Object derObject = derInStream.readObject();
+ s
+ .append(" qualifier:\n").append(ASN1Dump.dumpAsString(derObject))
+ .append('\n');
+ }
+ catch (IOException ex)
+ {
+ s.append(ex.getMessage());
+ }
+ s.append("qualifier: ").append(id).append('\n');
+ s.append(']');
+ return s.toString();
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/TrustAnchor.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/TrustAnchor.java
new file mode 100644
index 000000000..f139a742c
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/TrustAnchor.java
@@ -0,0 +1,293 @@
+package java.security.cert;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Sequence;
+
+/**
+ * A trust anchor or most-trusted Certification Authority (CA). <br />
+ * <br />
+ * 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. <br />
+ * <br />
+ * <strong>Concurrent Access</strong><br />
+ * <br />
+ * All TrustAnchor objects must be immutable and thread-safe. That is, multiple
+ * threads may concurrently invoke the methods defined in this class on a
+ * single TrustAnchor object (or more than one) with no ill effects. Requiring
+ * TrustAnchor objects to be immutable and thread-safe allows them to be passed
+ * around to various pieces of code without worrying about coordinating access.
+ * This stipulation applies to all public fields and methods of this class and
+ * any added or overridden by subclasses.<br />
+ * <br />
+ * <b>TODO: implement better nameConstraints testing.</b>
+ **/
+public class TrustAnchor
+{
+ private X509Certificate trustCert = null;
+
+ private PublicKey trustPublicKey = null;
+
+ private String trustName = null;
+
+ private byte[] nameConstraints = null;
+
+ /**
+ * 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.<br />
+ * <br />
+ * 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.<br />
+ * <br />
+ *
+ * <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>
+ *
+ * <br />
+ * <br />
+ * Note that the name constraints byte array supplied is cloned to protect
+ * against subsequent modifications.
+ *
+ * @param trustedCert
+ * a trusted X509Certificate
+ * @param 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.
+ *
+ * @exception IllegalArgumentException
+ * if the name constraints cannot be decoded
+ * @exception NullPointerException
+ * if the specified X509Certificate is null
+ */
+ public TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints)
+ {
+ if (trustedCert == null)
+ {
+ throw new NullPointerException("trustedCert must be non-null");
+ }
+
+ this.trustCert = trustedCert;
+ if (nameConstraints != null)
+ {
+ this.nameConstraints = (byte[])nameConstraints.clone();
+ checkNameConstraints(this.nameConstraints);
+ }
+ }
+
+ /**
+ * 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.
+ *
+ * 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 {@link #TrustAnchor(X509Certificate trustedCert, byte[]
+ * nameConstraints) TrustAnchor(X509Certificate trustedCert, byte[]
+ * nameConstraints) }.
+ *
+ * Note that the name constraints byte array supplied here is cloned to
+ * protect against subsequent modifications.
+ *
+ * @param caName
+ * the X.500 distinguished name of the most-trusted CA in RFC
+ * 2253 String format
+ * @param pubKey
+ * the public key of the most-trusted CA
+ * @param 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.
+ *
+ * @exception IllegalArgumentException
+ * if the specified caName parameter is empty (<code>caName.length() == 0</code>)
+ * or incorrectly formatted or the name constraints cannot be
+ * decoded
+ * @exception NullPointerException
+ * if the specified caName or pubKey parameter is null
+ */
+ public TrustAnchor(String caName, PublicKey pubKey, byte[] nameConstraints)
+ {
+ if (caName == null)
+ {
+ throw new NullPointerException("caName must be non-null");
+ }
+ if (pubKey == null)
+ {
+ throw new NullPointerException("pubKey must be non-null");
+ }
+ if (caName.length() == 0)
+ {
+ throw new IllegalArgumentException(
+ "caName can not be an empty string");
+ }
+
+ this.trustName = caName;
+ this.trustPublicKey = pubKey;
+ if (nameConstraints != null)
+ {
+ this.nameConstraints = (byte[])nameConstraints.clone();
+ checkNameConstraints(this.nameConstraints);
+ }
+ }
+
+ /**
+ * Returns the most-trusted CA certificate.
+ *
+ * @return a trusted <code>X509Certificate</code> or <code>null</code>
+ * if the trust anchor was not specified as a trusted certificate
+ */
+ public final X509Certificate getTrustedCert()
+ {
+ return trustCert;
+ }
+
+ /**
+ * Returns the name of the most-trusted CA in RFC 2253 String format.
+ *
+ * @return the X.500 distinguished name of the most-trusted CA, or
+ * <code>null</code> if the trust anchor was not specified as a
+ * trusted public key and name pair
+ */
+ public final String getCAName()
+ {
+ return trustName;
+ }
+
+ /**
+ * Returns the public key of the most-trusted CA.
+ *
+ * @return the public key of the most-trusted CA, or null if the trust
+ * anchor was not specified as a trusted public key and name pair
+ */
+ public final PublicKey getCAPublicKey()
+ {
+ return trustPublicKey;
+ }
+
+ /**
+ * Returns the name constraints parameter. The specified name constraints
+ * are associated with this trust anchor and are intended to be used as
+ * additional constraints when validating an X.509 certification path.<br />
+ * <br />
+ * The name constraints are returned 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 <code>TrustAnchor(X509Certificate trustedCert, byte[]
+ * nameConstraints)</code>.<br />
+ * <br />
+ * Note that the byte array returned is cloned to protect against subsequent
+ * modifications.
+ *
+ * @return a byte array containing the ASN.1 DER encoding of a
+ * NameConstraints extension used for checking name constraints, or
+ * <code>null</code> if not set.
+ */
+ public final byte[] getNameConstraints()
+ {
+ return (byte[])nameConstraints.clone();
+ }
+
+ /**
+ * Returns a formatted string describing the <code>TrustAnchor</code>.
+ *
+ * @return a formatted string describing the <code>TrustAnchor</code>
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[\n");
+ if (getCAPublicKey() != null)
+ {
+ sb.append(" Trusted CA Public Key: ").append(getCAPublicKey()).append('\n');
+ sb.append(" Trusted CA Issuer Name: ").append(getCAName()).append('\n');
+ }
+ else
+ {
+ sb.append(" Trusted CA cert: ").append(getTrustedCert()).append('\n');
+ }
+ if (nameConstraints != null)
+ {
+ sb.append(" Name Constraints: ").append(nameConstraints).append('\n');
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Check given DER encoded nameConstraints for correct decoding. Currently
+ * only basic DER decoding test.<br />
+ * <br />
+ * <b>TODO: implement more testing.</b>
+ *
+ * @param data
+ * the DER encoded nameConstrains to be checked or
+ * <code>null</code>
+ * @exception IllegalArgumentException
+ * if the check failed.
+ */
+ private void checkNameConstraints(byte[] data)
+ {
+ if (data != null)
+ {
+ try
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(data);
+ ASN1InputStream derInStream = new ASN1InputStream(inStream);
+ ASN1Object derObject = derInStream.readObject();
+ if (!(derObject instanceof ASN1Sequence))
+ {
+ throw new IllegalArgumentException(
+ "nameConstraints parameter decoding error");
+ }
+ }
+ catch (IOException ex)
+ {
+ throw new IllegalArgumentException(
+ "nameConstraints parameter decoding error: " + ex);
+ }
+ }
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRL.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRL.java
new file mode 100644
index 000000000..cf65ed0b6
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRL.java
@@ -0,0 +1,77 @@
+
+package java.security.cert;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.util.Date;
+import java.util.Set;
+
+public abstract class X509CRL extends CRL implements X509Extension
+{
+ protected X509CRL()
+ {
+ super("X.509");
+ }
+
+ public boolean equals(Object other)
+ {
+ if ( this == other )
+ return true;
+
+ if ( !(other instanceof X509CRL) )
+ return false;
+
+ try
+ {
+ byte[] enc1 = getEncoded();
+ byte[] enc2 = ((X509CRL)other).getEncoded();
+
+ return MessageDigest.isEqual(enc1, enc2);
+ }
+ catch (CRLException e)
+ {
+ return false;
+ }
+ }
+
+ public int hashCode()
+ {
+ int hashcode = 0;
+
+ try
+ {
+ byte[] encoded = getEncoded();
+ for (int i = 1; i < encoded.length; i++)
+ {
+ hashcode += encoded[i] * i;
+ }
+ }
+ catch (CRLException ce)
+ {
+ return(hashcode);
+ }
+
+ return(hashcode);
+ }
+
+ public abstract byte[] getEncoded() throws CRLException;
+ public abstract Principal getIssuerDN();
+ public abstract Date getNextUpdate();
+ public abstract X509CRLEntry getRevokedCertificate(BigInteger serialNumber);
+ public abstract Set getRevokedCertificates();
+ public abstract String getSigAlgName();
+ public abstract String getSigAlgOID();
+ public abstract byte[] getSigAlgParams();
+ public abstract byte[] getSignature();
+ public abstract byte[] getTBSCertList() throws CRLException;
+ public abstract Date getThisUpdate();
+ public abstract int getVersion();
+ public abstract void verify(PublicKey key) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException;
+ public abstract void verify(PublicKey key, String sigProvider) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException;
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLEntry.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLEntry.java
new file mode 100644
index 000000000..bb0d78074
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLEntry.java
@@ -0,0 +1,56 @@
+
+package java.security.cert;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.util.Date;
+
+public abstract class X509CRLEntry implements X509Extension
+{
+ public boolean equals(Object other)
+ {
+ if ( this == other )
+ return true;
+
+ if ( !(other instanceof X509CRLEntry) )
+ return false;
+
+ try
+ {
+ byte[] enc1 = getEncoded();
+ byte[] enc2 = ((X509CRLEntry)other).getEncoded();
+
+ return MessageDigest.isEqual(enc1, enc2);
+ }
+ catch (CRLException e)
+ {
+ return false;
+ }
+ }
+
+ public int hashCode()
+ {
+ int hashcode = 0;
+
+ try
+ {
+ byte[] encoded = getEncoded();
+ for (int i = 1; i < encoded.length; i++)
+ {
+ hashcode += encoded[i] * i;
+ }
+ }
+ catch (CRLException ce)
+ {
+ return(hashcode);
+ }
+
+ return(hashcode);
+ }
+
+ public abstract byte[] getEncoded() throws CRLException;
+ public abstract Date getRevocationDate();
+ public abstract BigInteger getSerialNumber();
+ public abstract boolean hasExtensions();
+ public abstract String toString();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java
new file mode 100644
index 000000000..7971e7b61
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java
@@ -0,0 +1,717 @@
+package java.security.cert;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CRL;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERInteger;
+import org.spongycastle.asn1.x509.X509Extensions;
+import org.spongycastle.asn1.x509.X509Name;
+import org.spongycastle.jce.PrincipalUtil;
+
+/**
+ * A <code>CRLSelector</code> that selects <code>X509CRLs</code> that match
+ * all specified criteria. This class is particularly useful when selecting CRLs
+ * from a <code>CertStore</code> to check revocation status of a particular
+ * certificate.<br />
+ * <br />
+ * When first constructed, an <code>X509CRLSelector</code> has no criteria
+ * enabled and each of the <code>get</code> methods return a default value (<code>null</code>).
+ * Therefore, the {@link #match match} method would return <code>true</code>
+ * for any <code>X509CRL</code>. Typically, several criteria are enabled (by
+ * calling {@link #setIssuerNames setIssuerNames} or
+ * {@link #setDateAndTime setDateAndTime}, for instance) and then the
+ * <code>X509CRLSelector</code> is passed to
+ * {@link CertStore#getCRLs CertStore.getCRLs} or some similar method.<br />
+ * <br />
+ * Please refer to RFC 2459 for definitions of the X.509 CRL fields and
+ * extensions mentioned below.<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.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier},
+ * {@link org.spongycastle.asn1.DEROutputStream DEROutputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name}
+ *
+ * @see CRLSelector
+ * @see X509CRL
+ */
+public class X509CRLSelector implements CRLSelector
+{
+ private Set issuerNames = null;
+
+ private Set issuerNamesX509 = null;
+
+ private BigInteger minCRL = null;
+
+ private BigInteger maxCRL = null;
+
+ private Date dateAndTime = null;
+
+ private X509Certificate certChecking = null;
+
+ /**
+ * Creates an <code>X509CRLSelector</code>. Initially, no criteria are
+ * set so any <code>X509CRL</code> will match.
+ */
+ public X509CRLSelector()
+ {
+ }
+
+ /**
+ * Sets the issuerNames criterion. The issuer distinguished name in the
+ * <code>X509CRL</code> must match at least one of the specified
+ * distinguished names. If <code>null</code>, any issuer distinguished
+ * name will do.<br />
+ * <br />
+ * This method allows the caller to specify, with a single method call, the
+ * complete set of issuer names which <code>X509CRLs</code> may contain.
+ * The specified value replaces the previous value for the issuerNames
+ * criterion.<br />
+ * <br />
+ * The <code>names</code> parameter (if not <code>null</code>) is a
+ * <code>Collection</code> of names. Each name is a <code>String</code>
+ * or a byte array representing a distinguished name (in RFC 2253 or ASN.1
+ * DER encoded form, respectively). If <code>null</code> is supplied as
+ * the value for this argument, no issuerNames check will be performed.<br />
+ * <br />
+ * Note that the <code>names</code> parameter can contain duplicate
+ * distinguished names, but they may be removed from the
+ * <code>Collection</code> of names returned by the
+ * {@link #getIssuerNames getIssuerNames} method.<br />
+ * <br />
+ * If a name is specified as a byte array, it should contain a single DER
+ * encoded distinguished name, as defined in X.501. The ASN.1 notation for
+ * this structure is as follows.
+ *
+ * <pre><code>
+ * Name ::= CHOICE {
+ * RDNSequence }
+ *
+ * RDNSequence ::= SEQUENCE OF RDN
+ *
+ * RDN ::=
+ * SET SIZE (1 .. MAX) OF AttributeTypeAndValue
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type AttributeType,
+ * value AttributeValue }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ *
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ * ....
+ * DirectoryString ::= CHOICE {
+ * teletexString TeletexString (SIZE (1..MAX)),
+ * printableString PrintableString (SIZE (1..MAX)),
+ * universalString UniversalString (SIZE (1..MAX)),
+ * utf8String UTF8String (SIZE (1.. MAX)),
+ * bmpString BMPString (SIZE (1..MAX)) }
+ * </code></pre>
+ *
+ * <br />
+ * <br />
+ * Note that a deep copy is performed on the <code>Collection</code> to
+ * protect against subsequent modifications.
+ *
+ * @param names
+ * a <code>Collection</code> of names (or <code>null</code>)
+ *
+ * @exception IOException
+ * if a parsing error occurs
+ *
+ * @see #getIssuerNames
+ */
+ public void setIssuerNames(Collection names) throws IOException
+ {
+ if (names == null || names.isEmpty())
+ {
+ issuerNames = null;
+ issuerNamesX509 = null;
+ }
+ else
+ {
+ Object item;
+ Iterator iter = names.iterator();
+ while (iter.hasNext())
+ {
+ item = iter.next();
+ if (item instanceof String)
+ {
+ addIssuerName((String)item);
+ }
+ else if (item instanceof byte[])
+ {
+ addIssuerName((byte[])item);
+ }
+ else
+ {
+ throw new IOException("name not byte[]or String: "
+ + item.toString());
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds a name to the issuerNames criterion. The issuer distinguished name
+ * in the <code>X509CRL</code> must match at least one of the specified
+ * distinguished names.<br />
+ * <br />
+ * This method allows the caller to add a name to the set of issuer names
+ * which <code>X509CRLs</code> may contain. The specified name is added to
+ * any previous value for the issuerNames criterion. If the specified name
+ * is a duplicate, it may be ignored.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the
+ * name
+ *
+ * @param name
+ * the name in RFC 2253 form
+ *
+ * @exception IOException
+ * if a parsing error occurs
+ */
+ public void addIssuerName(String name) throws IOException
+ {
+ if (issuerNames == null)
+ {
+ issuerNames = new HashSet();
+ issuerNamesX509 = new HashSet();
+ }
+ X509Name nameX509;
+ try
+ {
+ nameX509 = new X509Name(name);
+ }
+ catch (IllegalArgumentException ex)
+ {
+ throw new IOException(ex.getMessage());
+ }
+ issuerNamesX509.add(nameX509);
+ issuerNames.add(name);
+ }
+
+ /**
+ * Adds a name to the issuerNames criterion. The issuer distinguished name
+ * in the <code>X509CRL</code> must match at least one of the specified
+ * distinguished names.<br />
+ * <br />
+ * This method allows the caller to add a name to the set of issuer names
+ * which <code>X509CRLs</code> may contain. The specified name is added to
+ * any previous value for the issuerNames criterion. If the specified name
+ * is a duplicate, it may be ignored. If a name is specified as a byte
+ * array, it should contain a single DER encoded distinguished name, as
+ * defined in X.501. The ASN.1 notation for this structure is as follows.<br />
+ * <br />
+ * The name is provided as a byte array. This byte array should contain a
+ * single DER encoded distinguished name, as defined in X.501. The ASN.1
+ * notation for this structure appears in the documentation for
+ * {@link #setIssuerNames setIssuerNames(Collection names)}.<br />
+ * <br />
+ * Note that the byte array supplied here is cloned to protect against
+ * subsequent modifications.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the
+ * name, {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object} and
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence}
+ *
+ * @param name
+ * a byte array containing the name in ASN.1 DER encoded form
+ *
+ * @exception IOException
+ * if a parsing error occurs
+ */
+ public void addIssuerName(byte[] name) throws IOException
+ {
+ if (issuerNames == null)
+ {
+ issuerNames = new HashSet();
+ issuerNamesX509 = new HashSet();
+ }
+
+ ByteArrayInputStream inStream = new ByteArrayInputStream(name);
+ ASN1InputStream derInStream = new ASN1InputStream(inStream);
+ ASN1Object obj = derInStream.readObject();
+ if (obj instanceof ASN1Sequence)
+ {
+ issuerNamesX509.add(new X509Name((ASN1Sequence)obj));
+ }
+ else
+ {
+ throw new IOException("parsing error");
+ }
+ issuerNames.add(name.clone());
+ }
+
+ /**
+ * Sets the minCRLNumber criterion. The <code>X509CRL</code> must have a
+ * CRL number extension whose value is greater than or equal to the
+ * specified value. If <code>null</code>, no minCRLNumber check will be
+ * done.
+ *
+ * @param minCRL
+ * the minimum CRL number accepted (or <code>null</code>)
+ */
+ public void setMinCRLNumber(BigInteger minCRL)
+ {
+ this.minCRL = minCRL;
+ }
+
+ /**
+ * Sets the maxCRLNumber criterion. The <code>X509CRL</code> must have a
+ * CRL number extension whose value is less than or equal to the specified
+ * value. If <code>null</code>, no maxCRLNumber check will be done.
+ *
+ * @param maxCRL
+ * the maximum CRL number accepted (or <code>null</code>)
+ */
+ public void setMaxCRLNumber(BigInteger maxCRL)
+ {
+ this.maxCRL = maxCRL;
+ }
+
+ /**
+ * Sets the dateAndTime criterion. The specified date must be equal to or
+ * later than the value of the thisUpdate component of the
+ * <code>X509CRL</code> and earlier than the value of the nextUpdate
+ * component. There is no match if the <code>X509CRL</code> does not
+ * contain a nextUpdate component. If <code>null</code>, no dateAndTime
+ * check will be done.<br />
+ * <br />
+ * Note that the <code>Date</code> supplied here is cloned to protect
+ * against subsequent modifications.
+ *
+ * @param dateAndTime
+ * the <code>Date</code> to match against (or <code>null</code>)
+ *
+ * @see #getDateAndTime
+ */
+ public void setDateAndTime(Date dateAndTime)
+ {
+ if (dateAndTime == null)
+ {
+ this.dateAndTime = null;
+ }
+ else
+ {
+ this.dateAndTime = new Date(dateAndTime.getTime());
+ }
+ }
+
+ /**
+ * Sets the certificate being checked. This is not a criterion. Rather, it
+ * is optional information that may help a <code>CertStore</code> find
+ * CRLs that would be relevant when checking revocation for the specified
+ * certificate. If <code>null</code> is specified, then no such optional
+ * information is provided.
+ *
+ * @param cert
+ * the <code>X509Certificate</code> being checked (or
+ * <code>null</code>)
+ *
+ * @see #getCertificateChecking
+ */
+ public void setCertificateChecking(X509Certificate cert)
+ {
+ certChecking = cert;
+ }
+
+ /**
+ * Returns a copy of the issuerNames criterion. The issuer distinguished
+ * name in the <code>X509CRL</code> must match at least one of the
+ * specified distinguished names. If the value returned is <code>null</code>,
+ * any issuer distinguished name will do.<br />
+ * <br />
+ * If the value returned is not <code>null</code>, it is a
+ * <code>Collection</code> of names. Each name is a <code>String</code>
+ * or a byte array representing a distinguished name (in RFC 2253 or ASN.1
+ * DER encoded form, respectively). Note that the <code>Collection</code>
+ * returned may contain duplicate names.<br />
+ * <br />
+ * If a name is specified as a byte array, it should contain a single DER
+ * encoded distinguished name, as defined in X.501. The ASN.1 notation for
+ * this structure is given in the documentation for
+ * {@link #setIssuerNames setIssuerNames(Collection names)}.<br />
+ * <br />
+ * Note that a deep copy is performed on the <code>Collection</code> to
+ * protect against subsequent modifications.
+ *
+ * @return a <code>Collection</code> of names (or <code>null</code>)
+ * @see #setIssuerNames
+ */
+ public Collection getIssuerNames()
+ {
+ if (issuerNames == null)
+ {
+ return null;
+ }
+
+ Collection set = new HashSet();
+ Iterator iter = issuerNames.iterator();
+ Object item;
+ while (iter.hasNext())
+ {
+ item = iter.next();
+ if (item instanceof String)
+ {
+ set.add(new String((String)item));
+ }
+ else if (item instanceof byte[])
+ {
+ set.add(((byte[])item).clone());
+ }
+ }
+ return set;
+ }
+
+ /**
+ * Returns the minCRLNumber criterion. The <code>X509CRL</code> must have
+ * a CRL number extension whose value is greater than or equal to the
+ * specified value. If <code>null</code>, no minCRLNumber check will be
+ * done.
+ *
+ * @return the minimum CRL number accepted (or <code>null</code>)
+ */
+ public BigInteger getMinCRL()
+ {
+ return minCRL;
+ }
+
+ /**
+ * Returns the maxCRLNumber criterion. The <code>X509CRL</code> must have
+ * a CRL number extension whose value is less than or equal to the specified
+ * value. If <code>null</code>, no maxCRLNumber check will be done.
+ *
+ * @return the maximum CRL number accepted (or <code>null</code>)
+ */
+ public BigInteger getMaxCRL()
+ {
+ return maxCRL;
+ }
+
+ /**
+ * Returns the dateAndTime criterion. The specified date must be equal to or
+ * later than the value of the thisUpdate component of the
+ * <code>X509CRL</code> and earlier than the value of the nextUpdate
+ * component. There is no match if the <code>X509CRL</code> does not
+ * contain a nextUpdate component. If <code>null</code>, no dateAndTime
+ * check will be done.<br />
+ * <br />
+ * Note that the <code>Date</code> returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return the <code>Date</code> to match against (or <code>null</code>)
+ *
+ * @see #setDateAndTime
+ */
+ public Date getDateAndTime()
+ {
+ if (dateAndTime == null)
+ {
+ return null;
+ }
+
+ return new Date(dateAndTime.getTime());
+ }
+
+ /**
+ * Returns the certificate being checked. This is not a criterion. Rather,
+ * it is optional information that may help a <code>CertStore</code> find
+ * CRLs that would be relevant when checking revocation for the specified
+ * certificate. If the value returned is <code>null</code>, then no such
+ * optional information is provided.
+ *
+ * @return the certificate being checked (or <code>null</code>)
+ *
+ * @see #setCertificateChecking
+ */
+ public X509Certificate getCertificateChecking()
+ {
+ return certChecking;
+ }
+
+ /**
+ * Returns a printable representation of the <code>X509CRLSelector</code>.<br />
+ * <br />
+ * Uses
+ * {@link org.spongycastle.asn1.x509.X509Name#toString X509Name.toString} to
+ * format the output
+ *
+ * @return a <code>String</code> describing the contents of the
+ * <code>X509CRLSelector</code>.
+ */
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer();
+ s.append("X509CRLSelector: [\n");
+ if (issuerNamesX509 != null)
+ {
+ s.append(" IssuerNames:\n");
+ Iterator iter = issuerNamesX509.iterator();
+ while (iter.hasNext())
+ {
+ s.append(" ").append(iter.next()).append('\n');
+ }
+ }
+ if (minCRL != null)
+ {
+ s.append(" minCRLNumber: ").append(minCRL).append('\n');
+ }
+ if (maxCRL != null)
+ {
+ s.append(" maxCRLNumber: ").append(maxCRL).append('\n');
+ }
+ if (dateAndTime != null)
+ {
+ s.append(" dateAndTime: ").append(dateAndTime).append('\n');
+ }
+ if (certChecking != null)
+ {
+ s.append(" Certificate being checked: ").append(certChecking).append('\n');
+ }
+ s.append(']');
+ return s.toString();
+ }
+
+ /**
+ * Decides whether a <code>CRL</code> should be selected.<br />
+ * <br />
+ * Uses
+ * {@link org.spongycastle.asn1.x509.X509Name#toString X509Name.toString} to
+ * parse and to compare the crl parameter issuer and
+ * {@link org.spongycastle.asn1.x509.X509Extensions#CRLNumber CRLNumber} to
+ * access the CRL number extension.
+ *
+ * @param crl
+ * the <code>CRL</code> to be checked
+ *
+ * @return <code>true</code> if the <code>CRL</code> should be selected,
+ * <code>false</code> otherwise
+ */
+ public boolean match(CRL crl)
+ {
+ if (!(crl instanceof X509CRL))
+ {
+ return false;
+ }
+
+ X509CRL crlX509 = (X509CRL)crl;
+ boolean test;
+
+ if (issuerNamesX509 != null)
+ {
+ Iterator iter = issuerNamesX509.iterator();
+ test = false;
+ X509Name crlIssuer = null;
+ try
+ {
+ crlIssuer = PrincipalUtil.getIssuerX509Principal(crlX509);
+ }
+ catch (Exception ex)
+ {
+
+ return false;
+ }
+
+ while (iter.hasNext())
+ {
+ if (crlIssuer.equals(iter.next(), true))
+ {
+ test = true;
+ break;
+ }
+ }
+ if (!test)
+ {
+ return false;
+ }
+ }
+
+ byte[] data = crlX509.getExtensionValue(X509Extensions.CRLNumber
+ .getId());
+ if (data != null)
+ {
+ try
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(data);
+ ASN1InputStream derInputStream = new ASN1InputStream(inStream);
+ inStream = new ByteArrayInputStream(
+ ((ASN1OctetString)derInputStream.readObject())
+ .getOctets());
+ derInputStream = new ASN1InputStream(inStream);
+ BigInteger crlNumber = ((DERInteger)derInputStream.readObject())
+ .getPositiveValue();
+ if (minCRL != null && minCRL.compareTo(crlNumber) > 0)
+ {
+ return false;
+ }
+ if (maxCRL != null && maxCRL.compareTo(crlNumber) < 0)
+ {
+ return false;
+ }
+ }
+ catch (IOException ex)
+ {
+ return false;
+ }
+ }
+ else if (minCRL != null || maxCRL != null)
+ {
+ return false;
+ }
+
+ if (dateAndTime != null)
+ {
+ Date check = crlX509.getThisUpdate();
+ if (check == null)
+ {
+ return false;
+ }
+ else if (dateAndTime.before(check))
+ {
+ return false;
+ }
+
+ check = crlX509.getNextUpdate();
+ if (check == null)
+ {
+ return false;
+ }
+ else if (!dateAndTime.before(check))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns a copy of this object.
+ *
+ * @return the copy
+ */
+ public Object clone()
+ {
+ try
+ {
+ X509CRLSelector copy = (X509CRLSelector)super.clone();
+ if (issuerNames != null)
+ {
+ copy.issuerNames = new HashSet();
+ Iterator iter = issuerNames.iterator();
+ Object obj;
+ while (iter.hasNext())
+ {
+ obj = iter.next();
+ if (obj instanceof byte[])
+ {
+ copy.issuerNames.add(((byte[])obj).clone());
+ }
+ else
+ {
+ copy.issuerNames.add(obj);
+ }
+ }
+ copy.issuerNamesX509 = new HashSet(issuerNamesX509);
+ }
+ return copy;
+ }
+ catch (CloneNotSupportedException e)
+ {
+ /* Cannot happen */
+ throw new InternalError(e.toString());
+ }
+ }
+
+ /**
+ * Decides whether a <code>CRL</code> should be selected.
+ *
+ * @param crl
+ * the <code>CRL</code> to be checked
+ *
+ * @return <code>true</code> if the <code>CRL</code> should be selected,
+ * <code>false</code> otherwise
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof X509CRLSelector))
+ {
+ return false;
+ }
+
+ X509CRLSelector equalsCRL = (X509CRLSelector)obj;
+
+ if (!equals(dateAndTime, equalsCRL.dateAndTime))
+ {
+ return false;
+ }
+
+ if (!equals(minCRL, equalsCRL.minCRL))
+ {
+ return false;
+ }
+
+ if (!equals(maxCRL, equalsCRL.maxCRL))
+ {
+ return false;
+ }
+
+ if (!equals(issuerNamesX509, equalsCRL.issuerNamesX509))
+ {
+ return false;
+ }
+
+ if (!equals(certChecking, equalsCRL.certChecking))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Return <code>true</code> if two Objects are unequal.
+ * This means that one is <code>null</code> and the other is
+ * not or <code>obj1.equals(obj2)</code> returns
+ * <code>false</code>.
+ **/
+ private boolean equals(Object obj1, Object obj2)
+ {
+ if (obj1 == null)
+ {
+ if (obj2 != null)
+ {
+ return true;
+ }
+ }
+ else if (!obj1.equals(obj2))
+ {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java
new file mode 100644
index 000000000..89767cde5
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java
@@ -0,0 +1,2461 @@
+package java.security.cert;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERGeneralizedTime;
+import org.spongycastle.asn1.DEROutputStream;
+import org.spongycastle.asn1.util.ASN1Dump;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.ExtendedKeyUsage;
+import org.spongycastle.asn1.x509.KeyPurposeId;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.asn1.x509.X509Extensions;
+import org.spongycastle.asn1.x509.X509Name;
+import org.spongycastle.jce.PrincipalUtil;
+import org.spongycastle.util.Integers;
+
+/**
+ * A <code>CertSelector</code> that selects
+ * <code>X509Certificates that match all
+ * specified criteria. This class is particularly useful when
+ * selecting certificates from a CertStore to build a PKIX-compliant
+ * certification path.<br />
+ * <br />
+ * When first constructed, an <code>X509CertSelector</code> has no criteria enabled
+ * and each of the get methods return a default value (<code>null</code>, or -1 for
+ * the {@link #getBasicConstraints} method). Therefore, the {@link #match} method would
+ * return true for any <code>X509Certificate</code>. Typically, several criteria
+ * are enabled (by calling {@link #setIssuer} or {@link #setKeyUsage}, for instance) and
+ * then the <code>X509CertSelector</code> is passed to {@link CertStore#getCertificates} or
+ * some similar method.<br />
+ * <br />
+ * Several criteria can be enabled (by calling {@link #setIssuer} and
+ * {@link #setSerialNumber}, for example) such that the match method usually
+ * uniquely matches a single <code>X509Certificate</code>. We say usually, since it
+ * is possible for two issuing CAs to have the same distinguished name
+ * and each issue a certificate with the same serial number. Other
+ * unique combinations include the issuer, subject,
+ * subjectKeyIdentifier and/or the subjectPublicKey criteria.<br />
+ * <br />
+ * Please refer to RFC 2459 for definitions of the X.509 certificate
+ * extensions mentioned below.<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.<br />
+ * <br />
+ * <b>TODO: implement name constraints</b>
+ * <b>TODO: implement match check for path to names</b><br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier},
+ * {@link org.spongycastle.asn1.DEROutputStream DEROutputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object},
+ * {@link org.spongycastle.asn1.OIDTokenizer OIDTokenizer},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name},
+ * {@link org.spongycastle.asn1.x509.X509Extensions X509Extensions},
+ * {@link org.spongycastle.asn1.x509.ExtendedKeyUsage ExtendedKeyUsage},
+ * {@link org.spongycastle.asn1.x509.KeyPurposeId KeyPurposeId},
+ * {@link org.spongycastle.asn1.x509.SubjectPublicKeyInfo SubjectPublicKeyInfo},
+ * {@link org.spongycastle.asn1.x509.AlgorithmIdentifier AlgorithmIdentifier}
+ */
+public class X509CertSelector implements CertSelector
+{
+ private static final Hashtable keyPurposeIdMap = new Hashtable();
+ static
+ {
+ keyPurposeIdMap.put(KeyPurposeId.id_kp_serverAuth.getId(),
+ KeyPurposeId.id_kp_serverAuth);
+ keyPurposeIdMap.put(KeyPurposeId.id_kp_clientAuth.getId(),
+ KeyPurposeId.id_kp_clientAuth);
+ keyPurposeIdMap.put(KeyPurposeId.id_kp_codeSigning.getId(),
+ KeyPurposeId.id_kp_codeSigning);
+ keyPurposeIdMap.put(KeyPurposeId.id_kp_emailProtection.getId(),
+ KeyPurposeId.id_kp_emailProtection);
+ keyPurposeIdMap.put(KeyPurposeId.id_kp_ipsecEndSystem.getId(),
+ KeyPurposeId.id_kp_ipsecEndSystem);
+ keyPurposeIdMap.put(KeyPurposeId.id_kp_ipsecTunnel.getId(),
+ KeyPurposeId.id_kp_ipsecTunnel);
+ keyPurposeIdMap.put(KeyPurposeId.id_kp_ipsecUser.getId(),
+ KeyPurposeId.id_kp_ipsecUser);
+ keyPurposeIdMap.put(KeyPurposeId.id_kp_timeStamping.getId(),
+ KeyPurposeId.id_kp_timeStamping);
+ }
+
+ private X509Certificate x509Cert = null;
+
+ private BigInteger serialNumber = null;
+
+ private Object issuerDN = null;
+
+ private X509Name issuerDNX509 = null;
+
+ private Object subjectDN = null;
+
+ private X509Name subjectDNX509 = null;
+
+ private byte[] subjectKeyID = null;
+
+ private byte[] authorityKeyID = null;
+
+ private Date certValid = null;
+
+ private Date privateKeyValid = null;
+
+ private ASN1ObjectIdentifier subjectKeyAlgID = null;
+
+ private PublicKey subjectPublicKey = null;
+
+ private byte[] subjectPublicKeyByte = null;
+
+ private boolean[] keyUsage = null;
+
+ private Set keyPurposeSet = null;
+
+ private boolean matchAllSubjectAltNames = true;
+
+ private Set subjectAltNames = null;
+
+ private Set subjectAltNamesByte = null;
+
+ private int minMaxPathLen = -1;
+
+ private Set policy = null;
+
+ private Set policyOID = null;
+
+ private Set pathToNames = null;
+
+ private Set pathToNamesByte = null;
+
+ /**
+ * Creates an <code>X509CertSelector</code>. Initially, no criteria are
+ * set so any <code>X509Certificate</code> will match.
+ */
+ public X509CertSelector()
+ {
+ }
+
+ /**
+ * Sets the certificateEquals criterion. The specified
+ * <code>X509Certificate</code> must be equal to the
+ * <code>X509Certificate</code> passed to the match method. If
+ * <code>null</code>, then this check is not applied.<br />
+ * <br />
+ * This method is particularly useful when it is necessary to match a single
+ * certificate. Although other criteria can be specified in conjunction with
+ * the certificateEquals criterion, it is usually not practical or
+ * necessary.
+ *
+ * @param cert
+ * the X509Certificate to match (or <code>null</code>)
+ *
+ * @see #getCertificate()
+ */
+ public void setCertificate(X509Certificate cert)
+ {
+ x509Cert = cert;
+ }
+
+ /**
+ * Sets the serialNumber criterion. The specified serial number must match
+ * the certificate serial number in the <code>X509Certificate</code>. If
+ * <code>null</code>, any certificate serial number will do.
+ *
+ * @param serial
+ * the certificate serial number to match (or <code>null</code>)
+ *
+ * @see #getSerialNumber()
+ */
+ public void setSerialNumber(BigInteger serial)
+ {
+ serialNumber = serial;
+ }
+
+ /**
+ * Sets the issuer criterion. The specified distinguished name must match
+ * the issuer distinguished name in the <code>X509Certificate</code>. If
+ * <code>null</code>, any issuer distinguished name will do.<br />
+ * <br />
+ * If <code>issuerDN</code> is not <code>null</code>, it should contain
+ * a distinguished name, in RFC 2253 format.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the
+ * issuerDN.
+ *
+ * @param issuerDN
+ * a distinguished name in RFC 2253 format (or <code>null</code>)
+ *
+ * @exception IOException
+ * if a parsing error occurs (incorrect form for DN)
+ */
+ public void setIssuer(String issuerDN) throws IOException
+ {
+ if (issuerDN == null)
+ {
+ this.issuerDN = null;
+ this.issuerDNX509 = null;
+ }
+ else
+ {
+ X509Name nameX509;
+ try
+ {
+ nameX509 = new X509Name(issuerDN);
+ }
+ catch (IllegalArgumentException ex)
+ {
+ throw new IOException(ex.getMessage());
+ }
+ this.issuerDNX509 = nameX509;
+ this.issuerDN = issuerDN;
+ }
+ }
+
+ /**
+ * Sets the issuer criterion. The specified distinguished name must match
+ * the issuer distinguished name in the <code>X509Certificate</code>. If
+ * null is specified, the issuer criterion is disabled and any issuer
+ * distinguished name will do.<br />
+ * <br />
+ * If <code>issuerDN</code> is not <code>null</code>, it should contain
+ * a single DER encoded distinguished name, as defined in X.501. The ASN.1
+ * notation for this structure is as follows.<br />
+ * <br />
+ *
+ * <pre>
+ * Name ::= CHOICE {
+ * RDNSequence }
+ *
+ * RDNSequence ::= SEQUENCE OF RDN
+ *
+ * RDN ::=
+ * SET SIZE (1 .. MAX) OF AttributeTypeAndValue
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type AttributeType,
+ * value AttributeValue }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ *
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ * ....
+ * DirectoryString ::= CHOICE {
+ * teletexString TeletexString (SIZE (1..MAX)),
+ * printableString PrintableString (SIZE (1..MAX)),
+ * universalString UniversalString (SIZE (1..MAX)),
+ * utf8String UTF8String (SIZE (1.. MAX)),
+ * bmpString BMPString (SIZE (1..MAX)) }
+ * </pre>
+ *
+ * <br />
+ * <br />
+ * Note that the byte array specified here is cloned to protect against
+ * subsequent modifications.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name}
+ *
+ * @param issuerDN -
+ * a byte array containing the distinguished name in ASN.1 DER
+ * encoded form (or <code>null</code>)
+ *
+ * @exception IOException
+ * if an encoding error occurs (incorrect form for DN)
+ */
+ public void setIssuer(byte[] issuerDN) throws IOException
+ {
+ if (issuerDN == null)
+ {
+ this.issuerDN = null;
+ this.issuerDNX509 = null;
+ }
+ else
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(issuerDN);
+ ASN1InputStream derInStream = new ASN1InputStream(inStream);
+ ASN1Object obj = derInStream.readObject();
+ if (obj instanceof ASN1Sequence)
+ {
+ this.issuerDNX509 = new X509Name((ASN1Sequence)obj);
+ }
+ else
+ {
+ throw new IOException("parsing error");
+ }
+ this.issuerDN = (byte[])issuerDN.clone();
+ }
+ }
+
+ /**
+ * Sets the subject criterion. The specified distinguished name must match
+ * the subject distinguished name in the <code>X509Certificate</code>. If
+ * null, any subject distinguished name will do.<br />
+ * <br />
+ * If <code>subjectDN</code> is not <code>null</code>, it should
+ * contain a distinguished name, in RFC 2253 format.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the
+ * subjectDN.
+ *
+ * @param subjectDN
+ * a distinguished name in RFC 2253 format (or <code>null</code>)
+ *
+ * @exception IOException
+ * if a parsing error occurs (incorrect form for DN)
+ */
+ public void setSubject(String subjectDN) throws IOException
+ {
+ if (subjectDN == null)
+ {
+ this.subjectDN = null;
+ this.subjectDNX509 = null;
+ }
+ else
+ {
+ X509Name nameX509;
+ try
+ {
+ nameX509 = new X509Name(subjectDN);
+ }
+ catch (IllegalArgumentException ex)
+ {
+ throw new IOException(ex.getMessage());
+ }
+
+ this.subjectDNX509 = nameX509;
+ this.subjectDN = subjectDN;
+ }
+ }
+
+ /**
+ * Sets the subject criterion. The specified distinguished name must match
+ * the subject distinguished name in the <code>X509Certificate</code>. If
+ * null, any subject distinguished name will do.<br />
+ * <br />
+ * If <code>subjectDN</code> is not <code>null</code>, it should
+ * contain a single DER encoded distinguished name, as defined in X.501. For
+ * the ASN.1 notation for this structure, see
+ * {@link #setIssuer(byte []) setIssuer(byte [] issuerDN)}.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name}
+ *
+ * @param subjectDN
+ * a byte array containing the distinguished name in ASN.1 DER
+ * format (or <code>null</code>)
+ *
+ * @exception IOException
+ * if an encoding error occurs (incorrect form for DN)
+ */
+ public void setSubject(byte[] subjectDN) throws IOException
+ {
+ if (subjectDN == null)
+ {
+ this.subjectDN = null;
+ this.subjectDNX509 = null;
+ }
+ else
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(subjectDN);
+ ASN1InputStream derInStream = new ASN1InputStream(inStream);
+ ASN1Object obj = derInStream.readObject();
+
+ if (obj instanceof ASN1Sequence)
+ {
+ this.subjectDNX509 = new X509Name((ASN1Sequence)obj);
+ }
+ else
+ {
+ throw new IOException("parsing error");
+ }
+ this.subjectDN = (byte[])subjectDN.clone();
+ }
+ }
+
+ /**
+ * Sets the subjectKeyIdentifier criterion. The <code>X509Certificate</code>
+ * must contain a SubjectKeyIdentifier extension for which the contents of
+ * the extension matches the specified criterion value. If the criterion
+ * value is null, no subjectKeyIdentifier check will be done.<br />
+ * <br />
+ * If <code>subjectKeyID</code> is not <code>null</code>, it should
+ * contain a single DER encoded value corresponding to the contents of the
+ * extension value (not including the object identifier, criticality
+ * setting, and encapsulating OCTET STRING) for a SubjectKeyIdentifier
+ * extension. The ASN.1 notation for this structure follows.<br />
+ * <br />
+ *
+ * <pre>
+ * SubjectKeyIdentifier ::= KeyIdentifier
+ *
+ * KeyIdentifier ::= OCTET STRING
+ * </pre>
+ *
+ * <br />
+ * <br />
+ * Since the format of subject key identifiers is not mandated by any
+ * standard, subject key identifiers are not parsed by the
+ * <code>X509CertSelector</code>. Instead, the values are compared using
+ * a byte-by-byte comparison.<br />
+ * <br />
+ * Note that the byte array supplied here is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param subjectKeyID -
+ * the subject key identifier (or <code>null</code>)
+ *
+ * @see #getSubjectKeyIdentifier()
+ */
+ public void setSubjectKeyIdentifier(byte[] subjectKeyID)
+ {
+ if (subjectKeyID == null)
+ {
+ this.subjectKeyID = null;
+ }
+ else
+ {
+ this.subjectKeyID = (byte[])subjectKeyID.clone();
+ }
+ }
+
+ /**
+ * Sets the authorityKeyIdentifier criterion. The
+ * <code>X509Certificate</code> must contain an AuthorityKeyIdentifier
+ * extension for which the contents of the extension value matches the
+ * specified criterion value. If the criterion value is <code>null</code>,
+ * no authorityKeyIdentifier check will be done.<br />
+ * <br />
+ * If <code>authorityKeyID</code> is not <code>null</code>, it should
+ * contain a single DER encoded value corresponding to the contents of the
+ * extension value (not including the object identifier, criticality
+ * setting, and encapsulating OCTET STRING) for an AuthorityKeyIdentifier
+ * extension. The ASN.1 notation for this structure follows.<br />
+ * <br />
+ *
+ * <pre>
+ * AuthorityKeyIdentifier ::= SEQUENCE {
+ * keyIdentifier [0] KeyIdentifier OPTIONAL,
+ * authorityCertIssuer [1] GeneralNames OPTIONAL,
+ * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
+ *
+ * KeyIdentifier ::= OCTET STRING
+ * </pre>
+ *
+ * <br />
+ * <br />
+ * Authority key identifiers are not parsed by the
+ * <code>X509CertSelector</code>. Instead, the values are compared using
+ * a byte-by-byte comparison.<br />
+ * <br />
+ * When the <code>keyIdentifier</code> field of
+ * <code>AuthorityKeyIdentifier</code> is populated, the value is usually
+ * taken from the SubjectKeyIdentifier extension in the issuer's
+ * certificate. Note, however, that the result of
+ * X509Certificate.getExtensionValue(<SubjectKeyIdentifier Object
+ * Identifier>) on the issuer's certificate may NOT be used directly as the
+ * input to setAuthorityKeyIdentifier. This is because the
+ * SubjectKeyIdentifier contains only a KeyIdentifier OCTET STRING, and not
+ * a SEQUENCE of KeyIdentifier, GeneralNames, and CertificateSerialNumber.
+ * In order to use the extension value of the issuer certificate's
+ * SubjectKeyIdentifier extension, it will be necessary to extract the value
+ * of the embedded KeyIdentifier OCTET STRING, then DER encode this OCTET
+ * STRING inside a SEQUENCE. For more details on SubjectKeyIdentifier, see
+ * {@link #setSubjectKeyIdentifier(byte[]) setSubjectKeyIdentifier(byte[] subjectKeyID }).<br />
+ * <br />
+ * Note also that the byte array supplied here is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param authorityKeyID
+ * the authority key identifier (or <code>null</code>)
+ *
+ * @see #getAuthorityKeyIdentifier()
+ */
+ public void setAuthorityKeyIdentifier(byte[] authorityKeyID)
+ {
+ if (authorityKeyID == null)
+ {
+ this.authorityKeyID = null;
+ }
+ else
+ {
+ this.authorityKeyID = (byte[])authorityKeyID.clone();
+ }
+ }
+
+ /**
+ * Sets the certificateValid criterion. The specified date must fall within
+ * the certificate validity period for the X509Certificate. If
+ * <code>null</code>, no certificateValid check will be done.<br />
+ * <br />
+ * Note that the Date supplied here is cloned to protect against subsequent
+ * modifications.
+ *
+ * @param certValid
+ * the Date to check (or <code>null</code>)
+ *
+ * @see #getCertificateValid()
+ */
+ public void setCertificateValid(Date certValid)
+ {
+ if (certValid == null)
+ {
+ this.certValid = null;
+ }
+ else
+ {
+ this.certValid = new Date(certValid.getTime());
+ }
+ }
+
+ /**
+ * Sets the privateKeyValid criterion. The specified date must fall within
+ * the private key validity period for the X509Certificate. If
+ * <code>null</code>, no privateKeyValid check will be done.<br />
+ * <br />
+ * Note that the Date supplied here is cloned to protect against subsequent
+ * modifications.
+ *
+ * @param privateKeyValid
+ * the Date to check (or <code>null</code>)
+ *
+ * @see #getPrivateKeyValid()
+ */
+ public void setPrivateKeyValid(Date privateKeyValid)
+ {
+ if (privateKeyValid == null)
+ {
+ this.privateKeyValid = null;
+ }
+ else
+ {
+ this.privateKeyValid = new Date(privateKeyValid.getTime());
+ }
+ }
+
+ /**
+ * Sets the subjectPublicKeyAlgID criterion. The X509Certificate must
+ * contain a subject public key with the specified algorithm. If
+ * <code>null</code>, no subjectPublicKeyAlgID check will be done.
+ *
+ * @param oid
+ * The object identifier (OID) of the algorithm to check for (or
+ * <code>null</code>). An OID is represented by a set of
+ * nonnegative integers separated by periods.
+ *
+ * @exception IOException
+ * if the OID is invalid, such as the first component being
+ * not 0, 1 or 2 or the second component being greater than
+ * 39.
+ *
+ * @see #getSubjectPublicKeyAlgID()
+ */
+ public void setSubjectPublicKeyAlgID(String oid) throws IOException
+ {
+ CertUtil.parseOID(oid);
+ subjectKeyAlgID = new ASN1ObjectIdentifier(oid);
+ }
+
+ /**
+ * Sets the subjectPublicKey criterion. The X509Certificate must contain the
+ * specified subject public key. If null, no subjectPublicKey check will be
+ * done.
+ *
+ * @param key
+ * the subject public key to check for (or null)
+ *
+ * @see #getSubjectPublicKey()
+ */
+ public void setSubjectPublicKey(PublicKey key)
+ {
+ if (key == null)
+ {
+ subjectPublicKey = null;
+ subjectPublicKeyByte = null;
+ }
+ else
+ {
+ subjectPublicKey = key;
+ subjectPublicKeyByte = key.getEncoded();
+ }
+ }
+
+ /**
+ * Sets the subjectPublicKey criterion. The <code>X509Certificate</code>
+ * must contain the specified subject public key. If <code>null</code>,
+ * no subjectPublicKey check will be done.<br />
+ * <br />
+ * Because this method allows the public key to be specified as a byte
+ * array, it may be used for unknown key types.<br />
+ * <br />
+ * If key is not <code>null</code>, it should contain a single DER
+ * encoded SubjectPublicKeyInfo structure, as defined in X.509. The ASN.1
+ * notation for this structure is as follows.<br />
+ * <br />
+ *
+ * <pre>
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ * -- contains a value of the type
+ * -- registered for use with the
+ * -- algorithm object identifier value
+ * </pre>
+ *
+ * <br />
+ * <br />
+ * Note that the byte array supplied here is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param key
+ * a byte array containing the subject public key in ASN.1 DER
+ * form (or <code>null</code>)
+ *
+ * @exception IOException
+ * if an encoding error occurs (incorrect form for subject
+ * public key)
+ *
+ * @see #getSubjectPublicKey()
+ */
+ public void setSubjectPublicKey(byte[] key) throws IOException
+ {
+ if (key == null)
+ {
+ subjectPublicKey = null;
+ subjectPublicKeyByte = null;
+ }
+ else
+ {
+ subjectPublicKey = null;
+ subjectPublicKeyByte = (byte[])key.clone();
+ // TODO
+ // try to generyte PublicKey Object from subjectPublicKeyByte
+ }
+ }
+
+ /**
+ * Sets the keyUsage criterion. The X509Certificate must allow the specified
+ * keyUsage values. If null, no keyUsage check will be done. Note that an
+ * X509Certificate that has no keyUsage extension implicitly allows all
+ * keyUsage values.<br />
+ * <br />
+ * Note that the boolean array supplied here is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param keyUsage
+ * a boolean array in the same format as the boolean array
+ * returned by X509Certificate.getKeyUsage(). Or
+ * <code>null</code>.
+ *
+ * @see #getKeyUsage()
+ */
+ public void setKeyUsage(boolean[] keyUsage)
+ {
+ if (keyUsage == null)
+ {
+ this.keyUsage = null;
+ }
+ else
+ {
+ this.keyUsage = (boolean[])keyUsage.clone();
+ }
+ }
+
+ /**
+ * Sets the extendedKeyUsage criterion. The <code>X509Certificate</code>
+ * must allow the specified key purposes in its extended key usage
+ * extension. If <code>keyPurposeSet</code> is empty or <code>null</code>,
+ * no extendedKeyUsage check will be done. Note that an
+ * <code>X509Certificate</code> that has no extendedKeyUsage extension
+ * implicitly allows all key purposes.<br />
+ * <br />
+ * Note that the Set is cloned to protect against subsequent modifications.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.x509.KeyPurposeId KeyPurposeId}
+ *
+ * @param keyPurposeSet
+ * a <code>Set</code> of key purpose OIDs in string format (or
+ * <code>null</code>). Each OID is represented by a set of
+ * nonnegative integers separated by periods.
+ *
+ * @exception IOException
+ * if the OID is invalid, such as the first component being
+ * not 0, 1 or 2 or the second component being greater than
+ * 39.
+ *
+ * @see #getExtendedKeyUsage()
+ */
+ public void setExtendedKeyUsage(Set keyPurposeSet) throws IOException
+ {
+ if (keyPurposeSet == null || keyPurposeSet.isEmpty())
+ {
+ this.keyPurposeSet = keyPurposeSet;
+ }
+ else
+ {
+ this.keyPurposeSet = new HashSet();
+ Iterator iter = keyPurposeSet.iterator();
+ Object obj;
+ KeyPurposeId purposeID;
+ while (iter.hasNext())
+ {
+ obj = iter.next();
+ if (obj instanceof String)
+ {
+ purposeID = (KeyPurposeId)keyPurposeIdMap.get((String)obj);
+ if (purposeID == null)
+ {
+ throw new IOException("unknown purposeID "
+ + (String)obj);
+ }
+ this.keyPurposeSet.add(purposeID);
+ }
+ }
+ }
+ }
+
+ /**
+ * Enables/disables matching all of the subjectAlternativeNames specified in
+ * the {@link #setSubjectAlternativeNames setSubjectAlternativeNames} or
+ * {@link #addSubjectAlternativeName addSubjectAlternativeName} methods. If
+ * enabled, the <code>X509Certificate</code> must contain all of the
+ * specified subject alternative names. If disabled, the X509Certificate
+ * must contain at least one of the specified subject alternative names.<br />
+ * <br />
+ * The matchAllNames flag is <code>true</code> by default.
+ *
+ * @param matchAllNames
+ * if <code>true</code>, the flag is enabled; if
+ * <code>false</code>, the flag is disabled.
+ *
+ * @see #getMatchAllSubjectAltNames()
+ */
+ public void setMatchAllSubjectAltNames(boolean matchAllNames)
+ {
+ matchAllSubjectAltNames = matchAllNames;
+ }
+
+ /**
+ * Sets the subjectAlternativeNames criterion. The
+ * <code>X509Certificate</code> must contain all or at least one of the
+ * specified subjectAlternativeNames, depending on the value of the
+ * matchAllNames flag (see {@link #setMatchAllSubjectAltNames}).<br />
+ * <br />
+ * This method allows the caller to specify, with a single method call, the
+ * complete set of subject alternative names for the subjectAlternativeNames
+ * criterion. The specified value replaces the previous value for the
+ * subjectAlternativeNames criterion.<br />
+ * <br />
+ * The <code>names</code> parameter (if not <code>null</code>) is a
+ * <code>Collection</code> with one entry for each name to be included in
+ * the subject alternative name criterion. Each entry is a <code>List</code>
+ * whose first entry is an <code>Integer</code> (the name type, 0-8) and
+ * whose second entry is a <code>String</code> or a byte array (the name,
+ * in string or ASN.1 DER encoded form, respectively). There can be multiple
+ * names of the same type. If <code>null</code> is supplied as the value
+ * for this argument, no subjectAlternativeNames check will be performed.<br />
+ * <br />
+ * Each subject alternative name in the <code>Collection</code> may be
+ * specified either as a <code>String</code> or as an ASN.1 encoded byte
+ * array. For more details about the formats used, see
+ * {@link #addSubjectAlternativeName(int, String) addSubjectAlternativeName(int type, String name)}
+ * and
+ * {@link #addSubjectAlternativeName(int, byte[]) addSubjectAlternativeName(int type, byte [] name}).<br />
+ * <br />
+ * Note that the <code>names</code> parameter can contain duplicate names
+ * (same name and name type), but they may be removed from the
+ * <code>Collection</code> of names returned by the
+ * {@link #getSubjectAlternativeNames} method.<br />
+ * <br />
+ * Note that a deep copy is performed on the Collection to protect against
+ * subsequent modifications.
+ *
+ * @param names -
+ * a Collection of names (or null)
+ *
+ * @exception IOException
+ * if a parsing error occurs
+ *
+ * @see #getSubjectAlternativeNames()
+ */
+ public void setSubjectAlternativeNames(Collection names) throws IOException
+ {
+ try
+ {
+ if (names == null || names.isEmpty())
+ {
+ subjectAltNames = null;
+ subjectAltNamesByte = null;
+ }
+ else
+ {
+ subjectAltNames = new HashSet();
+ subjectAltNamesByte = new HashSet();
+ Iterator iter = names.iterator();
+ List item;
+ int type;
+ Object data;
+ while (iter.hasNext())
+ {
+ item = (List)iter.next();
+ type = ((Integer)item.get(0)).intValue();
+ data = item.get(1);
+ if (data instanceof String)
+ {
+ addSubjectAlternativeName(type, (String)data);
+ }
+ else if (data instanceof byte[])
+ {
+ addSubjectAlternativeName(type, (byte[])data);
+ }
+ else
+ {
+ throw new IOException(
+ "parsing error: unknown data type");
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new IOException("parsing exception:\n" + ex.toString());
+ }
+ }
+
+ /**
+ * Adds a name to the subjectAlternativeNames criterion. The
+ * <code>X509Certificate</code> must contain all or at least one of the
+ * specified subjectAlternativeNames, depending on the value of the
+ * matchAllNames flag (see {@link #setMatchAllSubjectAltNames}).<br />
+ * <br />
+ * This method allows the caller to add a name to the set of subject
+ * alternative names. The specified name is added to any previous value for
+ * the subjectAlternativeNames criterion. If the specified name is a
+ * duplicate, it may be ignored.<br />
+ * <br />
+ * The name is provided in string format. RFC 822, DNS, and URI names use
+ * the well-established string formats for those types (subject to the
+ * restrictions included in RFC 2459). IPv4 address names are supplied using
+ * dotted quad notation. OID address names are represented as a series of
+ * nonnegative integers separated by periods. And directory names
+ * (distinguished names) are supplied in RFC 2253 format. No standard string
+ * format is defined for otherNames, X.400 names, EDI party names, IPv6
+ * address names, or any other type of names. They should be specified using
+ * the
+ * {@link #addSubjectAlternativeName(int, byte[]) addSubjectAlternativeName(int type, byte [] name)}
+ * method.
+ *
+ * @param type
+ * the name type (0-8, as specified in RFC 2459, section 4.2.1.7)
+ * @param name -
+ * the name in string form (not null)
+ *
+ * @exception IOException
+ * if a parsing error occurs
+ */
+ public void addSubjectAlternativeName(int type, String name)
+ throws IOException
+ {
+ // TODO full implementation of CertUtil.parseGeneralName
+ byte[] encoded = CertUtil.parseGeneralName(type, name);
+ List tmpList = new ArrayList();
+ tmpList.add(Integers.valueOf(type));
+ tmpList.add(name);
+ subjectAltNames.add(tmpList);
+ tmpList.set(1, encoded);
+ subjectAltNamesByte.add(tmpList);
+ }
+
+ /**
+ * Adds a name to the subjectAlternativeNames criterion. The
+ * <code>X509Certificate</code> must contain all or at least one of the
+ * specified subjectAlternativeNames, depending on the value of the
+ * matchAllNames flag (see {@link #setMatchAllSubjectAltNames}).<br />
+ * <br />
+ * This method allows the caller to add a name to the set of subject
+ * alternative names. The specified name is added to any previous value for
+ * the subjectAlternativeNames criterion. If the specified name is a
+ * duplicate, it may be ignored.<br />
+ * <br />
+ * The name is provided as a byte array. This byte array should contain the
+ * DER encoded name, as it would appear in the GeneralName structure defined
+ * in RFC 2459 and X.509. The encoded byte array should only contain the
+ * encoded value of the name, and should not include the tag associated with
+ * the name in the GeneralName structure. The ASN.1 definition of this
+ * structure appears below.<br />
+ * <br />
+ *
+ * <pre>
+ * GeneralName ::= CHOICE {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER}
+ * </pre>
+ *
+ * <br />
+ * <br />
+ * Note that the byte array supplied here is cloned to protect against
+ * subsequent modifications.<br />
+ * <br />
+ * <b>TODO: check encoded format</b>
+ *
+ * @param type
+ * the name type (0-8, as listed above)
+ * @param name
+ * a byte array containing the name in ASN.1 DER encoded form
+ *
+ * @exception IOException
+ * if a parsing error occurs
+ */
+ public void addSubjectAlternativeName(int type, byte[] name)
+ throws IOException
+ {
+ // TODO check encoded format
+ List tmpList = new ArrayList();
+ tmpList.add(Integers.valueOf(type));
+ tmpList.add(name.clone());
+ subjectAltNames.add(tmpList);
+ subjectAltNamesByte.add(tmpList);
+ }
+
+ /**
+ * Sets the name constraints criterion. The <code>X509Certificate</code>
+ * must have subject and subject alternative names that meet the specified
+ * name constraints.<br />
+ * <br />
+ * 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.<br />
+ * <br />
+ *
+ * <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>
+ *
+ * <br />
+ * <br />
+ * Note that the byte array supplied here is cloned to protect against
+ * subsequent modifications.<br />
+ * <br />
+ * <b>TODO: implement this</b>
+ *
+ * @param bytes
+ * 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. Can be <code>null</code>, in
+ * which case no name constraints check will be performed
+ *
+ * @exception IOException
+ * if a parsing error occurs
+ * @exception UnsupportedOperationException
+ * because this method is not supported
+ * @see #getNameConstraints()
+ */
+ public void setNameConstraints(byte[] bytes) throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Sets the basic constraints constraint. If the value is greater than or
+ * equal to zero, <code>X509Certificates</code> must include a
+ * basicConstraints extension with a pathLen of at least this value. If the
+ * value is -2, only end-entity certificates are accepted. If the value is
+ * -1, no check is done.<br />
+ * <br />
+ * This constraint is useful when building a certification path forward
+ * (from the target toward the trust anchor. If a partial path has been
+ * built, any candidate certificate must have a maxPathLen value greater
+ * than or equal to the number of certificates in the partial path.
+ *
+ * @param minMaxPathLen
+ * the value for the basic constraints constraint
+ *
+ * @exception IllegalArgumentException
+ * if the value is less than -2
+ *
+ * @see #getBasicConstraints()
+ */
+ public void setBasicConstraints(int minMaxPathLen)
+ {
+ if (minMaxPathLen < -2)
+ {
+ throw new IllegalArgumentException("minMaxPathLen must be >= -2");
+ }
+
+ this.minMaxPathLen = minMaxPathLen;
+ }
+
+ /**
+ * Sets the policy constraint. The X509Certificate must include at least one
+ * of the specified policies in its certificate policies extension. If
+ * certPolicySet is empty, then the X509Certificate must include at least
+ * some specified policy in its certificate policies extension. If
+ * certPolicySet is null, no policy check will be performed.<br />
+ * <br />
+ * Note that the Set is cloned to protect against subsequent modifications.<br />
+ * <br />
+ * <b>TODO: implement match check for this</b>
+ *
+ * @param certPolicySet
+ * a Set of certificate policy OIDs in string format (or null).
+ * Each OID is represented by a set of nonnegative integers
+ * separated by periods.
+ *
+ * @exception IOException
+ * if a parsing error occurs on the OID such as the first
+ * component is not 0, 1 or 2 or the second component is
+ * greater than 39.
+ *
+ * @see #getPolicy()
+ */
+ public void setPolicy(Set certPolicySet) throws IOException
+ {
+ if (certPolicySet == null)
+ {
+ policy = null;
+ policyOID = null;
+ }
+ else
+ {
+ policyOID = new HashSet();
+ Iterator iter = certPolicySet.iterator();
+ Object item;
+ while (iter.hasNext())
+ {
+ item = iter.next();
+ if (item instanceof String)
+ {
+ CertUtil.parseOID((String)item);
+ policyOID.add(new ASN1ObjectIdentifier((String)item));
+ }
+ else
+ {
+ throw new IOException(
+ "certPolicySet contains null values or non String objects");
+ }
+ }
+ policy = new HashSet(certPolicySet);
+ }
+ }
+
+ /**
+ * Sets the pathToNames criterion. The <code>X509Certificate</code> must
+ * not include name constraints that would prohibit building a path to the
+ * specified names.<br />
+ * <br />
+ * This method allows the caller to specify, with a single method call, the
+ * complete set of names which the <code>X509Certificates</code>'s name
+ * constraints must permit. The specified value replaces the previous value
+ * for the pathToNames criterion.<br />
+ * <br />
+ * This constraint is useful when building a certification path forward
+ * (from the target toward the trust anchor. If a partial path has been
+ * built, any candidate certificate must not include name constraints that
+ * would prohibit building a path to any of the names in the partial path.<br />
+ * <br />
+ * The names parameter (if not <code>null</code>) is a
+ * <code>Collection</code> with one entry for each name to be included in
+ * the pathToNames criterion. Each entry is a <code>List</code> whose
+ * first entry is an Integer (the name type, 0-8) and whose second entry is
+ * a <code>String</code> or a byte array (the name, in string or ASN.1 DER
+ * encoded form, respectively). There can be multiple names of the same
+ * type. If <code>null</code> is supplied as the value for this argument,
+ * no pathToNames check will be performed.<br />
+ * <br />
+ * Each name in the Collection may be specified either as a String or as an
+ * ASN.1 encoded byte array. For more details about the formats used, see
+ * {@link #addPathToName(int, String) addPathToName(int type, String name)}
+ * and
+ * {@link #addPathToName(int, byte[]) addPathToName(int type, byte [] name)}.<br />
+ * <br />
+ * Note that the names parameter can contain duplicate names (same name and
+ * name type), but they may be removed from the Collection of names returned
+ * by the {@link #getPathToNames} method.<br />
+ * <br />
+ * Note that a deep copy is performed on the Collection to protect against
+ * subsequent modifications.<br />
+ * <br />
+ * <b>TODO: implement this match check for this</b>
+ *
+ * @param names
+ * a Collection with one entry per name (or <code>null</code>)
+ *
+ * @exception IOException
+ * if a parsing error occurs
+ * @exception UnsupportedOperationException
+ * because this method is not supported
+ *
+ * @see #getPathToNames()
+ */
+ public void setPathToNames(Collection names) throws IOException
+ {
+ try
+ {
+ if (names == null || names.isEmpty())
+ {
+ pathToNames = null;
+ pathToNamesByte = null;
+ }
+ else
+ {
+ pathToNames = new HashSet();
+ pathToNamesByte = new HashSet();
+ Iterator iter = names.iterator();
+ List item;
+ int type;
+ Object data;
+
+ while (iter.hasNext())
+ {
+ item = (List)iter.next();
+ type = ((Integer)item.get(0)).intValue();
+ data = item.get(1);
+ if (data instanceof String)
+ {
+ addPathToName(type, (String)data);
+ }
+ else if (data instanceof byte[])
+ {
+ addPathToName(type, (byte[])data);
+ }
+ else
+ {
+ throw new IOException(
+ "parsing error: unknown data type");
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new IOException("parsing exception:\n" + ex.toString());
+ }
+ }
+
+ /**
+ * Adds a name to the pathToNames criterion. The
+ * <code>X509Certificate</code> must not include name constraints that
+ * would prohibit building a path to the specified name.<br />
+ * <br />
+ * This method allows the caller to add a name to the set of names which the
+ * <code>X509Certificates</code>'s name constraints must permit. The
+ * specified name is added to any previous value for the pathToNames
+ * criterion. If the name is a duplicate, it may be ignored.<br />
+ * <br />
+ * The name is provided in string format. RFC 822, DNS, and URI names use
+ * the well-established string formats for those types (subject to the
+ * restrictions included in RFC 2459). IPv4 address names are supplied using
+ * dotted quad notation. OID address names are represented as a series of
+ * nonnegative integers separated by periods. And directory names
+ * (distinguished names) are supplied in RFC 2253 format. No standard string
+ * format is defined for otherNames, X.400 names, EDI party names, IPv6
+ * address names, or any other type of names. They should be specified using
+ * the
+ * {@link #addPathToName(int, byte[]) addPathToName(int type, byte [] name)}
+ * method.<br />
+ * <br />
+ * <b>TODO: implement this match check for this</b>
+ *
+ * @param type
+ * the name type (0-8, as specified in RFC 2459, section 4.2.1.7)
+ * @param name
+ * the name in string form
+ *
+ * @exceptrion IOException if a parsing error occurs
+ */
+ public void addPathToName(int type, String name) throws IOException
+ {
+ // TODO full implementation of CertUtil.parseGeneralName
+ byte[] encoded = CertUtil.parseGeneralName(type, name);
+ List tmpList = new ArrayList();
+ tmpList.add(Integers.valueOf(type));
+ tmpList.add(name);
+ pathToNames.add(tmpList);
+ tmpList.set(1, encoded);
+ pathToNamesByte.add(tmpList);
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Adds a name to the pathToNames criterion. The
+ * <code>X509Certificate</code> must not include name constraints that
+ * would prohibit building a path to the specified name.<br />
+ * <br />
+ * This method allows the caller to add a name to the set of names which the
+ * <code>X509Certificates</code>'s name constraints must permit. The
+ * specified name is added to any previous value for the pathToNames
+ * criterion. If the name is a duplicate, it may be ignored.<br />
+ * <br />
+ * The name is provided as a byte array. This byte array should contain the
+ * DER encoded name, as it would appear in the GeneralName structure defined
+ * in RFC 2459 and X.509. The ASN.1 definition of this structure appears in
+ * the documentation for
+ * {@link #addSubjectAlternativeName(int,byte[]) addSubjectAlternativeName(int type, byte[] name)}.<br />
+ * <br />
+ * Note that the byte array supplied here is cloned to protect against
+ * subsequent modifications.<br />
+ * <br />
+ * <b>TODO: implement this match check for this</b>
+ *
+ * @param type
+ * the name type (0-8, as specified in RFC 2459, section 4.2.1.7)
+ * @param name
+ * a byte array containing the name in ASN.1 DER encoded form
+ *
+ * @exception IOException
+ * if a parsing error occurs
+ */
+ public void addPathToName(int type, byte[] name) throws IOException
+ {
+ // TODO check encoded format
+ List tmpList = new ArrayList();
+ tmpList.add(Integers.valueOf(type));
+ tmpList.add(name.clone());
+ pathToNames.add(tmpList);
+ pathToNamesByte.add(tmpList);
+ }
+
+ /**
+ * Returns the certificateEquals criterion. The specified
+ * <code>X509Certificate</code> must be equal to the
+ * <code>X509Certificate</code> passed to the match method. If
+ * <code>null</code>, this check is not applied.
+ *
+ * @retrun the <code>X509Certificate</code> to match (or <code>null</code>)
+ *
+ * @see #setCertificate(java.security.cert.X509Certificate)
+ */
+ public X509Certificate getCertificate()
+ {
+ return x509Cert;
+ }
+
+ /**
+ * Returns the serialNumber criterion. The specified serial number must
+ * match the certificate serial number in the <code>X509Certificate</code>.
+ * If <code>null</code>, any certificate serial number will do.
+ *
+ * @return the certificate serial number to match (or <code>null</code>)
+ *
+ * @see #setSerialNumber(java.math.BigInteger)
+ */
+ public BigInteger getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ /**
+ * Returns the issuer criterion as a String. This distinguished name must
+ * match the issuer distinguished name in the <code>X509Certificate</code>.
+ * If <code>null</code>, the issuer criterion is disabled and any issuer
+ * distinguished name will do.<br />
+ * <br />
+ * If the value returned is not <code>null</code>, it is a distinguished
+ * name, in RFC 2253 format.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for formatiing
+ * byte[] issuerDN to String.
+ *
+ * @return the required issuer distinguished name in RFC 2253 format (or
+ * <code>null</code>)
+ */
+ public String getIssuerAsString()
+ {
+ if (issuerDN instanceof String)
+ {
+ return new String((String)issuerDN);
+ }
+ else if (issuerDNX509 != null)
+ {
+ return issuerDNX509.toString();
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the issuer criterion as a byte array. This distinguished name
+ * must match the issuer distinguished name in the
+ * <code>X509Certificate</code>. If <code>null</code>, the issuer
+ * criterion is disabled and any issuer distinguished name will do.<br />
+ * <br />
+ * If the value returned is not <code>null</code>, it is a byte array
+ * containing a single DER encoded distinguished name, as defined in X.501.
+ * The ASN.1 notation for this structure is supplied in the documentation
+ * for {@link #setIssuer(byte[]) setIssuer(byte [] issuerDN)}.<br />
+ * <br />
+ * Note that the byte array returned is cloned to protect against subsequent
+ * modifications.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.DEROutputStream DEROutputStream},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name} to gnerate byte[]
+ * output for String issuerDN.
+ *
+ * @return a byte array containing the required issuer distinguished name in
+ * ASN.1 DER format (or <code>null</code>)
+ *
+ * @exception IOException
+ * if an encoding error occurs
+ */
+ public byte[] getIssuerAsBytes() throws IOException
+ {
+ if (issuerDN instanceof byte[])
+ {
+ return (byte[])((byte[])issuerDN).clone();
+ }
+ else if (issuerDNX509 != null)
+ {
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ DEROutputStream derOutStream = new DEROutputStream(outStream);
+
+ derOutStream.writeObject(issuerDNX509.toASN1Primitive());
+ derOutStream.close();
+
+ return outStream.toByteArray();
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the subject criterion as a String. This distinguished name must
+ * match the subject distinguished name in the <code>X509Certificate</code>.
+ * If <code>null</code>, the subject criterion is disabled and any
+ * subject distinguished name will do.<br />
+ * <br />
+ * If the value returned is not <code>null</code>, it is a distinguished
+ * name, in RFC 2253 format.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for formatiing
+ * byte[] subjectDN to String.
+ *
+ * @return the required subject distinguished name in RFC 2253 format (or
+ * <code>null</code>)
+ */
+ public String getSubjectAsString()
+ {
+ if (subjectDN instanceof String)
+ {
+ return new String((String)subjectDN);
+ }
+ else if (subjectDNX509 != null)
+ {
+ return subjectDNX509.toString();
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the subject criterion as a byte array. This distinguished name
+ * must match the subject distinguished name in the
+ * <code>X509Certificate</code>. If <code>null</code>, the subject
+ * criterion is disabled and any subject distinguished name will do.<br />
+ * <br />
+ * If the value returned is not <code>null</code>, it is a byte array
+ * containing a single DER encoded distinguished name, as defined in X.501.
+ * The ASN.1 notation for this structure is supplied in the documentation
+ * for {@link #setSubject(byte [] subjectDN) setSubject(byte [] subjectDN)}.<br />
+ * <br />
+ * Note that the byte array returned is cloned to protect against subsequent
+ * modifications.<br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.DEROutputStream DEROutputStream},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name} to gnerate byte[]
+ * output for String subjectDN.
+ *
+ * @return a byte array containing the required subject distinguished name
+ * in ASN.1 DER format (or <code>null</code>)
+ *
+ * @exception IOException
+ * if an encoding error occurs
+ */
+ public byte[] getSubjectAsBytes() throws IOException
+ {
+ if (subjectDN instanceof byte[])
+ {
+ return (byte[])((byte[])subjectDN).clone();
+ }
+ else if (subjectDNX509 != null)
+ {
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ DEROutputStream derOutStream = new DEROutputStream(outStream);
+
+ derOutStream.writeObject(subjectDNX509.toASN1Primitive());
+ derOutStream.close();
+
+ return outStream.toByteArray();
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the subjectKeyIdentifier criterion. The
+ * <code>X509Certificate</code> must contain a SubjectKeyIdentifier
+ * extension with the specified value. If <code>null</code>, no
+ * subjectKeyIdentifier check will be done.<br />
+ * <br />
+ * Note that the byte array returned is cloned to protect against subsequent
+ * modifications.
+ *
+ * @return the key identifier (or <code>null</code>)
+ *
+ * @see #setSubjectKeyIdentifier
+ */
+ public byte[] getSubjectKeyIdentifier()
+ {
+ if (subjectKeyID != null)
+ {
+ return (byte[])subjectKeyID.clone();
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the authorityKeyIdentifier criterion. The
+ * <code>X509Certificate</code> must contain a AuthorityKeyIdentifier
+ * extension with the specified value. If <code>null</code>, no
+ * authorityKeyIdentifier check will be done.<br />
+ * <br />
+ * Note that the byte array returned is cloned to protect against subsequent
+ * modifications.
+ *
+ * @return the key identifier (or <code>null</code>)
+ *
+ * @see #setAuthorityKeyIdentifier
+ */
+ public byte[] getAuthorityKeyIdentifier()
+ {
+ if (authorityKeyID != null)
+ {
+ return (byte[])authorityKeyID.clone();
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the certificateValid criterion. The specified date must fall
+ * within the certificate validity period for the
+ * <code>X509Certificate</code>. If <code>null</code>, no
+ * certificateValid check will be done.<br />
+ * <br />
+ * Note that the <code>Date</code> returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return the <code>Date</code> to check (or <code>null</code>)
+ *
+ * @see #setCertificateValid
+ */
+ public Date getCertificateValid()
+ {
+ if (certValid != null)
+ {
+ return new Date(certValid.getTime());
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the privateKeyValid criterion. The specified date must fall
+ * within the private key validity period for the
+ * <code>X509Certificate</code>. If <code>null</code>, no
+ * privateKeyValid check will be done.<br />
+ * <br />
+ * Note that the <code>Date</code> returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return the <code>Date</code> to check (or <code>null</code>)
+ *
+ * @see #setPrivateKeyValid
+ */
+ public Date getPrivateKeyValid()
+ {
+ if (privateKeyValid != null)
+ {
+ return new Date(privateKeyValid.getTime());
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the subjectPublicKeyAlgID criterion. The
+ * <code>X509Certificate</code> must contain a subject public key with the
+ * specified algorithm. If <code>null</code>, no subjectPublicKeyAlgID
+ * check will be done.
+ *
+ * @return the object identifier (OID) of the signature algorithm to check
+ * for (or <code>null</code>). An OID is represented by a set of
+ * nonnegative integers separated by periods.
+ *
+ * @see #setSubjectPublicKeyAlgID
+ */
+ public String getSubjectPublicKeyAlgID()
+ {
+ if (subjectKeyAlgID != null)
+ {
+ return subjectKeyAlgID.toString();
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the subjectPublicKey criterion. The <code>X509Certificate</code>
+ * must contain the specified subject public key. If <code>null</code>,
+ * no subjectPublicKey check will be done.
+ *
+ * @return the subject public key to check for (or <code>null</code>)
+ *
+ * @see #setSubjectPublicKey
+ */
+ public PublicKey getSubjectPublicKey()
+ {
+ return subjectPublicKey;
+ }
+
+ /**
+ * Returns the keyUsage criterion. The <code>X509Certificate</code> must
+ * allow the specified keyUsage values. If null, no keyUsage check will be
+ * done.<br />
+ * <br />
+ * Note that the boolean array returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return a boolean array in the same format as the boolean array returned
+ * by
+ * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
+ * Or <code>null</code>.
+ *
+ * @see #setKeyUsage
+ */
+ public boolean[] getKeyUsage()
+ {
+ if (keyUsage != null)
+ {
+ return (boolean[])keyUsage.clone();
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the extendedKeyUsage criterion. The <code>X509Certificate</code>
+ * must allow the specified key purposes in its extended key usage
+ * extension. If the <code>keyPurposeSet</code> returned is empty or
+ * <code>null</code>, no extendedKeyUsage check will be done. Note that
+ * an <code>X509Certificate</code> that has no extendedKeyUsage extension
+ * implicitly allows all key purposes.
+ *
+ * @return an immutable <code>Set</code> of key purpose OIDs in string
+ * format (or <code>null</code>)
+ * @see #setExtendedKeyUsage
+ */
+ public Set getExtendedKeyUsage()
+ {
+ if (keyPurposeSet == null || keyPurposeSet.isEmpty())
+ {
+ return keyPurposeSet;
+ }
+
+ Set returnSet = new HashSet();
+ Iterator iter = keyPurposeSet.iterator();
+ while (iter.hasNext())
+ {
+ returnSet.add(iter.next().toString());
+ }
+
+ return Collections.unmodifiableSet(returnSet);
+ }
+
+ /**
+ * Indicates if the <code>X509Certificate</code> must contain all or at
+ * least one of the subjectAlternativeNames specified in the
+ * {@link #setSubjectAlternativeNames setSubjectAlternativeNames} or
+ * {@link #addSubjectAlternativeName addSubjectAlternativeName} methods. If
+ * <code>true</code>, the <code>X509Certificate</code> must contain all
+ * of the specified subject alternative names. If <code>false</code>, the
+ * <code>X509Certificate</code> must contain at least one of the specified
+ * subject alternative names.
+ *
+ * @return <code>true</code> if the flag is enabled; <code>false</code>
+ * if the flag is disabled. The flag is <code>true</code> by
+ * default.
+ *
+ * @see #setMatchAllSubjectAltNames
+ */
+ public boolean getMatchAllSubjectAltNames()
+ {
+ return matchAllSubjectAltNames;
+ }
+
+ /**
+ * Returns a copy of the subjectAlternativeNames criterion. The
+ * <code>X509Certificate</code> must contain all or at least one of the
+ * specified subjectAlternativeNames, depending on the value of the
+ * matchAllNames flag (see {@link #getMatchAllSubjectAltNames
+ * getMatchAllSubjectAltNames}). If the value returned is <code>null</code>,
+ * no subjectAlternativeNames check will be performed.<br />
+ * <br />
+ * If the value returned is not <code>null</code>, it is a
+ * <code>Collection</code> with one entry for each name to be included in
+ * the subject alternative name criterion. Each entry is a <code>List</code>
+ * whose first entry is an <code>Integer</code> (the name type, 0-8) and
+ * whose second entry is a <code>String</code> or a byte array (the name,
+ * in string or ASN.1 DER encoded form, respectively). There can be multiple
+ * names of the same type. Note that the <code>Collection</code> returned
+ * may contain duplicate names (same name and name type).<br />
+ * <br />
+ * Each subject alternative name in the <code>Collection</code> may be
+ * specified either as a <code>String</code> or as an ASN.1 encoded byte
+ * array. For more details about the formats used, see
+ * {@link #addSubjectAlternativeName(int type, String name)
+ * addSubjectAlternativeName(int type, String name)} and
+ * {@link #addSubjectAlternativeName(int type, byte [] name)
+ * addSubjectAlternativeName(int type, byte [] name)}.<br />
+ * <br />
+ * Note that a deep copy is performed on the <code>Collection</code> to
+ * protect against subsequent modifications.
+ *
+ * @return a <code>Collection</code> of names (or <code>null</code>)
+ *
+ * @see #setSubjectAlternativeNames
+ */
+ public Collection getSubjectAlternativeNames()
+ {
+ if (subjectAltNames != null)
+ {
+ return null;
+ }
+
+ Set returnAltNames = new HashSet();
+ List returnList;
+ Iterator iter = subjectAltNames.iterator();
+ List obj;
+ while (iter.hasNext())
+ {
+ obj = (List)iter.next();
+ returnList = new ArrayList();
+ returnList.add(obj.get(0));
+ if (obj.get(1) instanceof byte[])
+ {
+ returnList.add(((byte[])obj.get(1)).clone());
+ }
+ else
+ {
+ returnList.add(obj.get(1));
+ }
+ returnAltNames.add(returnList);
+ }
+
+ return returnAltNames;
+ }
+
+ /**
+ * Returns the name constraints criterion. The <code>X509Certificate</code>
+ * must have subject and subject alternative names that meet the specified
+ * name constraints.<br />
+ * <br />
+ * The name constraints are returned 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
+ * {@link #setNameConstraints(byte [] bytes) setNameConstraints(byte [] bytes)}.<br />
+ * <br />
+ * Note that the byte array returned is cloned to protect against subsequent
+ * modifications.<br />
+ * <br />
+ * <b>TODO: implement this</b>
+ *
+ * @return a byte array containing the ASN.1 DER encoding of a
+ * NameConstraints extension used for checking name constraints.
+ * <code>null</code> if no name constraints check will be
+ * performed.
+ *
+ * @exception UnsupportedOperationException
+ * because this method is not supported
+ *
+ * @see #setNameConstraints
+ */
+ public byte[] getNameConstraints()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the basic constraints constraint. If the value is greater than or
+ * equal to zero, the <code>X509Certificates</code> must include a
+ * basicConstraints extension with a pathLen of at least this value. If the
+ * value is -2, only end-entity certificates are accepted. If the value is
+ * -1, no basicConstraints check is done.
+ *
+ * @return the value for the basic constraints constraint
+ *
+ * @see #setBasicConstraints
+ */
+ public int getBasicConstraints()
+ {
+ return minMaxPathLen;
+ }
+
+ /**
+ * Returns the policy criterion. The <code>X509Certificate</code> must
+ * include at least one of the specified policies in its certificate
+ * policies extension. If the <code>Set</code> returned is empty, then the
+ * <code>X509Certificate</code> must include at least some specified
+ * policy in its certificate policies extension. If the <code>Set</code>
+ * returned is <code>null</code>, no policy check will be performed.
+ *
+ * @return an immutable <code>Set</code> of certificate policy OIDs in
+ * string format (or <code>null</code>)
+ *
+ * @see #setPolicy
+ */
+ public Set getPolicy()
+ {
+ if (policy == null)
+ {
+ return null;
+ }
+
+ return Collections.unmodifiableSet(policy);
+ }
+
+ /**
+ * Returns a copy of the pathToNames criterion. The
+ * <code>X509Certificate</code> must not include name constraints that
+ * would prohibit building a path to the specified names. If the value
+ * returned is <code>null</code>, no pathToNames check will be performed.<br />
+ * <br />
+ * If the value returned is not <code>null</code>, it is a
+ * <code>Collection</code> with one entry for each name to be included in
+ * the pathToNames criterion. Each entry is a <code>List</code> whose
+ * first entry is an <code>Integer</code> (the name type, 0-8) and whose
+ * second entry is a <code>String</code> or a byte array (the name, in
+ * string or ASN.1 DER encoded form, respectively). There can be multiple
+ * names of the same type. Note that the <code>Collection</code> returned
+ * may contain duplicate names (same name and name type).<br />
+ * <br />
+ * Each name in the <code>Collection</code> may be specified either as a
+ * <code>String</code> or as an ASN.1 encoded byte array. For more details
+ * about the formats used, see {@link #addPathToName(int type, String name)
+ * addPathToName(int type, String name)} and
+ * {@link #addPathToName(int type, byte [] name) addPathToName(int type,
+ * byte [] name)}.<br />
+ * <br />
+ * Note that a deep copy is performed on the <code>Collection</code> to
+ * protect against subsequent modifications.
+ *
+ * @return a <code>Collection</code> of names (or <code>null</code>)
+ *
+ * @see #setPathToNames
+ */
+ public Collection getPathToNames()
+ {
+ if (pathToNames == null)
+ {
+ return null;
+ }
+
+ Set returnPathToNames = new HashSet();
+ List returnList;
+ Iterator iter = pathToNames.iterator();
+ List obj;
+
+ while (iter.hasNext())
+ {
+ obj = (List)iter.next();
+ returnList = new ArrayList();
+ returnList.add(obj.get(0));
+ if (obj.get(1) instanceof byte[])
+ {
+ returnList.add(((byte[])obj.get(1)).clone());
+ }
+ else
+ {
+ returnList.add(obj.get(1));
+ }
+ returnPathToNames.add(returnList);
+ }
+
+ return returnPathToNames;
+ }
+
+ /**
+ * Return a printable representation of the <code>CertSelector</code>.<br />
+ * <br />
+ * <b>TODO: implement output for currently unsupported options(name
+ * constraints)</b><br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object},
+ * {@link org.spongycastle.asn1.x509.KeyPurposeId KeyPurposeId}
+ *
+ * @return a <code>String</code> describing the contents of the
+ * <code>CertSelector</code>
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("X509CertSelector: [\n");
+ if (x509Cert != null)
+ {
+ sb.append(" Certificate: ").append(x509Cert).append('\n');
+ }
+ if (serialNumber != null)
+ {
+ sb.append(" Serial Number: ").append(serialNumber).append('\n');
+ }
+ if (issuerDN != null)
+ {
+ sb.append(" Issuer: ").append(getIssuerAsString()).append('\n');
+ }
+ if (subjectDN != null)
+ {
+ sb.append(" Subject: ").append(getSubjectAsString()).append('\n');
+ }
+ try
+ {
+ if (subjectKeyID != null)
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(
+ subjectKeyID);
+ ASN1InputStream derInStream = new ASN1InputStream(inStream);
+ ASN1Object derObject = derInStream.readObject();
+ sb.append(" Subject Key Identifier: ")
+ .append(ASN1Dump.dumpAsString(derObject)).append('\n');
+ }
+ if (authorityKeyID != null)
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(
+ authorityKeyID);
+ ASN1InputStream derInStream = new ASN1InputStream(inStream);
+ ASN1Object derObject = derInStream.readObject();
+ sb.append(" Authority Key Identifier: ")
+ .append(ASN1Dump.dumpAsString(derObject)).append('\n');
+ }
+ }
+ catch (IOException ex)
+ {
+ sb.append(ex.getMessage()).append('\n');
+ }
+ if (certValid != null)
+ {
+ sb.append(" Certificate Valid: ").append(certValid).append('\n');
+ }
+ if (privateKeyValid != null)
+ {
+ sb.append(" Private Key Valid: ").append(privateKeyValid)
+ .append('\n');
+ }
+ if (subjectKeyAlgID != null)
+ {
+ sb.append(" Subject Public Key AlgID: ")
+ .append(subjectKeyAlgID).append('\n');
+ }
+ if (subjectPublicKey != null)
+ {
+ sb.append(" Subject Public Key: ").append(subjectPublicKey)
+ .append('\n');
+ }
+ if (keyUsage != null)
+ {
+ sb.append(" Key Usage: ").append(keyUsage).append('\n');
+ }
+ if (keyPurposeSet != null)
+ {
+ sb.append(" Extended Key Usage: ").append(keyPurposeSet)
+ .append('\n');
+ }
+ if (policy != null)
+ {
+ sb.append(" Policy: ").append(policy).append('\n');
+ }
+ sb.append(" matchAllSubjectAltNames flag: ")
+ .append(matchAllSubjectAltNames).append('\n');
+ if (subjectAltNamesByte != null)
+ {
+ sb.append(" SubjectAlternativNames: \n[");
+ Iterator iter = subjectAltNamesByte.iterator();
+ List obj;
+ try
+ {
+ while (iter.hasNext())
+ {
+ obj = (List)iter.next();
+ ByteArrayInputStream inStream = new ByteArrayInputStream(
+ (byte[])obj.get(1));
+ ASN1InputStream derInStream = new ASN1InputStream(inStream);
+ ASN1Object derObject = derInStream.readObject();
+ sb.append(" Type: ").append(obj.get(0)).append(" Data: ")
+ .append(ASN1Dump.dumpAsString(derObject)).append('\n');
+ }
+ }
+ catch (IOException ex)
+ {
+ sb.append(ex.getMessage()).append('\n');
+ }
+ sb.append("]\n");
+ }
+ if (pathToNamesByte != null)
+ {
+ sb.append(" PathToNamesNames: \n[");
+ Iterator iter = pathToNamesByte.iterator();
+ List obj;
+ try
+ {
+ while (iter.hasNext())
+ {
+ obj = (List)iter.next();
+ ByteArrayInputStream inStream = new ByteArrayInputStream(
+ (byte[])obj.get(1));
+ ASN1InputStream derInStream = new ASN1InputStream(inStream);
+ ASN1Object derObject = derInStream.readObject();
+ sb.append(" Type: ").append(obj.get(0)).append(" Data: ")
+ .append(ASN1Dump.dumpAsString(derObject)).append('\n');
+ }
+ }
+ catch (IOException ex)
+ {
+ sb.append(ex.getMessage()).append('\n');
+ }
+ sb.append("]\n");
+ }
+ sb.append(']');
+ return sb.toString();
+ }
+
+ /**
+ * Decides whether a <code>Certificate</code> should be selected.<br />
+ * <br />
+ * <b>TODO: implement missing tests (name constraints and path to names)</b><br />
+ * <br />
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object},
+ * {@link org.spongycastle.asn1.DERGeneralizedTime DERGeneralizedTime},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name},
+ * {@link org.spongycastle.asn1.x509.X509Extensions X509Extensions},
+ * {@link org.spongycastle.asn1.x509.ExtendedKeyUsage ExtendedKeyUsage},
+ * {@link org.spongycastle.asn1.x509.KeyPurposeId KeyPurposeId},
+ * {@link org.spongycastle.asn1.x509.SubjectPublicKeyInfo SubjectPublicKeyInfo},
+ * {@link org.spongycastle.asn1.x509.AlgorithmIdentifier AlgorithmIdentifier}
+ * to access X509 extensions
+ *
+ * @param cert
+ * the <code>Certificate</code> to be checked
+ *
+ * @return <code>true</code> if the <code>Certificate</code> should be
+ * selected, <code>false</code> otherwise
+ */
+ public boolean match(Certificate cert)
+ {
+ boolean[] booleanArray;
+ List tempList;
+ Iterator tempIter;
+
+ if (!(cert instanceof X509Certificate))
+ {
+ return false;
+ }
+ X509Certificate certX509 = (X509Certificate)cert;
+
+ if (x509Cert != null && !x509Cert.equals(certX509))
+ {
+ return false;
+ }
+ if (serialNumber != null
+ && !serialNumber.equals(certX509.getSerialNumber()))
+ {
+ return false;
+ }
+ try
+ {
+ if (issuerDNX509 != null)
+ {
+ if (!issuerDNX509.equals(PrincipalUtil
+ .getIssuerX509Principal(certX509), true))
+ {
+ return false;
+ }
+ }
+ if (subjectDNX509 != null)
+ {
+ if (!subjectDNX509.equals(PrincipalUtil
+ .getSubjectX509Principal(certX509), true))
+ {
+ return false;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ if (subjectKeyID != null)
+ {
+ byte[] data = certX509
+ .getExtensionValue(X509Extensions.SubjectKeyIdentifier
+ .getId());
+ if (data == null)
+ {
+ return false;
+ }
+ try
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(data);
+ ASN1InputStream derInputStream = new ASN1InputStream(inStream);
+ byte[] testData = ((ASN1OctetString)derInputStream.readObject())
+ .getOctets();
+ if (!Arrays.equals(subjectKeyID, testData))
+ {
+ return false;
+ }
+ }
+ catch (IOException ex)
+ {
+ return false;
+ }
+ }
+ if (authorityKeyID != null)
+ {
+ byte[] data = certX509
+ .getExtensionValue(X509Extensions.AuthorityKeyIdentifier
+ .getId());
+ if (data == null)
+ {
+ return false;
+ }
+ try
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(data);
+ ASN1InputStream derInputStream = new ASN1InputStream(inStream);
+ byte[] testData = ((ASN1OctetString)derInputStream.readObject())
+ .getOctets();
+ if (!Arrays.equals(authorityKeyID, testData))
+ {
+ return false;
+ }
+ }
+ catch (IOException ex)
+ {
+ return false;
+ }
+ }
+ if (certValid != null)
+ {
+ if (certX509.getNotAfter() != null
+ && certValid.after(certX509.getNotAfter()))
+ {
+ return false;
+ }
+ if (certX509.getNotBefore() != null
+ && certValid.before(certX509.getNotBefore()))
+ {
+ return false;
+ }
+ }
+ if (privateKeyValid != null)
+ {
+ try
+ {
+ byte[] data = certX509
+ .getExtensionValue(X509Extensions.PrivateKeyUsagePeriod
+ .getId());
+ if (data != null)
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(
+ data);
+ ASN1InputStream derInputStream = new ASN1InputStream(inStream);
+ inStream = new ByteArrayInputStream(
+ ((ASN1OctetString)derInputStream.readObject())
+ .getOctets());
+ derInputStream = new ASN1InputStream(inStream);
+ // TODO fix this, Sequence contains tagged objects
+ ASN1Sequence derObject = (ASN1Sequence)derInputStream
+ .readObject();
+ DERGeneralizedTime derDate = DERGeneralizedTime
+ .getInstance(derObject.getObjectAt(0));
+ SimpleDateFormat dateF = new SimpleDateFormat(
+ "yyyyMMddHHmmssZ");
+ if (privateKeyValid.before(dateF.parse(derDate.getTime())))
+ {
+ return false;
+ }
+ derDate = DERGeneralizedTime.getInstance(derObject
+ .getObjectAt(1));
+ if (privateKeyValid.after(dateF.parse(derDate.getTime())))
+ {
+ return false;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ }
+ if (subjectKeyAlgID != null)
+ {
+ try
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(
+ certX509.getPublicKey().getEncoded());
+ ASN1InputStream derInputStream = new ASN1InputStream(inStream);
+ SubjectPublicKeyInfo publicKeyInfo = new SubjectPublicKeyInfo(
+ (ASN1Sequence)derInputStream.readObject());
+ AlgorithmIdentifier algInfo = publicKeyInfo.getAlgorithmId();
+ if (!algInfo.getObjectId().equals(subjectKeyAlgID))
+ {
+ return false;
+ }
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ }
+ if (subjectPublicKeyByte != null)
+ {
+ if (!Arrays.equals(subjectPublicKeyByte, certX509.getPublicKey()
+ .getEncoded()))
+ {
+ return false;
+ }
+ }
+ if (subjectPublicKey != null)
+ {
+ if (!subjectPublicKey.equals(certX509.getPublicKey()))
+ {
+ return false;
+ }
+ }
+ if (keyUsage != null)
+ {
+ booleanArray = certX509.getKeyUsage();
+ if (booleanArray != null)
+ {
+ for (int i = 0; i < keyUsage.length; i++)
+ {
+ if (keyUsage[i]
+ && (booleanArray.length <= i || !booleanArray[i]))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ if (keyPurposeSet != null && !keyPurposeSet.isEmpty())
+ {
+ try
+ {
+ byte[] data = certX509
+ .getExtensionValue(X509Extensions.ExtendedKeyUsage
+ .getId());
+ if (data != null)
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(
+ data);
+ ASN1InputStream derInputStream = new ASN1InputStream(inStream);
+ ExtendedKeyUsage extendedKeyUsage = ExtendedKeyUsage.getInstance(
+ (ASN1Sequence)derInputStream.readObject());
+ tempIter = keyPurposeSet.iterator();
+ while (tempIter.hasNext())
+ {
+ if (!extendedKeyUsage
+ .hasKeyPurposeId((KeyPurposeId)tempIter.next()))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ }
+ if (minMaxPathLen != -1)
+ {
+ if (minMaxPathLen == -2 && certX509.getBasicConstraints() != -1)
+ {
+ return false;
+ }
+ if (minMaxPathLen >= 0
+ && certX509.getBasicConstraints() < minMaxPathLen)
+ {
+ return false;
+ }
+ }
+ if (policyOID != null)
+ {
+ try
+ {
+ byte[] data = certX509
+ .getExtensionValue(X509Extensions.CertificatePolicies
+ .getId());
+ if (data == null)
+ {
+ return false;
+ }
+ if (!policyOID.isEmpty())
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(
+ data);
+ ASN1InputStream derInputStream = new ASN1InputStream(inStream);
+ inStream = new ByteArrayInputStream(
+ ((ASN1OctetString)derInputStream.readObject())
+ .getOctets());
+ derInputStream = new ASN1InputStream(inStream);
+ Enumeration policySequence = ((ASN1Sequence)derInputStream
+ .readObject()).getObjects();
+ ASN1Sequence policyObject;
+ boolean test = false;
+ while (policySequence.hasMoreElements() && !test)
+ {
+ policyObject = (ASN1Sequence)policySequence
+ .nextElement();
+ if (policyOID.contains(policyObject.getObjectAt(0)))
+ {
+ test = true;
+ }
+ }
+ if (!test)
+ {
+ return false;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ return false;
+ }
+ }
+ if (subjectAltNamesByte != null)
+ {
+ try
+ {
+ byte[] data = certX509
+ .getExtensionValue(X509Extensions.SubjectAlternativeName
+ .getId());
+ if (data == null)
+ {
+ return false;
+ }
+ ByteArrayInputStream inStream = new ByteArrayInputStream(data);
+ ASN1InputStream derInputStream = new ASN1InputStream(inStream);
+ inStream = new ByteArrayInputStream(
+ ((ASN1OctetString)derInputStream.readObject())
+ .getOctets());
+ derInputStream = new ASN1InputStream(inStream);
+ Enumeration altNamesSequence = ((ASN1Sequence)derInputStream
+ .readObject()).getObjects();
+ ASN1TaggedObject altNameObject;
+ boolean test = false;
+ Set testSet = new HashSet(subjectAltNamesByte);
+ List testList;
+ ASN1Object derData;
+ ByteArrayOutputStream outStream;
+ DEROutputStream derOutStream;
+ while (altNamesSequence.hasMoreElements() && !test)
+ {
+ altNameObject = (ASN1TaggedObject)altNamesSequence
+ .nextElement();
+ testList = new ArrayList(2);
+ testList.add(Integers.valueOf(altNameObject.getTagNo()));
+ derData = altNameObject.getObject();
+ outStream = new ByteArrayOutputStream();
+ derOutStream = new DEROutputStream(outStream);
+ derOutStream.writeObject(derData);
+ derOutStream.close();
+ testList.add(outStream.toByteArray());
+
+ if (testSet.remove(testList))
+ {
+ test = true;
+ }
+
+ if (matchAllSubjectAltNames && !testSet.isEmpty())
+ {
+ test = false;
+ }
+ }
+ if (!test)
+ {
+ return false;
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns a copy of this object.
+ *
+ * @return the copy
+ */
+ public Object clone()
+ {
+ try
+ {
+ X509CertSelector copy = (X509CertSelector)super.clone();
+ if (issuerDN instanceof byte[])
+ {
+ copy.issuerDN = ((byte[])issuerDN).clone();
+ }
+ if (subjectDN instanceof byte[])
+ {
+ copy.subjectDN = ((byte[])subjectDN).clone();
+ }
+ if (subjectKeyID != null)
+ {
+ copy.subjectKeyID = (byte[])subjectKeyID.clone();
+ }
+ if (authorityKeyID != null)
+ {
+ copy.authorityKeyID = (byte[])authorityKeyID.clone();
+ }
+ if (subjectPublicKeyByte != null)
+ {
+ copy.subjectPublicKeyByte = (byte[])subjectPublicKeyByte
+ .clone();
+ }
+ if (keyUsage != null)
+ {
+ copy.keyUsage = (boolean[])keyUsage.clone();
+ }
+ if (keyPurposeSet != null)
+ {
+ copy.keyPurposeSet = new HashSet(keyPurposeSet);
+ }
+ if (policy != null)
+ {
+ copy.policy = new HashSet(policy);
+ copy.policyOID = new HashSet();
+ Iterator iter = policyOID.iterator();
+ while (iter.hasNext())
+ {
+ copy.policyOID.add(new ASN1ObjectIdentifier(
+ ((ASN1ObjectIdentifier)iter.next()).getId()));
+ }
+ }
+ if (subjectAltNames != null)
+ {
+ copy.subjectAltNames = new HashSet(getSubjectAlternativeNames());
+ Iterator iter = subjectAltNamesByte.iterator();
+ List obj;
+ List cloneObj;
+ while (iter.hasNext())
+ {
+ obj = (List)iter.next();
+ cloneObj = new ArrayList();
+ cloneObj.add(obj.get(0));
+ cloneObj.add(((byte[])obj.get(1)).clone());
+ copy.subjectAltNamesByte.add(cloneObj);
+ }
+ }
+ if (pathToNames != null)
+ {
+ copy.pathToNames = new HashSet(getPathToNames());
+ Iterator iter = pathToNamesByte.iterator();
+ List obj;
+ List cloneObj;
+ while (iter.hasNext())
+ {
+ obj = (List)iter.next();
+ cloneObj = new ArrayList();
+ cloneObj.add(obj.get(0));
+ cloneObj.add(((byte[])obj.get(1)).clone());
+ copy.pathToNamesByte.add(cloneObj);
+ }
+ }
+ return copy;
+ }
+ catch (CloneNotSupportedException e)
+ {
+ /* Cannot happen */
+ throw new InternalError(e.toString());
+ }
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Certificate.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Certificate.java
new file mode 100644
index 000000000..d56f1c6f3
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Certificate.java
@@ -0,0 +1,33 @@
+
+package java.security.cert;
+
+import java.math.BigInteger;
+import java.security.Principal;
+import java.util.Date;
+
+public abstract class X509Certificate extends Certificate
+implements X509Extension
+{
+ protected X509Certificate()
+ {
+ super("X.509");
+ }
+
+ public abstract void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException;
+ public abstract void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException;
+ public abstract int getBasicConstraints();
+ public abstract Principal getIssuerDN();
+ public abstract boolean[] getIssuerUniqueID();
+ public abstract boolean[] getKeyUsage();
+ public abstract Date getNotAfter();
+ public abstract Date getNotBefore();
+ public abstract BigInteger getSerialNumber();
+ public abstract String getSigAlgName();
+ public abstract String getSigAlgOID();
+ public abstract byte[] getSigAlgParams();
+ public abstract byte[] getSignature();
+ public abstract Principal getSubjectDN();
+ public abstract boolean[] getSubjectUniqueID();
+ public abstract byte[] getTBSCertificate() throws CertificateEncodingException;
+ public abstract int getVersion();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Extension.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Extension.java
new file mode 100644
index 000000000..20855be1e
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Extension.java
@@ -0,0 +1,12 @@
+
+package java.security.cert;
+
+import java.util.Set;
+
+public interface X509Extension
+{
+ public abstract Set getCriticalExtensionOIDs();
+ public abstract byte[] getExtensionValue(String oid);
+ public abstract Set getNonCriticalExtensionOIDs();
+ public abstract boolean hasUnsupportedCriticalExtension();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
new file mode 100644
index 000000000..0fbb0fb17
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
@@ -0,0 +1,67 @@
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+import java.security.spec.RSAOtherPrimeInfo;
+
+/**
+ * The interface to an RSA multi-prime private key, as defined in the
+ * PKCS#1 v2.1, using the Chinese Remainder Theorem (CRT) information values.
+ *
+ * @since 1.4
+ * @see RSAPrivateKeySpec, RSAMultiPrimePrivateCrtKeySpec, RSAPrivateKey,
+ * RSAPrivateCrtKey
+ */
+public interface RSAMultiPrimePrivateCrtKey
+extends RSAPrivateKey
+{
+ /**
+ * Returns the public exponent.
+ *
+ * @returns the public exponent.
+ */
+ public BigInteger getPublicExponent();
+
+ /**
+ * Returns the primeP.
+ *
+ * @returns the primeP.
+ */
+ public BigInteger getPrimeP();
+
+ /**
+ * Returns the primeQ.
+ *
+ * @returns the primeQ.
+ */
+ public BigInteger getPrimeQ();
+
+ /**
+ * Returns the primeExponentP.
+ *
+ * @returns the primeExponentP.
+ */
+ public BigInteger getPrimeExponentP();
+
+ /**
+ * Returns the primeExponentQ.
+ *
+ * @returns the primeExponentQ.
+ */
+ public BigInteger getPrimeExponentQ();
+
+ /**
+ * Returns the crtCoefficient.
+ *
+ * @returns the crtCoefficient.
+ */
+ public BigInteger getCrtCoefficient();
+
+ /**
+ * Returns the otherPrimeInfo or null if there are only two prime
+ * factors (p and q).
+ *
+ * @returns the otherPrimeInfo.
+ */
+ public RSAOtherPrimeInfo[] getOtherPrimeInfo();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAPrivateCrtKey.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAPrivateCrtKey.java
new file mode 100644
index 000000000..81855907c
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAPrivateCrtKey.java
@@ -0,0 +1,16 @@
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+
+public interface RSAPrivateCrtKey extends RSAPrivateKey
+{
+ public static final long serialVersionUID = 6034044314589513430L;
+
+ public abstract BigInteger getCrtCoefficient();
+ public abstract BigInteger getPrimeExponentP();
+ public abstract BigInteger getPrimeExponentQ();
+ public abstract BigInteger getPrimeP();
+ public abstract BigInteger getPrimeQ();
+ public abstract BigInteger getPublicExponent();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAPrivateKey.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAPrivateKey.java
new file mode 100644
index 000000000..9b37eef93
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAPrivateKey.java
@@ -0,0 +1,13 @@
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+
+public interface RSAPrivateKey extends PrivateKey
+{
+ public static final long serialVersionUID = 6034044314589513430L;
+
+ public abstract BigInteger getModulus();
+ public abstract BigInteger getPrivateExponent();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAPublicKey.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAPublicKey.java
new file mode 100644
index 000000000..6ae00ec2c
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/interfaces/RSAPublicKey.java
@@ -0,0 +1,13 @@
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+import java.security.PublicKey;
+
+public interface RSAPublicKey extends PublicKey
+{
+ public static final long serialVersionUID = 7187392471159151072L;
+
+ public abstract BigInteger getModulus();
+ public abstract BigInteger getPublicExponent();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/AlgorithmParameterSpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/AlgorithmParameterSpec.java
new file mode 100644
index 000000000..37a03e9b2
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/AlgorithmParameterSpec.java
@@ -0,0 +1,6 @@
+
+package java.security.spec;
+
+public interface AlgorithmParameterSpec
+{
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/DSAParameterSpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/DSAParameterSpec.java
new file mode 100644
index 000000000..a3897f8a6
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/DSAParameterSpec.java
@@ -0,0 +1,34 @@
+
+package java.security.spec;
+
+import java.math.BigInteger;
+import java.security.interfaces.DSAParams;
+
+public class DSAParameterSpec implements AlgorithmParameterSpec, DSAParams
+{
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger g;
+
+ public DSAParameterSpec(BigInteger p, BigInteger q, BigInteger g)
+ {
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/DSAPrivateKeySpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/DSAPrivateKeySpec.java
new file mode 100644
index 000000000..ff5febef6
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/DSAPrivateKeySpec.java
@@ -0,0 +1,40 @@
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+public class DSAPrivateKeySpec implements KeySpec
+{
+ private BigInteger x;
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger g;
+
+ public DSAPrivateKeySpec(BigInteger x, BigInteger p, BigInteger q, BigInteger g)
+ {
+ this.x = x;
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/DSAPublicKeySpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/DSAPublicKeySpec.java
new file mode 100644
index 000000000..f8ca36792
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/DSAPublicKeySpec.java
@@ -0,0 +1,40 @@
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+public class DSAPublicKeySpec implements KeySpec
+{
+ private BigInteger y;
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger g;
+
+ public DSAPublicKeySpec(BigInteger y, BigInteger p, BigInteger q, BigInteger g)
+ {
+ this.y = y;
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/EncodedKeySpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/EncodedKeySpec.java
new file mode 100644
index 000000000..7295460f0
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/EncodedKeySpec.java
@@ -0,0 +1,19 @@
+
+package java.security.spec;
+
+public abstract class EncodedKeySpec implements KeySpec
+{
+ private byte[] encodedKey;
+
+ public EncodedKeySpec(byte[] encodedKey)
+ {
+ this.encodedKey = (byte[])encodedKey.clone();
+ }
+
+ public byte[] getEncoded()
+ {
+ return (byte[])encodedKey.clone();
+ }
+
+ public abstract String getFormat();
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/InvalidKeySpecException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/InvalidKeySpecException.java
new file mode 100644
index 000000000..cb29aee38
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/InvalidKeySpecException.java
@@ -0,0 +1,16 @@
+
+package java.security.spec;
+
+import java.security.GeneralSecurityException;
+
+public class InvalidKeySpecException extends GeneralSecurityException
+{
+ public InvalidKeySpecException()
+ {
+ }
+
+ public InvalidKeySpecException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/InvalidParameterSpecException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/InvalidParameterSpecException.java
new file mode 100644
index 000000000..c8303edda
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/InvalidParameterSpecException.java
@@ -0,0 +1,16 @@
+
+package java.security.spec;
+
+import java.security.GeneralSecurityException;
+
+public class InvalidParameterSpecException extends GeneralSecurityException
+{
+ public InvalidParameterSpecException()
+ {
+ }
+
+ public InvalidParameterSpecException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/KeySpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/KeySpec.java
new file mode 100644
index 000000000..cfa7cb92f
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/KeySpec.java
@@ -0,0 +1,6 @@
+
+package java.security.spec;
+
+public interface KeySpec
+{
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/PKCS8EncodedKeySpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/PKCS8EncodedKeySpec.java
new file mode 100644
index 000000000..10c5f66c2
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/PKCS8EncodedKeySpec.java
@@ -0,0 +1,20 @@
+
+package java.security.spec;
+
+public class PKCS8EncodedKeySpec extends EncodedKeySpec
+{
+ public PKCS8EncodedKeySpec(byte[] encodedKey)
+ {
+ super(encodedKey);
+ }
+
+ public byte[] getEncoded()
+ {
+ return super.getEncoded();
+ }
+
+ public final String getFormat()
+ {
+ return "PKCS#8";
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/PSSParameterSpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/PSSParameterSpec.java
new file mode 100644
index 000000000..c4b4989cd
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/PSSParameterSpec.java
@@ -0,0 +1,45 @@
+
+package java.security.spec;
+
+/**
+ * This class specifies a parameter spec for RSA PSS encoding scheme,
+ * as defined in the PKCS#1 v2.1.
+ *
+ * @since 1.4
+ * @see AlgorithmParameterSpec, Signature
+ */
+public class PSSParameterSpec
+ extends Object
+ implements AlgorithmParameterSpec
+{
+ private int saltLen;
+
+ /**
+ * Creates a new PSSParameterSpec given the salt length as defined
+ * in PKCS#1.
+ *
+ * @param saltLen - the length of salt in bits to be used in PKCS#1
+ * PSS encoding.
+ * @throws IllegalArgumentException - if saltLen is less than 0.
+ */
+ public PSSParameterSpec(int saltLen)
+ {
+ if ( saltLen < 0 )
+ {
+ throw new IllegalArgumentException("Salt length must be >= 0");
+ }
+
+ this.saltLen = saltLen;
+ }
+
+ /**
+ * Returns the salt length in bits.
+ *
+ * @returns the salt length.
+ */
+ public int getSaltLength()
+ {
+ return saltLen;
+ }
+}
+
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAKeyGenParameterSpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAKeyGenParameterSpec.java
new file mode 100644
index 000000000..756c6c0fd
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAKeyGenParameterSpec.java
@@ -0,0 +1,35 @@
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * specifies parameters to be used for the generation of
+ * a RSA key pair.
+ */
+public class RSAKeyGenParameterSpec
+ implements AlgorithmParameterSpec
+{
+ static BigInteger F0 = BigInteger.valueOf(3);
+ static BigInteger F4 = BigInteger.valueOf(65537);
+
+ private int keysize;
+ private BigInteger publicExponent;
+
+ public RSAKeyGenParameterSpec(
+ int keysize,
+ BigInteger publicExponent)
+ {
+ this.keysize = keysize;
+ this.publicExponent = publicExponent;
+ }
+
+ public int getKeysize()
+ {
+ return keysize;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
new file mode 100644
index 000000000..53c3a8a51
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
@@ -0,0 +1,159 @@
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This class specifies an RSA multi-prime private key, as defined in
+ * the PKCS#1 v2.1, using the Chinese Remainder Theorem (CRT) information
+ * values for efficiency.
+ *
+ * @since 1.4
+ * @see Key, KeyFactory, KeySpec, PKCS8EncodedKeySpec, RSAPrivateKeySpec,
+ * RSAPublicKeySpec, RSAOtherPrimeInfo
+ */
+public class RSAMultiPrimePrivateCrtKeySpec
+ extends RSAPrivateKeySpec
+{
+ private BigInteger publicExponent;
+ private BigInteger privateExponent;
+ private BigInteger primeP;
+ private BigInteger primeQ;
+ private BigInteger primeExponentP;
+ private BigInteger primeExponentQ;
+ private BigInteger crtCoefficient;
+ private RSAOtherPrimeInfo[] otherPrimeInfo;
+
+ /**
+ * Creates a new RSAMultiPrimePrivateCrtKeySpec given the modulus,
+ * publicExponent, privateExponent, primeP, primeQ, primeExponentP,
+ * primeExponentQ, crtCoefficient, and otherPrimeInfo as defined in
+ * PKCS#1 v2.1.
+ *
+ * Note that otherPrimeInfo is cloned when constructing this object.
+ *
+ * @param modulus - the modulus n.
+ * @param publicExponent - the public exponent e.
+ * @param privateExponent - the private exponent d.
+ * @param primeP - the prime factor p of n.
+ * @param primeQ - the prime factor q of n.
+ * @param primeExponentP - this is d mod (p-1).
+ * @param primeExponentQ - this is d mod (q-1).
+ * @param crtCoefficient - the Chinese Remainder Theorem coefficient q-1
+ * mod p.
+ * @param otherPrimeInfo - triplets of the rest of primes, null can be
+ * specified if there are only two prime factors (p and q).
+ * @throws NullPointerException - if any of the parameters, i.e. modulus,
+ * publicExponent, privateExponent, primeP, primeQ, primeExponentP,
+ * primeExponentQ, crtCoefficient, is null.
+ * @throws IllegalArgumentException - if an empty, i.e. 0-length,
+ * otherPrimeInfo is specified.
+ */
+ public RSAMultiPrimePrivateCrtKeySpec(
+ BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger primeP,
+ BigInteger primeQ,
+ BigInteger primeExponentP,
+ BigInteger primeExponentQ,
+ BigInteger crtCoefficient,
+ RSAOtherPrimeInfo[] otherPrimeInfo)
+ {
+ super(modulus, privateExponent);
+
+ if ( publicExponent == null || primeP == null || primeQ == null
+ || primeExponentP == null || primeExponentQ == null
+ || crtCoefficient == null )
+ {
+ throw new NullPointerException("Invalid null argument");
+ }
+
+ if ( otherPrimeInfo != null )
+ {
+ if ( otherPrimeInfo.length == 0 )
+ {
+ throw new IllegalArgumentException("Invalid length for otherPrimeInfo");
+ }
+
+ this.otherPrimeInfo = (RSAOtherPrimeInfo[])otherPrimeInfo.clone();
+ }
+ }
+
+ /**
+ * Returns the public exponent.
+ *
+ * @returns the public exponent.
+ */
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+
+ /**
+ * Returns the primeP.
+ *
+ * @returns the primeP.
+ */
+ public BigInteger getPrimeP()
+ {
+ return primeP;
+ }
+
+ /**
+ * Returns the primeQ.
+ *
+ * @returns the primeQ.
+ */
+ public BigInteger getPrimeQ()
+ {
+ return primeQ;
+ }
+
+ /**
+ * Returns the primeExponentP.
+ *
+ * @returns the primeExponentP.
+ */
+ public BigInteger getPrimeExponentP()
+ {
+ return primeExponentP;
+ }
+
+ /**
+ * Returns the primeExponentQ.
+ *
+ * @returns the primeExponentQ.
+ */
+ public BigInteger getPrimeExponentQ()
+ {
+ return primeExponentQ;
+ }
+
+ /**
+ * Returns the crtCofficient.
+ *
+ * @returns the crtCofficient.
+ */
+ public BigInteger getCrtCoefficient()
+ {
+ return crtCoefficient;
+ }
+
+ /**
+ * Returns a copy of the otherPrimeInfo or null if there are only
+ * two prime factors (p and q).
+ *
+ * @returns the otherPrimeInfo.
+ */
+ public RSAOtherPrimeInfo[] getOtherPrimeInfo()
+ {
+ if ( otherPrimeInfo != null )
+ {
+ return (RSAOtherPrimeInfo[])otherPrimeInfo.clone();
+ }
+
+ return null;
+ }
+}
+
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAOtherPrimeInfo.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAOtherPrimeInfo.java
new file mode 100644
index 000000000..4d0e1468e
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAOtherPrimeInfo.java
@@ -0,0 +1,80 @@
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This class represents the triplet (prime, exponent, and coefficient)
+ * inside RSA's OtherPrimeInfo structure, as defined in the PKCS#1 v2.1.
+ * The ASN.1 syntax of RSA's OtherPrimeInfo is as follows:
+ *
+ * <pre>
+ * OtherPrimeInfo ::= SEQUENCE {
+ * prime INTEGER,
+ * exponent INTEGER,
+ * coefficient INTEGER
+ * }
+ * </pre>
+ */
+public class RSAOtherPrimeInfo
+extends Object
+{
+ private BigInteger prime;
+ private BigInteger primeExponent;
+ private BigInteger crtCoefficient;
+
+ /**
+ * Creates a new RSAOtherPrimeInfo given the prime, primeExponent,
+ * and crtCoefficient as defined in PKCS#1.
+ *
+ * @param prime - the prime factor of n.
+ * @param primeExponent - the exponent.
+ * @param crtCoefficient - the Chinese Remainder Theorem coefficient.
+ * @throws NullPointerException - if any of the parameters, i.e. prime,
+ * primeExponent, crtCoefficient, is null.
+ */
+ public RSAOtherPrimeInfo(
+ BigInteger prime,
+ BigInteger primeExponent,
+ BigInteger crtCoefficient)
+ {
+ if ( prime == null || primeExponent == null || crtCoefficient == null )
+ {
+ throw new NullPointerException("Null parameter");
+ }
+
+ this.prime = prime;
+ this.primeExponent = primeExponent;
+ this.crtCoefficient = crtCoefficient;
+ }
+
+ /**
+ * Returns the prime.
+ *
+ * @returns the prime.
+ */
+ public final BigInteger getPrime()
+ {
+ return prime;
+ }
+
+ /**
+ * Returns the prime's exponent.
+ *
+ * @returns the primeExponent.
+ */
+ public final BigInteger getExponent()
+ {
+ return primeExponent;
+ }
+
+ /**
+ * Returns the prime's crtCoefficient.
+ *
+ * @returns the crtCoefficient.
+ */
+ public final BigInteger getCrtCoefficient()
+ {
+ return crtCoefficient;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAPrivateCrtKeySpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAPrivateCrtKeySpec.java
new file mode 100644
index 000000000..b9d450ad7
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAPrivateCrtKeySpec.java
@@ -0,0 +1,64 @@
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+public class RSAPrivateCrtKeySpec extends RSAPrivateKeySpec
+{
+ private BigInteger publicExponent;
+ private BigInteger primeP;
+ private BigInteger primeQ;
+ private BigInteger primeExponentP;
+ private BigInteger primeExponentQ;
+ private BigInteger crtCoefficient;
+
+ public RSAPrivateCrtKeySpec(
+ BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger primeP,
+ BigInteger primeQ,
+ BigInteger primeExponentP,
+ BigInteger primeExponentQ,
+ BigInteger crtCoefficient)
+ {
+ super(modulus, privateExponent);
+
+ this.publicExponent = publicExponent;
+ this.primeP = primeP;
+ this.primeQ = primeQ;
+ this.primeExponentP = primeExponentP;
+ this.primeExponentQ = primeExponentQ;
+ this.crtCoefficient = crtCoefficient;
+ }
+
+ public BigInteger getCrtCoefficient()
+ {
+ return crtCoefficient;
+ }
+
+ public BigInteger getPrimeExponentP()
+ {
+ return primeExponentP;
+ }
+
+ public BigInteger getPrimeExponentQ()
+ {
+ return primeExponentQ;
+ }
+
+ public BigInteger getPrimeP()
+ {
+ return primeP;
+ }
+
+ public BigInteger getPrimeQ()
+ {
+ return primeQ;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAPrivateKeySpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAPrivateKeySpec.java
new file mode 100644
index 000000000..88dc4c159
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAPrivateKeySpec.java
@@ -0,0 +1,28 @@
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+public class RSAPrivateKeySpec extends Object implements KeySpec
+{
+ private BigInteger modulus;
+ private BigInteger privateExponent;
+
+ public RSAPrivateKeySpec(
+ BigInteger modulus,
+ BigInteger privateExponent)
+ {
+ this.modulus = modulus;
+ this.privateExponent = privateExponent;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPrivateExponent()
+ {
+ return privateExponent;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAPublicKeySpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAPublicKeySpec.java
new file mode 100644
index 000000000..b3a367e7e
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/RSAPublicKeySpec.java
@@ -0,0 +1,28 @@
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+public class RSAPublicKeySpec extends Object implements KeySpec
+{
+ private BigInteger modulus;
+ private BigInteger publicExponent;
+
+ public RSAPublicKeySpec(
+ BigInteger modulus,
+ BigInteger publicExponent)
+ {
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/X509EncodedKeySpec.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/X509EncodedKeySpec.java
new file mode 100644
index 000000000..1d095b11d
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/spec/X509EncodedKeySpec.java
@@ -0,0 +1,20 @@
+
+package java.security.spec;
+
+public class X509EncodedKeySpec extends EncodedKeySpec
+{
+ public X509EncodedKeySpec(byte[] encodedKey)
+ {
+ super(encodedKey);
+ }
+
+ public byte[] getEncoded()
+ {
+ return super.getEncoded();
+ }
+
+ public final String getFormat()
+ {
+ return "X.509";
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractCollection.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractCollection.java
new file mode 100644
index 000000000..0ea61b772
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractCollection.java
@@ -0,0 +1,242 @@
+package java.util;
+
+import java.lang.reflect.Array;
+/**
+ * Title:
+ * Description:
+ * Copyright: Copyright (c) 2001
+ * Company:
+ * @version 1.0
+ */
+
+
+public abstract class AbstractCollection implements Collection
+ {
+ protected AbstractCollection()
+ {
+ }
+
+ public abstract Iterator iterator();
+
+ public abstract int size();
+
+ public boolean isEmpty()
+ {
+ return size()==0;
+ }
+
+ public boolean contains(Object o)
+ {
+ Iterator it=iterator();
+ while(it.hasNext())
+ {
+ Object e=it.next();
+ if(o==null)
+ {
+ if(e==null)
+ return true;
+ }
+ else
+ {
+ if(o.equals(e))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Object[] toArray()
+ {
+ Object[] arObjects=new Object[size()];
+ Iterator it=iterator();
+ int i=0;
+ while(it.hasNext())
+ {
+ arObjects[i++]=it.next();
+ }
+ return arObjects;
+ }
+
+ public Object[] toArray(Object[] a) throws NullPointerException,ArrayStoreException
+ //TODO: Check if this is realy compatible to SUN!!!
+ {
+ if(a==null)
+ throw new NullPointerException();
+
+ if (isEmpty()) return a;
+ Object[] arObjects=null;
+ int size=size();
+ if(a.length<size)
+ {
+ Iterator it=iterator();
+ Object o=it.next();
+ if(o==null) //no object or object is null
+ throw new ArrayStoreException(); //correct ?
+ arObjects=(Object[])Array.newInstance(o.getClass(),size);
+ }
+ else
+ {
+ arObjects=a;
+ if(a.length>size)
+ arObjects[size]=null;
+
+ }
+
+ Iterator it=iterator();
+ int i=0;
+ while(it.hasNext())
+ {
+ Object o=it.next();
+ arObjects[i++]=o;
+ }
+ return arObjects;
+ }
+
+ public boolean add(Object o) throws UnsupportedOperationException,NullPointerException,ClassCastException,IllegalArgumentException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean remove(Object o) throws UnsupportedOperationException
+ {
+ Iterator it=iterator();
+ while(it.hasNext())
+ {
+ Object e=it.next();
+ if(o==null)
+ {
+ if(e==null)
+ {
+ try
+ {
+ it.remove();
+ }
+ catch(UnsupportedOperationException ue)
+ {
+ throw ue;
+ }
+ return true;
+ }
+ }
+ else
+ {
+ if(o.equals(e))
+ {
+ try
+ {
+ it.remove();
+ }
+ catch(UnsupportedOperationException ue)
+ {
+ throw ue;
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public boolean containsAll(Collection c)
+ {
+ Iterator it=c.iterator();
+ while(it.hasNext())
+ {
+ if(!contains(it.next()))
+ return false;
+ }
+ return true;
+ }
+
+ public boolean addAll(Collection c) throws UnsupportedOperationException
+ {
+ Iterator it=c.iterator();
+ boolean ret=false;
+ while(it.hasNext())
+ {
+ try
+ {
+ ret|=add(it.next());
+ }
+ catch(UnsupportedOperationException ue)
+ {
+ throw ue;
+ }
+ }
+ return ret;
+ }
+
+ public boolean removeAll(Collection c) throws UnsupportedOperationException
+ {
+ Iterator it=iterator();
+ boolean ret=false;
+ while(it.hasNext())
+ {
+ if(c.contains(it.next()))
+ try
+ {
+ it.remove();
+ ret=true;
+ }
+ catch(UnsupportedOperationException ue)
+ {
+ throw ue;
+ }
+ }
+ return ret;
+ }
+
+ public boolean retainAll(Collection c) throws UnsupportedOperationException
+ {
+ Iterator it=iterator();
+ boolean ret=false;
+ while(it.hasNext())
+ {
+ if(!c.contains(it.next()))
+ try
+ {
+ it.remove();
+ ret=true;
+ }
+ catch(UnsupportedOperationException ue)
+ {
+ throw ue;
+ }
+ }
+ return ret;
+ }
+
+ public void clear() throws UnsupportedOperationException
+ {
+ Iterator it=iterator();
+ while(it.hasNext())
+ {
+ try
+ {
+ it.next();
+ it.remove();
+ }
+ catch(UnsupportedOperationException ue)
+ {
+ throw ue;
+ }
+ }
+ }
+
+ public String toString()
+ {
+ String ret="[";
+ Iterator it=iterator();
+ if(it.hasNext())
+ ret+=String.valueOf(it.next());
+ while(it.hasNext())
+ {
+ ret+=", ";
+ ret+=String.valueOf(it.next());
+
+ }
+ ret+="]";
+ return ret;
+ }
+
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractList.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractList.java
new file mode 100644
index 000000000..363b57aec
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractList.java
@@ -0,0 +1,281 @@
+package java.util;
+
+/**
+ * Title:
+ * Description:
+ * Copyright: Copyright (c) 2001
+ * Company:
+ * @version 1.0
+ */
+
+public abstract class AbstractList extends AbstractCollection implements List
+
+{
+ protected AbstractList al = this;
+
+
+ protected AbstractList()
+ {
+ }
+
+ public boolean add(Object o) throws UnsupportedOperationException, ClassCastException, IllegalArgumentException
+ {
+ try
+ {
+ add(size(),o);
+ return true;
+ }
+ catch(UnsupportedOperationException ue)
+ {
+ throw ue;
+ }
+ }
+
+ public abstract Object get(int index) throws IndexOutOfBoundsException;
+
+ public Object set(int index,Object element) throws UnsupportedOperationException, ClassCastException, IllegalArgumentException, IndexOutOfBoundsException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void add(int index,Object element) throws UnsupportedOperationException, ClassCastException, IllegalArgumentException, IndexOutOfBoundsException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object remove(int index) throws UnsupportedOperationException, IndexOutOfBoundsException
+ {
+ Object o = get(index);
+
+ removeRange(index,index+1);
+ return o;
+ }
+
+ public int indexOf(Object o)
+ {
+ ListIterator li = listIterator();
+ Object e;
+ while(li.hasNext())
+ {
+ int index=li.nextIndex();
+ e=li.next();
+ System.out.println(e);
+ if(o==null)
+ {
+ if(e==null)
+ return index;
+ }
+ else
+ {
+ if(o.equals(e))
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ public int lastIndexOf(Object o)
+ {
+ ListIterator li=listIterator(size());
+ while(li.hasPrevious())
+ {
+ int index=li.previousIndex();
+ Object e=li.previous();
+ if(o==null)
+ {
+ if(e==null)
+ return index;
+ }
+ else
+ {
+ if(o.equals(e))
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ public void clear() throws UnsupportedOperationException
+ {
+ try
+ {
+ removeRange(0,size());
+ }
+ catch(UnsupportedOperationException ue)
+ {
+ throw ue;
+ }
+ }
+
+ public boolean addAll(int index,Collection c) throws UnsupportedOperationException, ClassCastException, IllegalArgumentException, IndexOutOfBoundsException
+ {
+ Iterator it=c.iterator();
+ boolean ret=false;
+ while(it.hasNext())
+ {
+ try
+ {
+ add(index++,it.next());
+ ret=true;
+ }
+ catch(UnsupportedOperationException ue)
+ {
+ throw ue;
+ }
+ }
+ return ret;
+ }
+
+ public Iterator iterator()
+ {
+ return new AbstractListIterator(this,0);
+ }
+
+ public ListIterator listIterator()
+ {
+ return listIterator(0);
+ }
+
+ public ListIterator listIterator(int index) throws IndexOutOfBoundsException
+ {
+ if(index<0||index>size()) throw new IndexOutOfBoundsException();
+ return new AbstractListListIterator(this,index);
+ }
+
+ public List subList(int fromIndex,int toIndex) throws IndexOutOfBoundsException,IllegalArgumentException
+ {
+ if(fromIndex < 0 || toIndex > size())
+ throw new IndexOutOfBoundsException();
+ if(fromIndex>toIndex)
+ throw new IllegalArgumentException();
+ return (List) new Sublist(this,fromIndex,toIndex);
+ }
+
+ public boolean equals(Object o)
+ {
+ if(o==this)
+ return true;
+ if(!(o instanceof List))
+ return false;
+ Iterator it1=iterator();
+ Iterator it2=((List)o).iterator();
+ while(it1.hasNext())
+ {
+ if(!it2.hasNext())
+ return false;
+ Object e1=it1.next();
+ Object e2=it2.next();
+ if(e1==null)
+ {
+ if(e2!=null)
+ return false;
+ }
+ if(!e1.equals(e2))
+ return false;
+ }
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int hashCode = 1;
+ Iterator it = iterator();
+ while (it.hasNext())
+ {
+ Object o = it.next();
+ hashCode = 31*hashCode + (o==null ? 0 : o.hashCode());
+ }
+ return hashCode;
+ }
+
+ protected void removeRange(int fromIndex,int toIndex)
+ {
+ System.out.println("breakpoint 1");
+ if(fromIndex==toIndex) return;
+ System.out.println("breakpoint 2");
+ ListIterator li=listIterator(fromIndex);
+ System.out.println("breakpoint 3");
+ int i=fromIndex;
+ do
+ {
+ li.next();
+ li.remove();
+ i++;
+ }while(li.hasNext()&&i<toIndex);
+ }
+
+////////////////////////////////////////////////////////////
+/////////////innere Klasse AbstractIterator/////////////////
+////////////////////////////////////////////////////////////
+
+private class AbstractListIterator implements Iterator
+ {
+ AbstractList m_al=null;
+ int m_nextIndex=0;
+ public AbstractListIterator(AbstractList al,int index)
+ {
+ m_al=al;
+ m_nextIndex=index;
+ }
+
+ public boolean hasNext()
+ {
+ return m_nextIndex < m_al.size();
+ }
+
+ public Object next()
+ {
+ return m_al.get(m_nextIndex++);
+ }
+
+ public void remove()
+ {
+ m_al.remove(m_nextIndex - 1);
+ }
+ }
+
+///////////////////////////////////////////////////////////////////////////////
+//////////// innere Klasse AbstraktListListIterator
+///////////////////////////////////////////////////////////////////////////////
+
+
+private class AbstractListListIterator extends AbstractListIterator implements ListIterator
+ {
+ public AbstractListListIterator(AbstractList al,int index)
+ {
+ super(al,index);
+ }
+
+ public boolean hasPrevious()
+ {
+ return m_nextIndex>0;
+ }
+
+ public Object previous()// throws NoSuchElementException;
+ {
+ return m_al.get(--m_nextIndex);
+ }
+
+ public int nextIndex()
+ {
+ return m_nextIndex;
+ }
+
+ public int previousIndex()
+ {
+ return m_nextIndex-1;
+ }
+
+ public void set(Object o) //throws UnsupportedOperationException, ClassCastException, IllegalArgumentException,IllegalStateException;
+ {
+ m_al.set(m_nextIndex-1,o);
+ }
+
+ public void add(Object o)// throws UnsupportedOperationException, ClassCastException, IllegalArgumentException;
+ {
+ m_al.add(m_nextIndex-1,o);
+ }
+ }
+
+
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractMap.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractMap.java
new file mode 100644
index 000000000..d5b2e02e1
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractMap.java
@@ -0,0 +1,164 @@
+package java.util;
+
+/*************
+ * Title:
+ * Description:
+ * Copyright: Copyright (c) 2001
+ * Company:
+ * @version 1.0
+ */
+
+public abstract class AbstractMap implements Map{
+
+ protected AbstractMap()
+ {
+ }
+
+ public int size()
+ {
+ return entrySet().size();
+ }
+
+ public boolean isEmpty()
+ {
+ return size()==0;
+ }
+
+ public boolean containsValue(Object value)
+ {
+ Iterator it=entrySet().iterator();
+ while(it.hasNext())
+ {
+ Map.Entry v=(Map.Entry)it.next();
+ if(value==null)
+ {
+ if(v.getValue()==null)
+ return true;
+ }
+ else
+ {
+ if(value.equals(v.getValue()))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean containsKey(Object key) throws ClassCastException,NullPointerException
+ {
+ Iterator it=entrySet().iterator();
+ while(it.hasNext())
+ {
+ Map.Entry v=(Map.Entry)it.next();
+ if(key==null)
+ {
+ if(v.getKey()==null)
+ return true;
+ }
+ else
+ {
+ if(key.equals(v.getKey()))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Object get(Object key)throws ClassCastException,NullPointerException
+ {
+ Iterator it=entrySet().iterator();
+ while(it.hasNext())
+ {
+ Map.Entry v=(Map.Entry)it.next();
+ if(key==null)
+ {
+ if(v.getKey()==null)
+ return v.getValue();
+ }
+ else
+ {
+ if(key.equals(v.getKey()))
+ return v.getValue();
+ }
+ }
+ return null;
+ }
+
+ public Object put(Object key,Object value) throws UnsupportedOperationException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object remove(Object key)
+ {
+ Iterator it=entrySet().iterator();
+ Object o=null;
+ while(it.hasNext())
+ {
+ Map.Entry v=(Map.Entry)it.next();
+ if(key==null)
+ {
+ if(v.getKey()==null)
+ {
+ o=v.getValue();
+ it.remove();
+ return o;
+ }
+ }
+ else
+ {
+ if(key.equals(v.getKey()))
+ {
+ o=v.getValue();
+ it.remove();
+ return o;
+ }
+ }
+ }
+ return null;
+ }
+
+ public void putAll(Map t)
+ {
+ Iterator it=t.entrySet().iterator();
+ while(it.hasNext())
+ {
+ Map.Entry v=(Map.Entry)it.next();
+ put(v.getKey(),v.getValue());
+ }
+ }
+
+ public void clear()
+ {
+ entrySet().clear();
+ }
+
+ public Set keySet()
+ {
+ throw new UnsupportedOperationException("no keySet in AbstractMap()");
+ }
+
+ public Collection values()
+ {
+ throw new UnsupportedOperationException("no values in AbstractMap()");
+ }
+
+ public abstract Set entrySet();
+
+ public boolean equals(Object o)
+ {
+ throw new UnsupportedOperationException("no equals in AbstractMap()");
+ }
+
+ public int hashCode()
+ {
+ throw new UnsupportedOperationException("no hashCode in AbstractMap()");
+ }
+
+ public String toString()
+ {
+ throw new UnsupportedOperationException("no toString in AbstractMap()");
+ }
+
+
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractSet.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractSet.java
new file mode 100644
index 000000000..45bbb22f6
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/AbstractSet.java
@@ -0,0 +1,42 @@
+package java.util;
+
+/**
+ * Title:
+ * Description:
+ * Copyright: Copyright (c) 2001
+ * Company:
+ * @version 1.0
+ */
+
+public abstract class AbstractSet extends AbstractCollection implements Set
+ {
+ protected AbstractSet()
+ {
+ }
+
+ public boolean equals(Object o)
+ {
+ if(this==o)
+ return true;
+ if(o==null)
+ return false;
+ if(!(o instanceof Set))
+ return false;
+ if(((Set)o).size()!=size())
+ return false;
+ return containsAll((Collection)o);
+ }
+
+ public int hashCode()
+ {
+ int hashCode=0;
+ Iterator it=iterator();
+ while(it.hasNext())
+ {
+ Object o=it.next();
+ if(o!=null)
+ hashCode+=o.hashCode();
+ }
+ return hashCode;
+ }
+ }
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/ArrayList.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/ArrayList.java
new file mode 100644
index 000000000..7e3cbbc3d
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/ArrayList.java
@@ -0,0 +1,107 @@
+package java.util;
+
+public class ArrayList extends AbstractList
+ implements List
+ {
+ Vector m_Vector=null;
+
+ public ArrayList()
+ {
+ m_Vector=new Vector();
+ }
+
+ public ArrayList(Collection c)
+ {
+ m_Vector=new Vector((int)(c.size()*1.1));
+ addAll(c);
+ }
+
+ public ArrayList(int initialCapacity)
+ {
+ m_Vector=new Vector(initialCapacity);
+ }
+
+ public void trimToSize()
+ {
+ m_Vector.trimToSize();
+ }
+
+ public void ensureCapacity(int minCapacity)
+ {
+ m_Vector.ensureCapacity(minCapacity);
+ }
+
+ public int size()
+ {
+ return m_Vector.size();
+ }
+
+ public boolean contains(Object elem)
+ {
+ return m_Vector.contains(elem);
+ }
+
+ public int indexOf(Object elem)
+ {
+ return m_Vector.indexOf(elem);
+ }
+
+ public int lastIndexOf(Object elem)
+ {
+ return m_Vector.lastIndexOf(elem);
+ }
+
+ public Object clone()
+ {
+ ArrayList al=new ArrayList();
+ al.m_Vector=(Vector)m_Vector.clone();
+ return al;
+ }
+
+ public Object[] toArray()
+ {
+ Object[] o=new Object[m_Vector.size()];
+ m_Vector.copyInto(o);
+ return o;
+ }
+
+ public Object get(int index)
+ {
+ return m_Vector.elementAt(index);
+ }
+
+ public Object set(int index,Object elem)
+ {
+ Object o=m_Vector.elementAt(index);
+ m_Vector.setElementAt(elem,index);
+ return o;
+ }
+
+ public boolean add(Object o)
+ {
+ m_Vector.addElement(o);
+ return true;
+ }
+
+ public void add(int index,Object elem)
+ {
+ m_Vector.insertElementAt(elem,index);
+ }
+
+ public Object remove(int index)
+ {
+ Object o=m_Vector.elementAt(index);
+ m_Vector.removeElementAt(index);
+ return o;
+ }
+
+ public void clear()
+ {
+ m_Vector.removeAllElements();
+ }
+
+
+
+
+
+ }
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/Arrays.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Arrays.java
new file mode 100644
index 000000000..0591e8d7f
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Arrays.java
@@ -0,0 +1,90 @@
+package java.util;
+
+public class Arrays
+{
+
+ private Arrays() {}
+
+ public static void fill(byte[] ret, byte v)
+ {
+ for (int i = 0; i != ret.length; i++)
+ {
+ ret[i] = v;
+ }
+ }
+
+ public static boolean equals(byte[] a, byte[] a2) {
+ if (a==a2)
+ return true;
+ if (a==null || a2==null)
+ return false;
+
+ int length = a.length;
+ if (a2.length != length)
+ return false;
+
+ for (int i=0; i<length; i++)
+ if (a[i] != a2[i])
+ return false;
+
+ return true;
+ }
+ public static List asList(Object[] a) {
+ return new ArrayList(a);
+ }
+
+ private static class ArrayList extends AbstractList implements java.io.Serializable
+ {
+ private Object[] a;
+
+ ArrayList(Object[] array)
+ {
+ a = array;
+ }
+
+ public int size()
+ {
+ return a.length;
+ }
+
+ public Object[] toArray()
+ {
+ return (Object[]) a.clone();
+ }
+
+ public Object get(int index)
+ {
+ return a[index];
+ }
+
+ public Object set(int index, Object element)
+ {
+ Object oldValue = a[index];
+ a[index] = element;
+ return oldValue;
+ }
+
+ public int indexOf(Object o)
+ {
+ if (o==null)
+ {
+ for (int i=0; i<a.length; i++)
+ if (a[i]==null)
+ return i;
+ }
+ else
+ {
+ for (int i=0; i<a.length; i++)
+ if (o.equals(a[i]))
+ return i;
+ }
+ return -1;
+ }
+
+ public boolean contains(Object o)
+ {
+ return indexOf(o) != -1;
+ }
+ }
+
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/Collection.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Collection.java
new file mode 100644
index 000000000..650eeb850
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Collection.java
@@ -0,0 +1,21 @@
+
+package java.util;
+
+public interface Collection
+ {
+ public boolean add(Object o) throws UnsupportedOperationException,ClassCastException,IllegalArgumentException;
+ public boolean addAll(Collection c) throws UnsupportedOperationException,ClassCastException,IllegalArgumentException;
+ public void clear() throws UnsupportedOperationException;
+ public boolean contains(Object o);
+ public boolean containsAll(Collection c);
+ public boolean equals(Object o);
+ public int hashCode();
+ public boolean isEmpty();
+ public Iterator iterator();
+ public /*SK13*/boolean remove(Object o) throws UnsupportedOperationException;
+ public boolean removeAll(Collection c) throws UnsupportedOperationException;
+ public boolean retainAll(Collection c) throws UnsupportedOperationException;
+ public int size();
+ public Object[] toArray();
+ public Object[] toArray(Object[] a) throws ArrayStoreException;
+ }
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/Collections.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Collections.java
new file mode 100644
index 000000000..1b7f2e930
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Collections.java
@@ -0,0 +1,376 @@
+package java.util;
+
+import java.io.Serializable;
+
+public class Collections
+{
+ public static List EMPTY_LIST = new ArrayList();
+
+ private Collections()
+ {
+ }
+
+ public static Collection unmodifiableCollection(Collection c)
+ {
+ return new UnmodifiableCollection(c);
+ }
+
+ static class UnmodifiableCollection
+ implements Collection, Serializable
+ {
+ Collection c;
+
+ UnmodifiableCollection(Collection c)
+ {
+ this.c = c;
+ }
+
+ public int size()
+ {
+ return c.size();
+ }
+
+ public boolean isEmpty()
+ {
+ return c.isEmpty();
+ }
+
+ public boolean contains(Object o)
+ {
+ return c.contains(o);
+ }
+
+ public Object[] toArray()
+ {
+ return c.toArray();
+ }
+
+ public Object[] toArray(Object[] a)
+ {
+ return c.toArray(a);
+ }
+
+ public Iterator iterator()
+ {
+ return new Iterator()
+ {
+ Iterator i = c.iterator();
+
+ public boolean hasNext()
+ {
+ return i.hasNext();
+ }
+
+ public Object next()
+ {
+ return i.next();
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ public boolean add(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean remove(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean containsAll(Collection coll)
+ {
+ return c.containsAll(coll);
+ }
+
+ public boolean addAll(Collection coll)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean removeAll(Collection coll)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean retainAll(Collection coll)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void clear()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public String toString()
+ {
+ return c.toString();
+ }
+ }
+
+ public static Set unmodifiableSet(Set s)
+ {
+ return new UnmodifiableSet(s);
+ }
+
+ static class UnmodifiableSet
+ extends UnmodifiableCollection
+ implements Set, Serializable
+ {
+ UnmodifiableSet(Set s)
+ {
+ super(s);
+ }
+
+ public boolean equals(Object o)
+ {
+ return c.equals(o);
+ }
+
+ public int hashCode()
+ {
+ return c.hashCode();
+ }
+ }
+
+ public static List unmodifiableList(List list)
+ {
+ return new UnmodifiableList(list);
+ }
+
+ static class UnmodifiableList
+ extends UnmodifiableCollection
+ implements List
+ {
+ private List list;
+
+ UnmodifiableList(List list)
+ {
+ super(list);
+ this.list = list;
+ }
+
+ public boolean equals(Object o)
+ {
+ return list.equals(o);
+ }
+
+ public int hashCode()
+ {
+ return list.hashCode();
+ }
+
+ public Object get(int index)
+ {
+ return list.get(index);
+ }
+
+ public Object set(int index, Object element)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void add(int index, Object element)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object remove(int index)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public int indexOf(Object o)
+ {
+ return list.indexOf(o);
+ }
+
+ public int lastIndexOf(Object o)
+ {
+ return list.lastIndexOf(o);
+ }
+
+ public boolean addAll(int index, Collection c)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public ListIterator listIterator()
+ {
+ return listIterator(0);
+ }
+
+ public ListIterator listIterator(final int index)
+ {
+ return new ListIterator()
+ {
+ ListIterator i = list.listIterator(index);
+
+ public boolean hasNext()
+ {
+ return i.hasNext();
+ }
+
+ public Object next()
+ {
+ return i.next();
+ }
+
+ public boolean hasPrevious()
+ {
+ return i.hasPrevious();
+ }
+
+ public Object previous()
+ {
+ return i.previous();
+ }
+
+ public int nextIndex()
+ {
+ return i.nextIndex();
+ }
+
+ public int previousIndex()
+ {
+ return i.previousIndex();
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void set(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void add(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ public List subList(int fromIndex, int toIndex)
+ {
+ return new UnmodifiableList(list.subList(fromIndex, toIndex));
+ }
+ }
+
+ public static Enumeration enumeration(final Collection c)
+ {
+ return new Enumeration()
+ {
+ Iterator i = c.iterator();
+
+ public boolean hasMoreElements()
+ {
+ return i.hasNext();
+ }
+
+ public Object nextElement()
+ {
+ return i.next();
+ }
+ };
+ }
+
+ public static Map unmodifiableMap(Map s)
+ {
+ return new UnmodifiableMap(s);
+ }
+
+ static class UnmodifiableMap
+ implements Map
+ {
+ private Map c;
+
+ UnmodifiableMap(Map map)
+ {
+ this.c = map;
+ }
+
+ public int size()
+ {
+ return c.size();
+ }
+
+ public boolean isEmpty()
+ {
+ return c.isEmpty();
+ }
+
+ public boolean containsKey(Object o)
+ {
+ return c.containsKey(o);
+ }
+
+ public boolean containsValue(Object o)
+ {
+ return c.containsValue(o);
+ }
+
+ public Object get(Object o)
+ {
+ return c.get(o);
+ }
+
+ public Object put(Object o, Object o2)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object remove(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void putAll(Map map)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void clear()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Set keySet()
+ {
+ return Collections.unmodifiableSet(c.keySet());
+ }
+
+ public Collection values()
+ {
+ return new UnmodifiableCollection(c.values());
+ }
+
+ public Set entrySet()
+ {
+ return Collections.unmodifiableSet(c.entrySet());
+ }
+
+ public boolean equals(Object o)
+ {
+ return c.equals(o);
+ }
+
+ public int hashCode()
+ {
+ return c.hashCode();
+ }
+
+ public String toString()
+ {
+ return c.toString();
+ }
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/HashMap.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/HashMap.java
new file mode 100644
index 000000000..e9bdbda5d
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/HashMap.java
@@ -0,0 +1,285 @@
+package java.util;
+
+
+public class HashMap extends AbstractMap{
+
+ //////////////////////////////////////////////////////////////
+ ///// innere Klasse Null ////////////////////////////////////
+ //////////////////////////////////////////////////////////////
+public class Null extends Object
+ {
+ public Null()
+ {
+
+ }
+
+ public String toString()
+ {
+ return "Nullobject";
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////
+ ///// innere Klasse innerSet ////////////////////////////////////
+ //////////////////////////////////////////////////////////////
+
+ class ISet extends AbstractSet implements java.util.Set
+ {
+
+ Vector vec = null;
+
+ public ISet()
+ {
+
+ vec = new Vector();
+
+ }
+
+ public boolean add(Object o)
+ {
+ vec.addElement(o);
+ return true;
+ }
+
+ public int size()
+ {
+ return vec.size();
+ }
+
+ public Iterator iterator()
+ {
+ return new IIterator(vec);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////
+ ///// innere Klasse Iterator ////////////////////////////////////
+ //////////////////////////////////////////////////////////////
+ class IIterator implements java.util.Iterator
+ {
+ int index = 0;
+ Vector vec = null;
+ public IIterator(Vector ve)
+ {
+ vec = ve;
+ }
+
+ public boolean hasNext()
+ {
+ if (vec.size() > index) return true;
+ return false;
+ }
+
+ public Object next()
+ {
+ Object o = vec.elementAt(index);
+ if (o==Nullobject) o=null;
+ index++;
+ return o;
+
+ }
+
+ public void remove()
+ {
+ index--;
+ vec.removeElementAt(index);
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////
+ ///// innere Klasse Entry ////////////////////////////////////
+ //////////////////////////////////////////////////////////////
+
+
+ class Entry implements Map.Entry
+ {
+ public Object key=null;
+ public Object value=null;
+
+ public Entry(Object ke,Object valu)
+ {
+ key = ke;
+ value = valu;
+ }
+ public boolean equals(Object o)
+ {
+ if (value == ((Entry)o).value && key == ((Entry)o).key ) return true;
+ else return false;
+
+ }
+
+ public Object getValue()
+ {
+ return value;
+ }
+
+ public Object getKey()
+ {
+ return (Object)key;
+ }
+
+ public int hashCode()
+ {
+ return value.hashCode() + key.hashCode();
+
+ }
+
+ public Object setValue(Object valu)
+ {
+ value = (String)valu;
+ return this;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
+
+ private Hashtable m_HashTable=null;
+ private Null Nullobject = null;
+
+ public HashMap()
+ {
+ Nullobject = new Null();
+ m_HashTable=new Hashtable();
+ }
+
+ public HashMap(int initialCapacity)
+ {
+ Nullobject = new Null();
+ m_HashTable=new Hashtable(initialCapacity);
+ }
+
+ public HashMap(int initialCapacity, float loadFactor)
+ {
+ Nullobject = new Null();
+ m_HashTable=new Hashtable(initialCapacity, loadFactor);
+ }
+
+ public HashMap(Map t)
+ {
+ Nullobject = new Null();
+ m_HashTable=new Hashtable();
+ this.putAll(t);
+ }
+
+ public void clear()
+ {
+ m_HashTable.clear();
+ }
+
+ public Object clone()
+ {
+ HashMap hm=new HashMap();
+ hm.m_HashTable=(Hashtable)m_HashTable.clone();
+ return hm;
+ }
+
+ public boolean containsKey(Object key)
+ {
+ if (key == null) key = Nullobject;
+ boolean b = m_HashTable.containsKey(key);
+ return b;
+
+ }
+
+ public boolean containsValue(Object value)
+ {
+ if (value == null ) value = Nullobject;
+ boolean b = m_HashTable.contains(value);
+ return b;
+ }
+
+ public Set entrySet()
+ {
+
+ Object Key = null;
+ ISet s = new ISet();
+ Enumeration enum = m_HashTable.keys();
+ while (enum.hasMoreElements())
+ {
+ Key = enum.nextElement();
+ s.add(new Entry(Key,m_HashTable.get(Key)));
+ }
+ return s;
+ }
+
+ public Object get(Object key)
+ {
+
+ if (key==null) key= Nullobject;
+
+ Object o = m_HashTable.get(key);
+
+ if (o == Nullobject) o=null;
+
+ return o;
+ }
+
+ public boolean isEmpty()
+ {
+ return m_HashTable.isEmpty();
+ }
+
+ public Set keySet()
+ {
+ ISet s=new ISet();
+ Enumeration enum = m_HashTable.keys();
+
+ while (enum.hasMoreElements())
+ {
+ s.add(enum.nextElement());
+ }
+
+ return s;
+ }
+
+ public Object put(Object key, Object value)
+ {
+ if (key==null) key=Nullobject;
+ if (value==null) value = Nullobject;
+ return m_HashTable.put(key,value);
+ }
+
+ public void putAll(Map m)
+ {
+ Iterator it = m.entrySet().iterator();
+ Object key=null;
+ Object value=null;
+
+ while (it.hasNext())
+ {
+ Map.Entry me = (Map.Entry)it.next();
+ if (me.getKey() == null) key = Nullobject;
+ else key= me.getKey();
+ if (me.getValue()==null) value = Nullobject;
+ else value = me.getValue();
+ m_HashTable.put(key,value);
+ }
+ }
+
+ public Object remove(Object key)
+ {
+ return m_HashTable.remove(key);
+ }
+
+ public int size()
+ {
+ return m_HashTable.size();
+ }
+
+ public Collection values()
+ {
+
+ ISet s=new ISet();
+ Enumeration enum = m_HashTable.keys();
+
+ while (enum.hasMoreElements())
+ {
+ Object Key = enum.nextElement();
+ //s.add(((Map.Entry)m_HashTable.get(Key)).getValue());
+ s.add(m_HashTable.get(Key));
+ }
+ return s;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/HashSet.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/HashSet.java
new file mode 100644
index 000000000..5721cd20e
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/HashSet.java
@@ -0,0 +1,83 @@
+package java.util;
+
+import java.io.*;
+///*sk13*/import java.util.Hashtable;
+
+public class HashSet extends /*sk13*/AbstractSet
+ /*sk13*/ /*extends Hashmap*/
+
+{
+ private HashMap m_HashMap=null;
+
+ public HashSet()
+ {
+ m_HashMap=new HashMap();
+
+ }
+
+ public HashSet(Collection c)
+ {
+ m_HashMap=new HashMap(Math.max(11,c.size()*2));
+ addAll(c);
+
+ }
+
+ public HashSet(int initialCapacity, float loadFactor)
+ {
+ m_HashMap=new HashMap(initialCapacity,loadFactor);
+
+ }
+
+ public HashSet(int initialCapacity)
+ {
+ m_HashMap=new HashMap(initialCapacity);
+
+ }
+
+ public Iterator iterator()
+ {
+ return (m_HashMap.keySet()).iterator();
+ }
+
+ public int size()
+ {
+ return m_HashMap.size();
+ }
+
+ public boolean contains(Object o)
+ {
+ return m_HashMap.containsKey(o);
+ }
+
+ public boolean add(Object o)
+ {
+ if (!m_HashMap.containsValue(o))
+ {
+ m_HashMap.put(o, o);
+
+ return true;
+
+ }
+
+ return false;
+ }
+
+ public boolean remove(Object o)
+ {
+ return (m_HashMap.remove(o)!=null);
+ }
+
+ public void clear()
+ {
+ m_HashMap.clear();
+ }
+
+
+ public Object clone()
+ {
+ HashSet hs=new HashSet();
+ hs.m_HashMap=(HashMap)m_HashMap.clone();
+ return hs;
+ }
+
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/Iterator.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Iterator.java
new file mode 100644
index 000000000..9f977fe8c
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Iterator.java
@@ -0,0 +1,9 @@
+
+package java.util;
+
+public interface Iterator
+{
+ public abstract boolean hasNext();
+ public abstract Object next() throws NoSuchElementException;
+ public abstract void remove() throws UnsupportedOperationException,IllegalStateException;
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/List.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/List.java
new file mode 100644
index 000000000..ee5896ea8
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/List.java
@@ -0,0 +1,15 @@
+package java.util;
+
+public interface List extends Collection
+ {
+ void add(int index, Object element)throws UnsupportedOperationException,ClassCastException,IllegalArgumentException,IndexOutOfBoundsException;
+ boolean addAll(int index, Collection c) throws UnsupportedOperationException,ClassCastException,IllegalArgumentException,IndexOutOfBoundsException;
+ Object get(int index) throws IndexOutOfBoundsException;
+ int indexOf(Object o);
+ int lastIndexOf(Object o);
+ ListIterator listIterator();
+ ListIterator listIterator(int index)throws IndexOutOfBoundsException;
+ Object remove(int index)throws UnsupportedOperationException,IndexOutOfBoundsException;
+ Object set(int index, Object element) throws UnsupportedOperationException,ClassCastException,IllegalArgumentException,IndexOutOfBoundsException;
+ List subList(int fromIndex, int toIndex) throws IndexOutOfBoundsException;
+ }
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/ListIterator.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/ListIterator.java
new file mode 100644
index 000000000..15e17896e
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/ListIterator.java
@@ -0,0 +1,19 @@
+package java.util;
+
+/**
+ * Title:
+ * Description:
+ * Copyright: Copyright (c) 2001
+ * Company:
+ * @version 1.0
+ */
+
+public interface ListIterator extends Iterator
+ {
+ public boolean hasPrevious();
+ public Object previous() throws NoSuchElementException;
+ public int nextIndex();
+ public int previousIndex();
+ public void set(Object o) throws UnsupportedOperationException, ClassCastException, IllegalArgumentException,IllegalStateException;
+ public void add(Object o) throws UnsupportedOperationException, ClassCastException, IllegalArgumentException;
+ }
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/Map.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Map.java
new file mode 100644
index 000000000..e0040a383
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Map.java
@@ -0,0 +1,37 @@
+package java.util;
+
+/**
+ * Title:
+ * Description:
+ * Copyright: Copyright (c) 2001
+ * Company:
+ * @version 1.0
+ */
+
+public interface Map {
+
+ public static interface Entry
+ {
+ public Object getKey();
+ public Object getValue();
+ public Object setValue(Object value) throws UnsupportedOperationException, ClassCastException,IllegalArgumentException,NullPointerException;
+ public boolean equals(Object o);
+ public int hashCode();
+ };
+
+ public int size();
+ public boolean isEmpty();
+ public boolean containsKey(Object Key) throws ClassCastException,NullPointerException;
+ public boolean containsValue(Object value);
+ public Object get(Object key)throws ClassCastException,NullPointerException;
+ public Object put(Object key,Object value)throws UnsupportedOperationException, ClassCastException,IllegalArgumentException,NullPointerException;
+ public Object remove(Object key)throws UnsupportedOperationException;
+ public void putAll(Map t)throws UnsupportedOperationException, ClassCastException,IllegalArgumentException,NullPointerException;
+ public void clear()throws UnsupportedOperationException;
+ public Set keySet();
+ public Collection values();
+ public Set entrySet();
+ public boolean equals(Object o);
+ public int hashCode();
+
+ }
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/Set.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Set.java
new file mode 100644
index 000000000..e312d6b83
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Set.java
@@ -0,0 +1,26 @@
+
+package java.util;
+
+public interface Set extends Collection
+ {
+
+ public int size();
+ public boolean isEmpty();
+ public boolean contains(Object o);
+ public Iterator iterator();
+ public Object[] toArray();
+ public Object[] toArray(Object[] a);
+ public boolean add(Object o);
+ public boolean remove(Object o);
+ public boolean containsAll(Collection c);
+ public boolean addAll(Collection c);
+ public boolean retainAll(Collection c);
+ public boolean removeAll(Collection c);
+ public void clear();
+ public boolean equals(Object o);
+ public int hashCode();
+
+
+
+
+ }
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/util/Sublist.java b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Sublist.java
new file mode 100644
index 000000000..3f1a4a1bd
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/java/util/Sublist.java
@@ -0,0 +1,125 @@
+package java.util;
+
+/**
+ * Title:
+ * Description:
+ * Copyright: Copyright (c) 2001
+ * Company:
+ * @version 1.0
+ */
+
+public class Sublist extends AbstractList
+
+ {
+ AbstractList m_al=null;
+ int m_fromIndex=0;
+ int m_toIndex=0;
+ int size=0;
+
+ public Sublist(AbstractList ali,int fromIndex,int toIndex)
+ {
+ m_al=ali;
+ m_toIndex=toIndex;
+ m_fromIndex=fromIndex;
+ size = size();
+ }
+ public Object set(int index,Object o)
+ {
+ if (index < size)
+ {
+ o = m_al.set(index+m_fromIndex,o);
+ if (o != null)
+ {
+ size++;
+ m_toIndex++;
+ }
+ return o;
+ }
+ else throw new IndexOutOfBoundsException();
+ }
+
+ public Object get(int index) throws IndexOutOfBoundsException
+ {
+ if (index < size) return m_al.get(index+m_fromIndex);
+ else throw new IndexOutOfBoundsException();
+ }
+
+ public void add (int index,Object o)
+ {
+
+ if (index <= size)
+ {
+ m_al.add(index + m_fromIndex,o);
+ m_toIndex++;
+ size++;
+
+ }
+ else throw new IndexOutOfBoundsException();
+
+ }
+
+ public Object remove(int index,Object o)
+ {
+ if (index < size)
+ {
+ Object ob = m_al.remove(index + m_fromIndex);
+ if (ob !=null)
+ {
+ m_toIndex--;
+ size--;
+ }
+ return ob;
+ }
+ else throw new IndexOutOfBoundsException();
+ }
+
+ public boolean addAll(int index, Collection c)
+ {
+ if (index < size)
+ {
+ boolean bool = m_al.addAll(index + m_fromIndex,c);
+ if (bool)
+ {
+ int lange = c.size();
+ m_toIndex = m_toIndex + lange;
+ size = size + lange;
+ }
+ return bool;
+ }
+ else throw new IndexOutOfBoundsException();
+ }
+
+ public boolean addAll(Collection c)
+ {
+ boolean bool = m_al.addAll(m_toIndex,c);
+ if (bool)
+ {
+ int lange = c.size();
+ m_toIndex = m_toIndex + lange;
+ size = size + lange;
+ }
+ return bool;
+ }
+
+ public void removeRange (int from,int to)
+ {
+ if ((from <= to) && (from <= size) && (to <= size))
+ {
+ m_al.removeRange(from,to);
+ int lange = to - from;
+ m_toIndex = m_toIndex - lange;
+ size = size - lange;
+ }
+ else
+ {
+ if (from > to) throw new IllegalArgumentException();
+ else throw new IndexOutOfBoundsException();
+ }
+ }
+
+ public int size()
+ {
+ return (m_toIndex - m_fromIndex);
+ }
+
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1InputStream.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1InputStream.java
new file mode 100644
index 000000000..d8bacbc7c
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1InputStream.java
@@ -0,0 +1,466 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.spongycastle.util.io.Streams;
+
+/**
+ * a general purpose ASN.1 decoder - note: this class differs from the
+ * others in that it returns null after it has read the last object in
+ * the stream. If an ASN.1 NULL is encountered a DER/BER Null object is
+ * returned.
+ */
+public class ASN1InputStream
+ extends FilterInputStream
+ implements BERTags
+{
+ private int limit;
+ private boolean lazyEvaluate;
+
+ private byte[][] tmpBuffers;
+
+ public ASN1InputStream(
+ InputStream is)
+ {
+ this(is, StreamUtil.findLimit(is));
+ }
+
+ /**
+ * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+ * the stream is automatically limited to the length of the input array.
+ *
+ * @param input array containing ASN.1 encoded data.
+ */
+ public ASN1InputStream(
+ byte[] input)
+ {
+ this(new ByteArrayInputStream(input), input.length);
+ }
+
+ /**
+ * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+ * the stream is automatically limited to the length of the input array.
+ *
+ * @param input array containing ASN.1 encoded data.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ byte[] input,
+ boolean lazyEvaluate)
+ {
+ this(new ByteArrayInputStream(input), input.length, lazyEvaluate);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param limit maximum size of a DER encoded object.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ int limit)
+ {
+ this(input, limit, false);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
+ * objects such as sequences will be parsed lazily.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ boolean lazyEvaluate)
+ {
+ this(input, StreamUtil.findLimit(input), lazyEvaluate);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
+ * objects such as sequences will be parsed lazily.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param limit maximum size of a DER encoded object.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ int limit,
+ boolean lazyEvaluate)
+ {
+ super(input);
+ this.limit = limit;
+ this.lazyEvaluate = lazyEvaluate;
+ this.tmpBuffers = new byte[11][];
+ }
+
+ int getLimit()
+ {
+ return limit;
+ }
+
+ protected int readLength()
+ throws IOException
+ {
+ return readLength(this, limit);
+ }
+
+ protected void readFully(
+ byte[] bytes)
+ throws IOException
+ {
+ if (Streams.readFully(this, bytes) != bytes.length)
+ {
+ throw new EOFException("EOF encountered in middle of object");
+ }
+ }
+
+ /**
+ * build an object given its tag and the number of bytes to construct it from.
+ */
+ protected ASN1Primitive buildObject(
+ int tag,
+ int tagNo,
+ int length)
+ throws IOException
+ {
+ boolean isConstructed = (tag & CONSTRUCTED) != 0;
+
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this, length);
+
+ if ((tag & APPLICATION) != 0)
+ {
+ return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
+ }
+
+ if ((tag & TAGGED) != 0)
+ {
+ return new ASN1StreamParser(defIn).readTaggedObject(isConstructed, tagNo);
+ }
+
+ if (isConstructed)
+ {
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case OCTET_STRING:
+ //
+ // yes, people actually do this...
+ //
+ ASN1EncodableVector v = buildDEREncodableVector(defIn);
+ ASN1OctetString[] strings = new ASN1OctetString[v.size()];
+
+ for (int i = 0; i != strings.length; i++)
+ {
+ strings[i] = (ASN1OctetString)v.get(i);
+ }
+
+ return new BEROctetString(strings);
+ case SEQUENCE:
+ if (lazyEvaluate)
+ {
+ return new LazyEncodedSequence(defIn.toByteArray());
+ }
+ else
+ {
+ return DERFactory.createSequence(buildDEREncodableVector(defIn));
+ }
+ case SET:
+ return DERFactory.createSet(buildDEREncodableVector(defIn));
+ case EXTERNAL:
+ return new DERExternal(buildDEREncodableVector(defIn));
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
+ }
+ }
+
+ return createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
+ }
+
+ ASN1EncodableVector buildEncodableVector()
+ throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ ASN1Primitive o;
+
+ while ((o = readObject()) != null)
+ {
+ v.add(o);
+ }
+
+ return v;
+ }
+
+ ASN1EncodableVector buildDEREncodableVector(
+ DefiniteLengthInputStream dIn) throws IOException
+ {
+ return new ASN1InputStream(dIn).buildEncodableVector();
+ }
+
+ public ASN1Primitive readObject()
+ throws IOException
+ {
+ int tag = read();
+ if (tag <= 0)
+ {
+ if (tag == 0)
+ {
+ throw new IOException("unexpected end-of-contents marker");
+ }
+
+ return null;
+ }
+
+ //
+ // calculate tag number
+ //
+ int tagNo = readTagNumber(this, tag);
+
+ boolean isConstructed = (tag & CONSTRUCTED) != 0;
+
+ //
+ // calculate length
+ //
+ int length = readLength();
+
+ if (length < 0) // indefinite length method
+ {
+ if (!isConstructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this, limit);
+ ASN1StreamParser sp = new ASN1StreamParser(indIn, limit);
+
+ if ((tag & APPLICATION) != 0)
+ {
+ return new BERApplicationSpecificParser(tagNo, sp).getLoadedObject();
+ }
+
+ if ((tag & TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(true, tagNo, sp).getLoadedObject();
+ }
+
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case OCTET_STRING:
+ return new BEROctetStringParser(sp).getLoadedObject();
+ case SEQUENCE:
+ return new BERSequenceParser(sp).getLoadedObject();
+ case SET:
+ return new BERSetParser(sp).getLoadedObject();
+ case EXTERNAL:
+ return new DERExternalParser(sp).getLoadedObject();
+ default:
+ throw new IOException("unknown BER object encountered");
+ }
+ }
+ else
+ {
+ try
+ {
+ return buildObject(tag, tagNo, length);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ASN1Exception("corrupted stream detected", e);
+ }
+ }
+ }
+
+ static int readTagNumber(InputStream s, int tag)
+ throws IOException
+ {
+ int tagNo = tag & 0x1f;
+
+ //
+ // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+ //
+ if (tagNo == 0x1f)
+ {
+ tagNo = 0;
+
+ int b = s.read();
+
+ // 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 IOException("corrupted stream - invalid high tag number found");
+ }
+
+ while ((b >= 0) && ((b & 0x80) != 0))
+ {
+ tagNo |= (b & 0x7f);
+ tagNo <<= 7;
+ b = s.read();
+ }
+
+ if (b < 0)
+ {
+ throw new EOFException("EOF found inside tag value.");
+ }
+
+ tagNo |= (b & 0x7f);
+ }
+
+ return tagNo;
+ }
+
+ static int readLength(InputStream s, int limit)
+ throws IOException
+ {
+ int length = s.read();
+ if (length < 0)
+ {
+ throw new EOFException("EOF found when length expected");
+ }
+
+ if (length == 0x80)
+ {
+ return -1; // indefinite-length encoding
+ }
+
+ if (length > 127)
+ {
+ int size = length & 0x7f;
+
+ // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+ if (size > 4)
+ {
+ throw new IOException("DER length more than 4 bytes: " + size);
+ }
+
+ length = 0;
+ for (int i = 0; i < size; i++)
+ {
+ int next = s.read();
+
+ if (next < 0)
+ {
+ throw new EOFException("EOF found reading length");
+ }
+
+ length = (length << 8) + next;
+ }
+
+ if (length < 0)
+ {
+ throw new IOException("corrupted stream - negative length found");
+ }
+
+ if (length >= limit) // after all we must have read at least 1 byte
+ {
+ throw new IOException("corrupted stream - out of bounds length found");
+ }
+ }
+
+ return length;
+ }
+
+ private static byte[] getBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
+ throws IOException
+ {
+ int len = defIn.getRemaining();
+ if (defIn.getRemaining() < tmpBuffers.length)
+ {
+ byte[] buf = tmpBuffers[len];
+
+ if (buf == null)
+ {
+ buf = tmpBuffers[len] = new byte[len];
+ }
+
+ Streams.readFully(defIn, buf);
+
+ return buf;
+ }
+ else
+ {
+ return defIn.toByteArray();
+ }
+ }
+
+ private static char[] getBMPCharBuffer(DefiniteLengthInputStream defIn)
+ throws IOException
+ {
+ int len = defIn.getRemaining() / 2;
+ char[] buf = new char[len];
+ int totalRead = 0;
+ while (totalRead < len)
+ {
+ int ch1 = defIn.read();
+ if (ch1 < 0)
+ {
+ break;
+ }
+ int ch2 = defIn.read();
+ if (ch2 < 0)
+ {
+ break;
+ }
+ buf[totalRead++] = (char)((ch1 << 8) | (ch2 & 0xff));
+ }
+
+ return buf;
+ }
+
+ static ASN1Primitive createPrimitiveDERObject(
+ int tagNo,
+ DefiniteLengthInputStream defIn,
+ byte[][] tmpBuffers)
+ throws IOException
+ {
+ switch (tagNo)
+ {
+ case BIT_STRING:
+ return DERBitString.fromInputStream(defIn.getRemaining(), defIn);
+ case BMP_STRING:
+ return new DERBMPString(getBMPCharBuffer(defIn));
+ case BOOLEAN:
+ return ASN1Boolean.fromOctetString(getBuffer(defIn, tmpBuffers));
+ case ENUMERATED:
+ return ASN1Enumerated.fromOctetString(getBuffer(defIn, tmpBuffers));
+ case GENERALIZED_TIME:
+ return new ASN1GeneralizedTime(defIn.toByteArray());
+ case GENERAL_STRING:
+ return new DERGeneralString(defIn.toByteArray());
+ case IA5_STRING:
+ return new DERIA5String(defIn.toByteArray());
+ case INTEGER:
+ return new ASN1Integer(defIn.toByteArray());
+ case NULL:
+ return DERNull.INSTANCE; // actual content is ignored (enforce 0 length?)
+ case NUMERIC_STRING:
+ return new DERNumericString(defIn.toByteArray());
+ case OBJECT_IDENTIFIER:
+ return ASN1ObjectIdentifier.fromOctetString(getBuffer(defIn, tmpBuffers));
+ case OCTET_STRING:
+ return new DEROctetString(defIn.toByteArray());
+ case PRINTABLE_STRING:
+ return new DERPrintableString(defIn.toByteArray());
+ case T61_STRING:
+ return new DERT61String(defIn.toByteArray());
+ case UNIVERSAL_STRING:
+ return new DERUniversalString(defIn.toByteArray());
+ case UTC_TIME:
+ return new ASN1UTCTime(defIn.toByteArray());
+ case UTF8_STRING:
+ return new DERUTF8String(defIn.toByteArray());
+ case VISIBLE_STRING:
+ return new DERVisibleString(defIn.toByteArray());
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
+ }
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1StreamParser.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1StreamParser.java
new file mode 100644
index 000000000..bbaef0565
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1StreamParser.java
@@ -0,0 +1,247 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ASN1StreamParser
+{
+ private InputStream _in;
+ private int _limit;
+ private byte[][] tmpBuffers;
+
+ public ASN1StreamParser(
+ InputStream in)
+ {
+ this(in, StreamUtil.findLimit(in));
+ }
+
+ public ASN1StreamParser(
+ InputStream in,
+ int limit)
+ {
+ this._in = in;
+ this._limit = limit;
+
+ this.tmpBuffers = new byte[11][];
+ }
+
+ public ASN1StreamParser(
+ byte[] encoding)
+ {
+ this(new ByteArrayInputStream(encoding), encoding.length);
+ }
+
+ ASN1Encodable readIndef(int tagValue) throws IOException
+ {
+ // Note: INDEF => CONSTRUCTED
+
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagValue)
+ {
+ case BERTags.EXTERNAL:
+ return new DERExternalParser(this);
+ case BERTags.OCTET_STRING:
+ return new BEROctetStringParser(this);
+ case BERTags.SEQUENCE:
+ return new BERSequenceParser(this);
+ case BERTags.SET:
+ return new BERSetParser(this);
+ default:
+ throw new ASN1Exception("unknown BER object encountered: 0x" + Integer.toHexString(tagValue));
+ }
+ }
+
+ ASN1Encodable readImplicit(boolean constructed, int tag) throws IOException
+ {
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ if (!constructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ return readIndef(tag);
+ }
+
+ if (constructed)
+ {
+ switch (tag)
+ {
+ case BERTags.SET:
+ return new DERSetParser(this);
+ case BERTags.SEQUENCE:
+ return new DERSequenceParser(this);
+ case BERTags.OCTET_STRING:
+ return new BEROctetStringParser(this);
+ }
+ }
+ else
+ {
+ switch (tag)
+ {
+ case BERTags.SET:
+ throw new ASN1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)");
+ case BERTags.SEQUENCE:
+ throw new ASN1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)");
+ case BERTags.OCTET_STRING:
+ return new DEROctetStringParser((DefiniteLengthInputStream)_in);
+ }
+ }
+
+ // TODO ASN1Exception
+ throw new RuntimeException("implicit tagging not implemented");
+ }
+
+ ASN1Primitive readTaggedObject(boolean constructed, int tag) throws IOException
+ {
+ if (!constructed)
+ {
+ // Note: !CONSTRUCTED => IMPLICIT
+ DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
+ return new DERTaggedObject(false, tag, new DEROctetString(defIn.toByteArray()));
+ }
+
+ ASN1EncodableVector v = readVector();
+
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ return v.size() == 1
+ ? new BERTaggedObject(true, tag, v.get(0))
+ : new BERTaggedObject(false, tag, BERFactory.createSequence(v));
+ }
+
+ return v.size() == 1
+ ? new DERTaggedObject(true, tag, v.get(0))
+ : new DERTaggedObject(false, tag, DERFactory.createSequence(v));
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ int tag = _in.read();
+ if (tag == -1)
+ {
+ return null;
+ }
+
+ //
+ // turn of looking for "00" while we resolve the tag
+ //
+ set00Check(false);
+
+ //
+ // calculate tag number
+ //
+ int tagNo = ASN1InputStream.readTagNumber(_in, tag);
+
+ boolean isConstructed = (tag & BERTags.CONSTRUCTED) != 0;
+
+ //
+ // calculate length
+ //
+ int length = ASN1InputStream.readLength(_in, _limit);
+
+ if (length < 0) // indefinite length method
+ {
+ if (!isConstructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit);
+ ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
+
+ if ((tag & BERTags.APPLICATION) != 0)
+ {
+ return new BERApplicationSpecificParser(tagNo, sp);
+ }
+
+ if ((tag & BERTags.TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(true, tagNo, sp);
+ }
+
+ return sp.readIndef(tagNo);
+ }
+ else
+ {
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
+
+ if ((tag & BERTags.APPLICATION) != 0)
+ {
+ return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
+ }
+
+ if ((tag & BERTags.TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(isConstructed, tagNo, new ASN1StreamParser(defIn));
+ }
+
+ if (isConstructed)
+ {
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case BERTags.OCTET_STRING:
+ //
+ // yes, people actually do this...
+ //
+ return new BEROctetStringParser(new ASN1StreamParser(defIn));
+ case BERTags.SEQUENCE:
+ return new DERSequenceParser(new ASN1StreamParser(defIn));
+ case BERTags.SET:
+ return new DERSetParser(new ASN1StreamParser(defIn));
+ case BERTags.EXTERNAL:
+ return new DERExternalParser(new ASN1StreamParser(defIn));
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
+ }
+ }
+
+ // Some primitive encodings can be handled by parsers too...
+ switch (tagNo)
+ {
+ case BERTags.OCTET_STRING:
+ return new DEROctetStringParser(defIn);
+ }
+
+ try
+ {
+ return ASN1InputStream.createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ASN1Exception("corrupted stream detected", e);
+ }
+ }
+ }
+
+ private void set00Check(boolean enabled)
+ {
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ ((IndefiniteLengthInputStream)_in).setEofOn00(enabled);
+ }
+ }
+
+ ASN1EncodableVector readVector() throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ ASN1Encodable obj;
+ while ((obj = readObject()) != null)
+ {
+ if (obj instanceof InMemoryRepresentable)
+ {
+ v.add(((InMemoryRepresentable)obj).getLoadedObject());
+ }
+ else
+ {
+ v.add(obj.toASN1Primitive());
+ }
+ }
+
+ return v;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/DERApplicationSpecific.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/DERApplicationSpecific.java
new file mode 100644
index 000000000..30c66ab65
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/DERApplicationSpecific.java
@@ -0,0 +1,276 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * Base class for an application specific object
+ */
+public class DERApplicationSpecific
+ extends ASN1Primitive
+{
+ private boolean isConstructed;
+ private int tag;
+ private byte[] octets;
+
+ DERApplicationSpecific(
+ boolean isConstructed,
+ int tag,
+ byte[] octets)
+ {
+ this.isConstructed = isConstructed;
+ this.tag = tag;
+ this.octets = octets;
+ }
+
+ public DERApplicationSpecific(
+ int tag,
+ byte[] octets)
+ {
+ this(false, tag, octets);
+ }
+
+ public DERApplicationSpecific(
+ int tag,
+ ASN1Encodable object)
+ throws IOException
+ {
+ this(true, tag, object);
+ }
+
+ public DERApplicationSpecific(
+ boolean explicit,
+ int tag,
+ ASN1Encodable object)
+ throws IOException
+ {
+ ASN1Primitive primitive = object.toASN1Primitive();
+
+ byte[] data = primitive.getEncoded(ASN1Encoding.DER);
+
+ this.isConstructed = explicit || (primitive instanceof ASN1Set || primitive instanceof ASN1Sequence);
+ this.tag = tag;
+
+ if (explicit)
+ {
+ this.octets = data;
+ }
+ else
+ {
+ int lenBytes = getLengthOfHeader(data);
+ byte[] tmp = new byte[data.length - lenBytes];
+ System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
+ this.octets = tmp;
+ }
+ }
+
+ public DERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
+ {
+ this.tag = tagNo;
+ this.isConstructed = true;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != vec.size(); i++)
+ {
+ try
+ {
+ bOut.write(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.DER));
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("malformed object: " + e, e);
+ }
+ }
+ this.octets = bOut.toByteArray();
+ }
+
+ public static DERApplicationSpecific getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DERApplicationSpecific)
+ {
+ return (DERApplicationSpecific)obj;
+ }
+ else if (obj instanceof byte[])
+ {
+ try
+ {
+ return DERApplicationSpecific.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct object from byte[]: " + e.getMessage());
+ }
+ }
+ else if (obj instanceof ASN1Encodable)
+ {
+ ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (primitive instanceof ASN1Sequence)
+ {
+ return (DERApplicationSpecific)primitive;
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ private int getLengthOfHeader(byte[] data)
+ {
+ int length = data[1] & 0xff; // TODO: assumes 1 byte tag
+
+ if (length == 0x80)
+ {
+ return 2; // indefinite-length encoding
+ }
+
+ if (length > 127)
+ {
+ int size = length & 0x7f;
+
+ // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+ if (size > 4)
+ {
+ throw new IllegalStateException("DER length more than 4 bytes: " + size);
+ }
+
+ return size + 2;
+ }
+
+ return 2;
+ }
+
+ public boolean isConstructed()
+ {
+ return isConstructed;
+ }
+
+ public byte[] getContents()
+ {
+ return octets;
+ }
+
+ public int getApplicationTag()
+ {
+ return tag;
+ }
+
+ /**
+ * Return the enclosed object assuming explicit tagging.
+ *
+ * @return the resulting object
+ * @throws IOException if reconstruction fails.
+ */
+ public ASN1Primitive getObject()
+ throws IOException
+ {
+ return new ASN1InputStream(getContents()).readObject();
+ }
+
+ /**
+ * Return the enclosed object assuming implicit tagging.
+ *
+ * @param derTagNo the type tag that should be applied to the object's contents.
+ * @return the resulting object
+ * @throws IOException if reconstruction fails.
+ */
+ public ASN1Primitive getObject(int derTagNo)
+ throws IOException
+ {
+ if (derTagNo >= 0x1f)
+ {
+ throw new IOException("unsupported tag number");
+ }
+
+ byte[] orig = this.getEncoded();
+ byte[] tmp = replaceTagNumber(derTagNo, orig);
+
+ if ((orig[0] & BERTags.CONSTRUCTED) != 0)
+ {
+ tmp[0] |= BERTags.CONSTRUCTED;
+ }
+
+ return new ASN1InputStream(tmp).readObject();
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ return StreamUtil.calculateTagLength(tag) + StreamUtil.calculateBodyLength(octets.length) + octets.length;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.asn1.ASN1Primitive#encode(org.spongycastle.asn1.DEROutputStream)
+ */
+ void encode(ASN1OutputStream out) throws IOException
+ {
+ int classBits = BERTags.APPLICATION;
+ if (isConstructed)
+ {
+ classBits |= BERTags.CONSTRUCTED;
+ }
+
+ out.writeEncoded(classBits, tag, octets);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERApplicationSpecific))
+ {
+ return false;
+ }
+
+ DERApplicationSpecific other = (DERApplicationSpecific)o;
+
+ return isConstructed == other.isConstructed
+ && tag == other.tag
+ && Arrays.areEqual(octets, other.octets);
+ }
+
+ public int hashCode()
+ {
+ return (isConstructed ? 1 : 0) ^ tag ^ Arrays.hashCode(octets);
+ }
+
+ private byte[] replaceTagNumber(int newTag, byte[] input)
+ throws IOException
+ {
+ 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 ASN1ParsingException("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];
+
+ System.arraycopy(input, index, tmp, 1, tmp.length - 1);
+
+ tmp[0] = (byte)newTag;
+
+ return tmp;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/BCStyle.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/BCStyle.java
new file mode 100644
index 000000000..2591e4cdc
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/BCStyle.java
@@ -0,0 +1,481 @@
+package org.spongycastle.asn1.x500.style;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x500.AttributeTypeAndValue;
+import org.spongycastle.asn1.x500.RDN;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x500.X500NameStyle;
+import org.spongycastle.asn1.x509.X509ObjectIdentifiers;
+
+public class BCStyle
+ implements X500NameStyle
+{
+ /**
+ * country code - StringType(SIZE(2))
+ */
+ public static final ASN1ObjectIdentifier C = new ASN1ObjectIdentifier("2.5.4.6");
+
+ /**
+ * organization - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier O = new ASN1ObjectIdentifier("2.5.4.10");
+
+ /**
+ * organizational unit name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier OU = new ASN1ObjectIdentifier("2.5.4.11");
+
+ /**
+ * Title
+ */
+ public static final ASN1ObjectIdentifier T = new ASN1ObjectIdentifier("2.5.4.12");
+
+ /**
+ * common name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier CN = new ASN1ObjectIdentifier("2.5.4.3");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier SN = new ASN1ObjectIdentifier("2.5.4.5");
+
+ /**
+ * street - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier STREET = new ASN1ObjectIdentifier("2.5.4.9");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier SERIALNUMBER = SN;
+
+ /**
+ * locality name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier L = new ASN1ObjectIdentifier("2.5.4.7");
+
+ /**
+ * state, or province name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier ST = new ASN1ObjectIdentifier("2.5.4.8");
+
+ /**
+ * Naming attributes of type X520name
+ */
+ public static final ASN1ObjectIdentifier SURNAME = new ASN1ObjectIdentifier("2.5.4.4");
+ public static final ASN1ObjectIdentifier GIVENNAME = new ASN1ObjectIdentifier("2.5.4.42");
+ public static final ASN1ObjectIdentifier INITIALS = new ASN1ObjectIdentifier("2.5.4.43");
+ public static final ASN1ObjectIdentifier GENERATION = new ASN1ObjectIdentifier("2.5.4.44");
+ public static final ASN1ObjectIdentifier UNIQUE_IDENTIFIER = new ASN1ObjectIdentifier("2.5.4.45");
+
+ /**
+ * businessCategory - DirectoryString(SIZE(1..128)
+ */
+ public static final ASN1ObjectIdentifier BUSINESS_CATEGORY = new ASN1ObjectIdentifier(
+ "2.5.4.15");
+
+ /**
+ * postalCode - DirectoryString(SIZE(1..40)
+ */
+ public static final ASN1ObjectIdentifier POSTAL_CODE = new ASN1ObjectIdentifier(
+ "2.5.4.17");
+
+ /**
+ * dnQualifier - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier DN_QUALIFIER = new ASN1ObjectIdentifier(
+ "2.5.4.46");
+
+ /**
+ * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier PSEUDONYM = new ASN1ObjectIdentifier(
+ "2.5.4.65");
+
+
+ /**
+ * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
+ */
+ public static final ASN1ObjectIdentifier DATE_OF_BIRTH = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.1");
+
+ /**
+ * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
+ */
+ public static final ASN1ObjectIdentifier PLACE_OF_BIRTH = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.2");
+
+ /**
+ * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
+ */
+ public static final ASN1ObjectIdentifier GENDER = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.3");
+
+ /**
+ * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static final ASN1ObjectIdentifier COUNTRY_OF_CITIZENSHIP = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.4");
+
+ /**
+ * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static final ASN1ObjectIdentifier COUNTRY_OF_RESIDENCE = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.5");
+
+
+ /**
+ * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier NAME_AT_BIRTH = new ASN1ObjectIdentifier("1.3.36.8.3.14");
+
+ /**
+ * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
+ * DirectoryString(SIZE(1..30))
+ */
+ public static final ASN1ObjectIdentifier POSTAL_ADDRESS = new ASN1ObjectIdentifier("2.5.4.16");
+
+ /**
+ * RFC 2256 dmdName
+ */
+ public static final ASN1ObjectIdentifier DMD_NAME = new ASN1ObjectIdentifier("2.5.4.54");
+
+ /**
+ * id-at-telephoneNumber
+ */
+ public static final ASN1ObjectIdentifier TELEPHONE_NUMBER = X509ObjectIdentifiers.id_at_telephoneNumber;
+
+ /**
+ * id-at-name
+ */
+ public static final ASN1ObjectIdentifier NAME = X509ObjectIdentifiers.id_at_name;
+
+ /**
+ * Email address (RSA PKCS#9 extension) - IA5String.
+ * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
+ */
+ public static final ASN1ObjectIdentifier EmailAddress = PKCSObjectIdentifiers.pkcs_9_at_emailAddress;
+
+ /**
+ * more from PKCS#9
+ */
+ public static final ASN1ObjectIdentifier UnstructuredName = PKCSObjectIdentifiers.pkcs_9_at_unstructuredName;
+ public static final ASN1ObjectIdentifier UnstructuredAddress = PKCSObjectIdentifiers.pkcs_9_at_unstructuredAddress;
+
+ /**
+ * email address in Verisign certificates
+ */
+ public static final ASN1ObjectIdentifier E = EmailAddress;
+
+ /*
+ * others...
+ */
+ public static final ASN1ObjectIdentifier DC = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
+
+ /**
+ * LDAP User id.
+ */
+ public static final ASN1ObjectIdentifier UID = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
+
+ /**
+ * default look up table translating OID values into their common symbols following
+ * the convention in RFC 2253 with a few extras
+ */
+ private static final Hashtable DefaultSymbols = new Hashtable();
+
+ /**
+ * look up table translating common symbols into their OIDS.
+ */
+ private static final Hashtable DefaultLookUp = new Hashtable();
+
+ static
+ {
+ DefaultSymbols.put(C, "C");
+ DefaultSymbols.put(O, "O");
+ DefaultSymbols.put(T, "T");
+ DefaultSymbols.put(OU, "OU");
+ DefaultSymbols.put(CN, "CN");
+ DefaultSymbols.put(L, "L");
+ DefaultSymbols.put(ST, "ST");
+ DefaultSymbols.put(SN, "SERIALNUMBER");
+ DefaultSymbols.put(EmailAddress, "E");
+ DefaultSymbols.put(DC, "DC");
+ DefaultSymbols.put(UID, "UID");
+ DefaultSymbols.put(STREET, "STREET");
+ DefaultSymbols.put(SURNAME, "SURNAME");
+ DefaultSymbols.put(GIVENNAME, "GIVENNAME");
+ DefaultSymbols.put(INITIALS, "INITIALS");
+ DefaultSymbols.put(GENERATION, "GENERATION");
+ DefaultSymbols.put(UnstructuredAddress, "unstructuredAddress");
+ DefaultSymbols.put(UnstructuredName, "unstructuredName");
+ DefaultSymbols.put(UNIQUE_IDENTIFIER, "UniqueIdentifier");
+ DefaultSymbols.put(DN_QUALIFIER, "DN");
+ DefaultSymbols.put(PSEUDONYM, "Pseudonym");
+ DefaultSymbols.put(POSTAL_ADDRESS, "PostalAddress");
+ DefaultSymbols.put(NAME_AT_BIRTH, "NameAtBirth");
+ DefaultSymbols.put(COUNTRY_OF_CITIZENSHIP, "CountryOfCitizenship");
+ DefaultSymbols.put(COUNTRY_OF_RESIDENCE, "CountryOfResidence");
+ DefaultSymbols.put(GENDER, "Gender");
+ DefaultSymbols.put(PLACE_OF_BIRTH, "PlaceOfBirth");
+ DefaultSymbols.put(DATE_OF_BIRTH, "DateOfBirth");
+ DefaultSymbols.put(POSTAL_CODE, "PostalCode");
+ DefaultSymbols.put(BUSINESS_CATEGORY, "BusinessCategory");
+ DefaultSymbols.put(TELEPHONE_NUMBER, "TelephoneNumber");
+ DefaultSymbols.put(NAME, "Name");
+
+ DefaultLookUp.put("c", C);
+ DefaultLookUp.put("o", O);
+ DefaultLookUp.put("t", T);
+ DefaultLookUp.put("ou", OU);
+ DefaultLookUp.put("cn", CN);
+ DefaultLookUp.put("l", L);
+ DefaultLookUp.put("st", ST);
+ DefaultLookUp.put("sn", SN);
+ DefaultLookUp.put("serialnumber", SN);
+ DefaultLookUp.put("street", STREET);
+ DefaultLookUp.put("emailaddress", E);
+ DefaultLookUp.put("dc", DC);
+ DefaultLookUp.put("e", E);
+ DefaultLookUp.put("uid", UID);
+ DefaultLookUp.put("surname", SURNAME);
+ DefaultLookUp.put("givenname", GIVENNAME);
+ DefaultLookUp.put("initials", INITIALS);
+ DefaultLookUp.put("generation", GENERATION);
+ DefaultLookUp.put("unstructuredaddress", UnstructuredAddress);
+ DefaultLookUp.put("unstructuredname", UnstructuredName);
+ DefaultLookUp.put("uniqueidentifier", UNIQUE_IDENTIFIER);
+ DefaultLookUp.put("dn", DN_QUALIFIER);
+ DefaultLookUp.put("pseudonym", PSEUDONYM);
+ DefaultLookUp.put("postaladdress", POSTAL_ADDRESS);
+ DefaultLookUp.put("nameofbirth", NAME_AT_BIRTH);
+ DefaultLookUp.put("countryofcitizenship", COUNTRY_OF_CITIZENSHIP);
+ DefaultLookUp.put("countryofresidence", COUNTRY_OF_RESIDENCE);
+ DefaultLookUp.put("gender", GENDER);
+ DefaultLookUp.put("placeofbirth", PLACE_OF_BIRTH);
+ DefaultLookUp.put("dateofbirth", DATE_OF_BIRTH);
+ DefaultLookUp.put("postalcode", POSTAL_CODE);
+ DefaultLookUp.put("businesscategory", BUSINESS_CATEGORY);
+ DefaultLookUp.put("telephonenumber", TELEPHONE_NUMBER);
+ DefaultLookUp.put("name", NAME);
+ }
+
+ /**
+ * Singleton instance.
+ */
+ public static final X500NameStyle INSTANCE = new BCStyle();
+
+ protected Hashtable defaultLookUp;
+ protected Hashtable defaultSymbols;
+
+ protected BCStyle()
+ {
+ defaultSymbols = copyHashTable(DefaultSymbols);
+ defaultLookUp = copyHashTable(DefaultLookUp);
+ }
+
+ public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
+ {
+ if (value.length() != 0 && value.charAt(0) == '#')
+ {
+ try
+ {
+ return IETFUtils.valueFromHexString(value, 1);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("can't recode value for oid " + oid.getId());
+ }
+ }
+ else
+ {
+ if (value.length() != 0 && value.charAt(0) == '\\')
+ {
+ value = value.substring(1);
+ }
+ if (oid.equals(EmailAddress) || oid.equals(DC))
+ {
+ return new DERIA5String(value);
+ }
+ else if (oid.equals(DATE_OF_BIRTH)) // accept time string as well as # (for compatibility)
+ {
+ return new ASN1GeneralizedTime(value);
+ }
+ else if (oid.equals(C) || oid.equals(SN) || oid.equals(DN_QUALIFIER)
+ || oid.equals(TELEPHONE_NUMBER))
+ {
+ return new DERPrintableString(value);
+ }
+ }
+
+ return new DERUTF8String(value);
+ }
+
+ public String oidToDisplayName(ASN1ObjectIdentifier oid)
+ {
+ return (String)DefaultSymbols.get(oid);
+ }
+
+ public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
+ {
+ return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
+ }
+
+ public ASN1ObjectIdentifier attrNameToOID(String attrName)
+ {
+ return IETFUtils.decodeAttrName(attrName, defaultLookUp);
+ }
+
+ public boolean areEqual(X500Name name1, X500Name name2)
+ {
+ RDN[] rdns1 = name1.getRDNs();
+ RDN[] rdns2 = name2.getRDNs();
+
+ if (rdns1.length != rdns2.length)
+ {
+ return false;
+ }
+
+ boolean reverse = false;
+
+ if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null)
+ {
+ reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward
+ }
+
+ for (int i = 0; i != rdns1.length; i++)
+ {
+ if (!foundMatch(reverse, rdns1[i], rdns2))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs)
+ {
+ if (reverse)
+ {
+ for (int i = possRDNs.length - 1; i >= 0; i--)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i != possRDNs.length; i++)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected boolean rdnAreEqual(RDN rdn1, RDN rdn2)
+ {
+ return IETFUtils.rDNAreEqual(rdn1, rdn2);
+ }
+
+ public RDN[] fromString(String dirName)
+ {
+ return IETFUtils.rDNsFromString(dirName, this);
+ }
+
+ public int calculateHashCode(X500Name name)
+ {
+ int hashCodeValue = 0;
+ RDN[] rdns = name.getRDNs();
+
+ // this needs to be order independent, like equals
+ for (int i = 0; i != rdns.length; i++)
+ {
+ if (rdns[i].isMultiValued())
+ {
+ AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
+
+ for (int j = 0; j != atv.length; j++)
+ {
+ hashCodeValue ^= atv[j].getType().hashCode();
+ hashCodeValue ^= calcHashCode(atv[j].getValue());
+ }
+ }
+ else
+ {
+ hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
+ hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
+ }
+ }
+
+ return hashCodeValue;
+ }
+
+ private int calcHashCode(ASN1Encodable enc)
+ {
+ String value = IETFUtils.valueToString(enc);
+
+ value = IETFUtils.canonicalize(value);
+
+ return value.hashCode();
+ }
+
+ public String toString(X500Name name)
+ {
+ StringBuffer buf = new StringBuffer();
+ boolean first = true;
+
+ RDN[] rdns = name.getRDNs();
+
+ for (int i = 0; i < rdns.length; i++)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append(',');
+ }
+
+ IETFUtils.appendRDN(buf, rdns[i], defaultSymbols);
+ }
+
+ return buf.toString();
+ }
+
+ private static Hashtable copyHashTable(Hashtable paramsMap)
+ {
+ Hashtable newTable = new Hashtable();
+
+ Enumeration keys = paramsMap.keys();
+ while (keys.hasMoreElements())
+ {
+ Object key = keys.nextElement();
+ newTable.put(key, paramsMap.get(key));
+ }
+
+ return newTable;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/RFC4519Style.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/RFC4519Style.java
new file mode 100644
index 000000000..0fd117850
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/RFC4519Style.java
@@ -0,0 +1,380 @@
+package org.spongycastle.asn1.x500.style;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.x500.AttributeTypeAndValue;
+import org.spongycastle.asn1.x500.RDN;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x500.X500NameStyle;
+
+public class RFC4519Style
+ implements X500NameStyle
+{
+ public static final ASN1ObjectIdentifier businessCategory = new ASN1ObjectIdentifier("2.5.4.15");
+ public static final ASN1ObjectIdentifier c = new ASN1ObjectIdentifier("2.5.4.6");
+ public static final ASN1ObjectIdentifier cn = new ASN1ObjectIdentifier("2.5.4.3");
+ public static final ASN1ObjectIdentifier dc = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
+ public static final ASN1ObjectIdentifier description = new ASN1ObjectIdentifier("2.5.4.13");
+ public static final ASN1ObjectIdentifier destinationIndicator = new ASN1ObjectIdentifier("2.5.4.27");
+ public static final ASN1ObjectIdentifier distinguishedName = new ASN1ObjectIdentifier("2.5.4.49");
+ public static final ASN1ObjectIdentifier dnQualifier = new ASN1ObjectIdentifier("2.5.4.46");
+ public static final ASN1ObjectIdentifier enhancedSearchGuide = new ASN1ObjectIdentifier("2.5.4.47");
+ public static final ASN1ObjectIdentifier facsimileTelephoneNumber = new ASN1ObjectIdentifier("2.5.4.23");
+ public static final ASN1ObjectIdentifier generationQualifier = new ASN1ObjectIdentifier("2.5.4.44");
+ public static final ASN1ObjectIdentifier givenName = new ASN1ObjectIdentifier("2.5.4.42");
+ public static final ASN1ObjectIdentifier houseIdentifier = new ASN1ObjectIdentifier("2.5.4.51");
+ public static final ASN1ObjectIdentifier initials = new ASN1ObjectIdentifier("2.5.4.43");
+ public static final ASN1ObjectIdentifier internationalISDNNumber = new ASN1ObjectIdentifier("2.5.4.25");
+ public static final ASN1ObjectIdentifier l = new ASN1ObjectIdentifier("2.5.4.7");
+ public static final ASN1ObjectIdentifier member = new ASN1ObjectIdentifier("2.5.4.31");
+ public static final ASN1ObjectIdentifier name = new ASN1ObjectIdentifier("2.5.4.41");
+ public static final ASN1ObjectIdentifier o = new ASN1ObjectIdentifier("2.5.4.10");
+ public static final ASN1ObjectIdentifier ou = new ASN1ObjectIdentifier("2.5.4.11");
+ public static final ASN1ObjectIdentifier owner = new ASN1ObjectIdentifier("2.5.4.32");
+ public static final ASN1ObjectIdentifier physicalDeliveryOfficeName = new ASN1ObjectIdentifier("2.5.4.19");
+ public static final ASN1ObjectIdentifier postalAddress = new ASN1ObjectIdentifier("2.5.4.16");
+ public static final ASN1ObjectIdentifier postalCode = new ASN1ObjectIdentifier("2.5.4.17");
+ public static final ASN1ObjectIdentifier postOfficeBox = new ASN1ObjectIdentifier("2.5.4.18");
+ public static final ASN1ObjectIdentifier preferredDeliveryMethod = new ASN1ObjectIdentifier("2.5.4.28");
+ public static final ASN1ObjectIdentifier registeredAddress = new ASN1ObjectIdentifier("2.5.4.26");
+ public static final ASN1ObjectIdentifier roleOccupant = new ASN1ObjectIdentifier("2.5.4.33");
+ public static final ASN1ObjectIdentifier searchGuide = new ASN1ObjectIdentifier("2.5.4.14");
+ public static final ASN1ObjectIdentifier seeAlso = new ASN1ObjectIdentifier("2.5.4.34");
+ public static final ASN1ObjectIdentifier serialNumber = new ASN1ObjectIdentifier("2.5.4.5");
+ public static final ASN1ObjectIdentifier sn = new ASN1ObjectIdentifier("2.5.4.4");
+ public static final ASN1ObjectIdentifier st = new ASN1ObjectIdentifier("2.5.4.8");
+ public static final ASN1ObjectIdentifier street = new ASN1ObjectIdentifier("2.5.4.9");
+ public static final ASN1ObjectIdentifier telephoneNumber = new ASN1ObjectIdentifier("2.5.4.20");
+ public static final ASN1ObjectIdentifier teletexTerminalIdentifier = new ASN1ObjectIdentifier("2.5.4.22");
+ public static final ASN1ObjectIdentifier telexNumber = new ASN1ObjectIdentifier("2.5.4.21");
+ public static final ASN1ObjectIdentifier title = new ASN1ObjectIdentifier("2.5.4.12");
+ public static final ASN1ObjectIdentifier uid = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
+ public static final ASN1ObjectIdentifier uniqueMember = new ASN1ObjectIdentifier("2.5.4.50");
+ public static final ASN1ObjectIdentifier userPassword = new ASN1ObjectIdentifier("2.5.4.35");
+ public static final ASN1ObjectIdentifier x121Address = new ASN1ObjectIdentifier("2.5.4.24");
+ public static final ASN1ObjectIdentifier x500UniqueIdentifier = new ASN1ObjectIdentifier("2.5.4.45");
+
+ /**
+ * default look up table translating OID values into their common symbols following
+ * the convention in RFC 2253 with a few extras
+ */
+ private static final Hashtable DefaultSymbols = new Hashtable();
+
+ /**
+ * look up table translating common symbols into their OIDS.
+ */
+ private static final Hashtable DefaultLookUp = new Hashtable();
+
+ static
+ {
+ DefaultSymbols.put(businessCategory, "businessCategory");
+ DefaultSymbols.put(c, "c");
+ DefaultSymbols.put(cn, "cn");
+ DefaultSymbols.put(dc, "dc");
+ DefaultSymbols.put(description, "description");
+ DefaultSymbols.put(destinationIndicator, "destinationIndicator");
+ DefaultSymbols.put(distinguishedName, "distinguishedName");
+ DefaultSymbols.put(dnQualifier, "dnQualifier");
+ DefaultSymbols.put(enhancedSearchGuide, "enhancedSearchGuide");
+ DefaultSymbols.put(facsimileTelephoneNumber, "facsimileTelephoneNumber");
+ DefaultSymbols.put(generationQualifier, "generationQualifier");
+ DefaultSymbols.put(givenName, "givenName");
+ DefaultSymbols.put(houseIdentifier, "houseIdentifier");
+ DefaultSymbols.put(initials, "initials");
+ DefaultSymbols.put(internationalISDNNumber, "internationalISDNNumber");
+ DefaultSymbols.put(l, "l");
+ DefaultSymbols.put(member, "member");
+ DefaultSymbols.put(name, "name");
+ DefaultSymbols.put(o, "o");
+ DefaultSymbols.put(ou, "ou");
+ DefaultSymbols.put(owner, "owner");
+ DefaultSymbols.put(physicalDeliveryOfficeName, "physicalDeliveryOfficeName");
+ DefaultSymbols.put(postalAddress, "postalAddress");
+ DefaultSymbols.put(postalCode, "postalCode");
+ DefaultSymbols.put(postOfficeBox, "postOfficeBox");
+ DefaultSymbols.put(preferredDeliveryMethod, "preferredDeliveryMethod");
+ DefaultSymbols.put(registeredAddress, "registeredAddress");
+ DefaultSymbols.put(roleOccupant, "roleOccupant");
+ DefaultSymbols.put(searchGuide, "searchGuide");
+ DefaultSymbols.put(seeAlso, "seeAlso");
+ DefaultSymbols.put(serialNumber, "serialNumber");
+ DefaultSymbols.put(sn, "sn");
+ DefaultSymbols.put(st, "st");
+ DefaultSymbols.put(street, "street");
+ DefaultSymbols.put(telephoneNumber, "telephoneNumber");
+ DefaultSymbols.put(teletexTerminalIdentifier, "teletexTerminalIdentifier");
+ DefaultSymbols.put(telexNumber, "telexNumber");
+ DefaultSymbols.put(title, "title");
+ DefaultSymbols.put(uid, "uid");
+ DefaultSymbols.put(uniqueMember, "uniqueMember");
+ DefaultSymbols.put(userPassword, "userPassword");
+ DefaultSymbols.put(x121Address, "x121Address");
+ DefaultSymbols.put(x500UniqueIdentifier, "x500UniqueIdentifier");
+
+ DefaultLookUp.put("businesscategory", businessCategory);
+ DefaultLookUp.put("c", c);
+ DefaultLookUp.put("cn", cn);
+ DefaultLookUp.put("dc", dc);
+ DefaultLookUp.put("description", description);
+ DefaultLookUp.put("destinationindicator", destinationIndicator);
+ DefaultLookUp.put("distinguishedname", distinguishedName);
+ DefaultLookUp.put("dnqualifier", dnQualifier);
+ DefaultLookUp.put("enhancedsearchguide", enhancedSearchGuide);
+ DefaultLookUp.put("facsimiletelephonenumber", facsimileTelephoneNumber);
+ DefaultLookUp.put("generationqualifier", generationQualifier);
+ DefaultLookUp.put("givenname", givenName);
+ DefaultLookUp.put("houseidentifier", houseIdentifier);
+ DefaultLookUp.put("initials", initials);
+ DefaultLookUp.put("internationalisdnnumber", internationalISDNNumber);
+ DefaultLookUp.put("l", l);
+ DefaultLookUp.put("member", member);
+ DefaultLookUp.put("name", name);
+ DefaultLookUp.put("o", o);
+ DefaultLookUp.put("ou", ou);
+ DefaultLookUp.put("owner", owner);
+ DefaultLookUp.put("physicaldeliveryofficename", physicalDeliveryOfficeName);
+ DefaultLookUp.put("postaladdress", postalAddress);
+ DefaultLookUp.put("postalcode", postalCode);
+ DefaultLookUp.put("postofficebox", postOfficeBox);
+ DefaultLookUp.put("preferreddeliverymethod", preferredDeliveryMethod);
+ DefaultLookUp.put("registeredaddress", registeredAddress);
+ DefaultLookUp.put("roleoccupant", roleOccupant);
+ DefaultLookUp.put("searchguide", searchGuide);
+ DefaultLookUp.put("seealso", seeAlso);
+ DefaultLookUp.put("serialnumber", serialNumber);
+ DefaultLookUp.put("sn", sn);
+ DefaultLookUp.put("st", st);
+ DefaultLookUp.put("street", street);
+ DefaultLookUp.put("telephonenumber", telephoneNumber);
+ DefaultLookUp.put("teletexterminalidentifier", teletexTerminalIdentifier);
+ DefaultLookUp.put("telexnumber", telexNumber);
+ DefaultLookUp.put("title", title);
+ DefaultLookUp.put("uid", uid);
+ DefaultLookUp.put("uniquemember", uniqueMember);
+ DefaultLookUp.put("userpassword", userPassword);
+ DefaultLookUp.put("x121address", x121Address);
+ DefaultLookUp.put("x500uniqueidentifier", x500UniqueIdentifier);
+
+ // TODO: need to add correct matching for equality comparisons.
+ }
+
+ /**
+ * Singleton instance.
+ */
+ public static final X500NameStyle INSTANCE = new RFC4519Style();
+
+ protected Hashtable defaultLookUp;
+ protected Hashtable defaultSymbols;
+
+ protected RFC4519Style()
+ {
+ defaultSymbols = copyHashTable(DefaultSymbols);
+ defaultLookUp = copyHashTable(DefaultLookUp);
+ }
+
+ public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
+ {
+ if (value.length() != 0 && value.charAt(0) == '#')
+ {
+ try
+ {
+ return IETFUtils.valueFromHexString(value, 1);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("can't recode value for oid " + oid.getId());
+ }
+ }
+ else
+ {
+ if (value.length() != 0 && value.charAt(0) == '\\')
+ {
+ value = value.substring(1);
+ }
+ if (oid.equals(dc))
+ {
+ return new DERIA5String(value);
+ }
+ else if (oid.equals(c) || oid.equals(serialNumber) || oid.equals(dnQualifier)
+ || oid.equals(telephoneNumber))
+ {
+ return new DERPrintableString(value);
+ }
+ }
+
+ return new DERUTF8String(value);
+ }
+
+ public String oidToDisplayName(ASN1ObjectIdentifier oid)
+ {
+ return (String)DefaultSymbols.get(oid);
+ }
+
+ public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
+ {
+ return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
+ }
+
+ public ASN1ObjectIdentifier attrNameToOID(String attrName)
+ {
+ return IETFUtils.decodeAttrName(attrName, defaultLookUp);
+ }
+
+ public boolean areEqual(X500Name name1, X500Name name2)
+ {
+ RDN[] rdns1 = name1.getRDNs();
+ RDN[] rdns2 = name2.getRDNs();
+
+ if (rdns1.length != rdns2.length)
+ {
+ return false;
+ }
+
+ boolean reverse = false;
+
+ if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null)
+ {
+ reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward
+ }
+
+ for (int i = 0; i != rdns1.length; i++)
+ {
+ if (!foundMatch(reverse, rdns1[i], rdns2))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs)
+ {
+ if (reverse)
+ {
+ for (int i = possRDNs.length - 1; i >= 0; i--)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i != possRDNs.length; i++)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected boolean rdnAreEqual(RDN rdn1, RDN rdn2)
+ {
+ return IETFUtils.rDNAreEqual(rdn1, rdn2);
+ }
+
+ // parse backwards
+ public RDN[] fromString(String dirName)
+ {
+ RDN[] tmp = IETFUtils.rDNsFromString(dirName, this);
+ RDN[] res = new RDN[tmp.length];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ res[res.length - i - 1] = tmp[i];
+ }
+
+ return res;
+ }
+
+ public int calculateHashCode(X500Name name)
+ {
+ int hashCodeValue = 0;
+ RDN[] rdns = name.getRDNs();
+
+ // this needs to be order independent, like equals
+ for (int i = 0; i != rdns.length; i++)
+ {
+ if (rdns[i].isMultiValued())
+ {
+ AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
+
+ for (int j = 0; j != atv.length; j++)
+ {
+ hashCodeValue ^= atv[j].getType().hashCode();
+ hashCodeValue ^= calcHashCode(atv[j].getValue());
+ }
+ }
+ else
+ {
+ hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
+ hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
+ }
+ }
+
+ return hashCodeValue;
+ }
+
+ private int calcHashCode(ASN1Encodable enc)
+ {
+ String value = IETFUtils.valueToString(enc);
+
+ value = IETFUtils.canonicalize(value);
+
+ return value.hashCode();
+ }
+
+ // convert in reverse
+ public String toString(X500Name name)
+ {
+ StringBuffer buf = new StringBuffer();
+ boolean first = true;
+
+ RDN[] rdns = name.getRDNs();
+
+ for (int i = rdns.length - 1; i >= 0; i--)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append(',');
+ }
+
+ IETFUtils.appendRDN(buf, rdns[i], defaultSymbols);
+ }
+
+ return buf.toString();
+ }
+
+ private static Hashtable copyHashTable(Hashtable paramsMap)
+ {
+ Hashtable newTable = new Hashtable();
+
+ Enumeration keys = paramsMap.keys();
+ while (keys.hasMoreElements())
+ {
+ Object key = keys.nextElement();
+ newTable.put(key, paramsMap.get(key));
+ }
+
+ return newTable;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java
new file mode 100644
index 000000000..17554b960
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java
@@ -0,0 +1,573 @@
+package org.spongycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.util.Arrays;
+
+/**
+ * A participant in a Password Authenticated Key Exchange by Juggling (J-PAKE) exchange.
+ * <p/>
+ * <p/>
+ * The J-PAKE exchange is defined by Feng Hao and Peter Ryan in the paper
+ * <a href="http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf">
+ * "Password Authenticated Key Exchange by Juggling, 2008."</a>
+ * <p/>
+ * <p/>
+ * The J-PAKE protocol is symmetric.
+ * There is no notion of a <i>client</i> or <i>server</i>, but rather just two <i>participants</i>.
+ * An instance of {@link JPAKEParticipant} represents one participant, and
+ * is the primary interface for executing the exchange.
+ * <p/>
+ * <p/>
+ * To execute an exchange, construct a {@link JPAKEParticipant} on each end,
+ * and call the following 7 methods
+ * (once and only once, in the given order, for each participant, sending messages between them as described):
+ * <ol>
+ * <li>{@link #createRound1PayloadToSend()} - and send the payload to the other participant</li>
+ * <li>{@link #validateRound1PayloadReceived(JPAKERound1Payload)} - use the payload received from the other participant</li>
+ * <li>{@link #createRound2PayloadToSend()} - and send the payload to the other participant</li>
+ * <li>{@link #validateRound2PayloadReceived(JPAKERound2Payload)} - use the payload received from the other participant</li>
+ * <li>{@link #calculateKeyingMaterial()}</li>
+ * <li>{@link #createRound3PayloadToSend(BigInteger)} - and send the payload to the other participant</li>
+ * <li>{@link #validateRound3PayloadReceived(JPAKERound3Payload, BigInteger)} - use the payload received from the other participant</li>
+ * </ol>
+ * <p/>
+ * <p/>
+ * Each side should derive a session key from the keying material returned by {@link #calculateKeyingMaterial()}.
+ * The caller is responsible for deriving the session key using a secure key derivation function (KDF).
+ * <p/>
+ * <p/>
+ * Round 3 is an optional key confirmation process.
+ * If you do not execute round 3, then there is no assurance that both participants are using the same key.
+ * (i.e. if the participants used different passwords, then their session keys will differ.)
+ * <p/>
+ * <p/>
+ * If the round 3 validation succeeds, then the keys are guaranteed to be the same on both sides.
+ * <p/>
+ * <p/>
+ * The symmetric design can easily support the asymmetric cases when one party initiates the communication.
+ * e.g. Sometimes the round1 payload and round2 payload may be sent in one pass.
+ * Also, in some cases, the key confirmation payload can be sent together with the round2 payload.
+ * These are the trivial techniques to optimize the communication.
+ * <p/>
+ * <p/>
+ * The key confirmation process is implemented as specified in
+ * <a href="http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf">NIST SP 800-56A Revision 1</a>,
+ * Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes.
+ * <p/>
+ * <p/>
+ * This class is stateful and NOT threadsafe.
+ * Each instance should only be used for ONE complete J-PAKE exchange
+ * (i.e. a new {@link JPAKEParticipant} should be constructed for each new J-PAKE exchange).
+ * <p/>
+ * <p/>
+ * See {@link JPAKEExample} for example usage.
+ */
+public class JPAKEParticipant
+{
+ /*
+ * Possible internal states. Used for state checking.
+ */
+
+ public static final int STATE_INITIALIZED = 0;
+ public static final int STATE_ROUND_1_CREATED = 10;
+ public static final int STATE_ROUND_1_VALIDATED = 20;
+ public static final int STATE_ROUND_2_CREATED = 30;
+ public static final int STATE_ROUND_2_VALIDATED = 40;
+ public static final int STATE_KEY_CALCULATED = 50;
+ public static final int STATE_ROUND_3_CREATED = 60;
+ public static final int STATE_ROUND_3_VALIDATED = 70;
+
+ /**
+ * Unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ */
+ private String participantId;
+
+ /**
+ * Shared secret. This only contains the secret between construction
+ * and the call to {@link #calculateKeyingMaterial()}.
+ * <p/>
+ * i.e. When {@link #calculateKeyingMaterial()} is called, this buffer overwritten with 0's,
+ * and the field is set to null.
+ */
+ private char[] password;
+
+ /**
+ * Digest to use during calculations.
+ */
+ private Digest digest;
+
+ /**
+ * Source of secure random data.
+ */
+ private SecureRandom random;
+
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger g;
+
+ /**
+ * The participantId of the other participant in this exchange.
+ */
+ private String partnerParticipantId;
+
+ /**
+ * Alice's x1 or Bob's x3.
+ */
+ private BigInteger x1;
+ /**
+ * Alice's x2 or Bob's x4.
+ */
+ private BigInteger x2;
+ /**
+ * Alice's g^x1 or Bob's g^x3.
+ */
+ private BigInteger gx1;
+ /**
+ * Alice's g^x2 or Bob's g^x4.
+ */
+ private BigInteger gx2;
+ /**
+ * Alice's g^x3 or Bob's g^x1.
+ */
+ private BigInteger gx3;
+ /**
+ * Alice's g^x4 or Bob's g^x2.
+ */
+ private BigInteger gx4;
+ /**
+ * Alice's B or Bob's A.
+ */
+ private BigInteger b;
+
+ /**
+ * The current state.
+ * See the <tt>STATE_*</tt> constants for possible values.
+ */
+ private int state;
+
+ /**
+ * Convenience constructor for a new {@link JPAKEParticipant} that uses
+ * the {@link JPAKEPrimeOrderGroups#NIST_3072} prime order group,
+ * a SHA-256 digest, and a default {@link SecureRandom} implementation.
+ * <p/>
+ * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
+ *
+ * @param participantId unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ * @param password shared secret.
+ * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
+ * Caller should clear the input password as soon as possible.
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if password is empty
+ */
+ public JPAKEParticipant(
+ String participantId,
+ char[] password)
+ {
+ this(
+ participantId,
+ password,
+ JPAKEPrimeOrderGroups.NIST_3072);
+ }
+
+
+ /**
+ * Convenience constructor for a new {@link JPAKEParticipant} that uses
+ * a SHA-256 digest and a default {@link SecureRandom} implementation.
+ * <p/>
+ * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
+ *
+ * @param participantId unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ * @param password shared secret.
+ * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
+ * Caller should clear the input password as soon as possible.
+ * @param group prime order group.
+ * See {@link JPAKEPrimeOrderGroups} for standard groups
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if password is empty
+ */
+ public JPAKEParticipant(
+ String participantId,
+ char[] password,
+ JPAKEPrimeOrderGroup group)
+ {
+ this(
+ participantId,
+ password,
+ group,
+ new SHA256Digest(),
+ new SecureRandom());
+ }
+
+
+ /**
+ * Construct a new {@link JPAKEParticipant}.
+ * <p/>
+ * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
+ *
+ * @param participantId unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ * @param password shared secret.
+ * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
+ * Caller should clear the input password as soon as possible.
+ * @param group prime order group.
+ * See {@link JPAKEPrimeOrderGroups} for standard groups
+ * @param digest digest to use during zero knowledge proofs and key confirmation (SHA-256 or stronger preferred)
+ * @param random source of secure random data for x1 and x2, and for the zero knowledge proofs
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if password is empty
+ */
+ public JPAKEParticipant(
+ String participantId,
+ char[] password,
+ JPAKEPrimeOrderGroup group,
+ Digest digest,
+ SecureRandom random)
+ {
+ JPAKEUtil.validateNotNull(participantId, "participantId");
+ JPAKEUtil.validateNotNull(password, "password");
+ JPAKEUtil.validateNotNull(group, "p");
+ JPAKEUtil.validateNotNull(digest, "digest");
+ JPAKEUtil.validateNotNull(random, "random");
+ if (password.length == 0)
+ {
+ throw new IllegalArgumentException("Password must not be empty.");
+ }
+
+ this.participantId = participantId;
+
+ /*
+ * Create a defensive copy so as to fully encapsulate the password.
+ *
+ * This array will contain the password for the lifetime of this
+ * participant BEFORE {@link #calculateKeyingMaterial()} is called.
+ *
+ * i.e. When {@link #calculateKeyingMaterial()} is called, the array will be cleared
+ * in order to remove the password from memory.
+ *
+ * The caller is responsible for clearing the original password array
+ * given as input to this constructor.
+ */
+ this.password = Arrays.copyOf(password, password.length);
+
+ this.p = group.getP();
+ this.q = group.getQ();
+ this.g = group.getG();
+
+ this.digest = digest;
+ this.random = random;
+
+ this.state = STATE_INITIALIZED;
+ }
+
+ /**
+ * Gets the current state of this participant.
+ * See the <tt>STATE_*</tt> constants for possible values.
+ */
+ public int getState()
+ {
+ return this.state;
+ }
+
+ /**
+ * Creates and returns the payload to send to the other participant during round 1.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_CREATED}.
+ */
+ public JPAKERound1Payload createRound1PayloadToSend()
+ {
+ if (this.state >= STATE_ROUND_1_CREATED)
+ {
+ throw new IllegalStateException("Round1 payload already created for " + participantId);
+ }
+
+ this.x1 = JPAKEUtil.generateX1(q, random);
+ this.x2 = JPAKEUtil.generateX2(q, random);
+
+ this.gx1 = JPAKEUtil.calculateGx(p, g, x1);
+ this.gx2 = JPAKEUtil.calculateGx(p, g, x2);
+ BigInteger[] knowledgeProofForX1 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx1, x1, participantId, digest, random);
+ BigInteger[] knowledgeProofForX2 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx2, x2, participantId, digest, random);
+
+ this.state = STATE_ROUND_1_CREATED;
+
+ return new JPAKERound1Payload(participantId, gx1, gx2, knowledgeProofForX1, knowledgeProofForX2);
+ }
+
+ /**
+ * Validates the payload received from the other participant during round 1.
+ * <p/>
+ * <p/>
+ * Must be called prior to {@link #createRound2PayloadToSend()}.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_VALIDATED}.
+ *
+ * @throws CryptoException if validation fails.
+ * @throws IllegalStateException if called multiple times.
+ */
+ public void validateRound1PayloadReceived(JPAKERound1Payload round1PayloadReceived)
+ throws CryptoException
+ {
+ if (this.state >= STATE_ROUND_1_VALIDATED)
+ {
+ throw new IllegalStateException("Validation already attempted for round1 payload for" + participantId);
+ }
+ this.partnerParticipantId = round1PayloadReceived.getParticipantId();
+ this.gx3 = round1PayloadReceived.getGx1();
+ this.gx4 = round1PayloadReceived.getGx2();
+
+ BigInteger[] knowledgeProofForX3 = round1PayloadReceived.getKnowledgeProofForX1();
+ BigInteger[] knowledgeProofForX4 = round1PayloadReceived.getKnowledgeProofForX2();
+
+ JPAKEUtil.validateParticipantIdsDiffer(participantId, round1PayloadReceived.getParticipantId());
+ JPAKEUtil.validateGx4(gx4);
+ JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx3, knowledgeProofForX3, round1PayloadReceived.getParticipantId(), digest);
+ JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx4, knowledgeProofForX4, round1PayloadReceived.getParticipantId(), digest);
+
+ this.state = STATE_ROUND_1_VALIDATED;
+ }
+
+ /**
+ * Creates and returns the payload to send to the other participant during round 2.
+ * <p/>
+ * <p/>
+ * {@link #validateRound1PayloadReceived(JPAKERound1Payload)} must be called prior to this method.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_CREATED}.
+ *
+ * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times
+ */
+ public JPAKERound2Payload createRound2PayloadToSend()
+ {
+ if (this.state >= STATE_ROUND_2_CREATED)
+ {
+ throw new IllegalStateException("Round2 payload already created for " + this.participantId);
+ }
+ if (this.state < STATE_ROUND_1_VALIDATED)
+ {
+ throw new IllegalStateException("Round1 payload must be validated prior to creating Round2 payload for " + this.participantId);
+ }
+ BigInteger gA = JPAKEUtil.calculateGA(p, gx1, gx3, gx4);
+ BigInteger s = JPAKEUtil.calculateS(password);
+ BigInteger x2s = JPAKEUtil.calculateX2s(q, x2, s);
+ BigInteger A = JPAKEUtil.calculateA(p, q, gA, x2s);
+ BigInteger[] knowledgeProofForX2s = JPAKEUtil.calculateZeroKnowledgeProof(p, q, gA, A, x2s, participantId, digest, random);
+
+ this.state = STATE_ROUND_2_CREATED;
+
+ return new JPAKERound2Payload(participantId, A, knowledgeProofForX2s);
+ }
+
+ /**
+ * Validates the payload received from the other participant during round 2.
+ * <p/>
+ * <p/>
+ * Note that this DOES NOT detect a non-common password.
+ * The only indication of a non-common password is through derivation
+ * of different keys (which can be detected explicitly by executing round 3 and round 4)
+ * <p/>
+ * <p/>
+ * Must be called prior to {@link #calculateKeyingMaterial()}.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_VALIDATED}.
+ *
+ * @throws CryptoException if validation fails.
+ * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times
+ */
+ public void validateRound2PayloadReceived(JPAKERound2Payload round2PayloadReceived)
+ throws CryptoException
+ {
+ if (this.state >= STATE_ROUND_2_VALIDATED)
+ {
+ throw new IllegalStateException("Validation already attempted for round2 payload for" + participantId);
+ }
+ if (this.state < STATE_ROUND_1_VALIDATED)
+ {
+ throw new IllegalStateException("Round1 payload must be validated prior to validating Round2 payload for " + this.participantId);
+ }
+ BigInteger gB = JPAKEUtil.calculateGA(p, gx3, gx1, gx2);
+ this.b = round2PayloadReceived.getA();
+ BigInteger[] knowledgeProofForX4s = round2PayloadReceived.getKnowledgeProofForX2s();
+
+ JPAKEUtil.validateParticipantIdsDiffer(participantId, round2PayloadReceived.getParticipantId());
+ JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round2PayloadReceived.getParticipantId());
+ JPAKEUtil.validateGa(gB);
+ JPAKEUtil.validateZeroKnowledgeProof(p, q, gB, b, knowledgeProofForX4s, round2PayloadReceived.getParticipantId(), digest);
+
+ this.state = STATE_ROUND_2_VALIDATED;
+ }
+
+ /**
+ * Calculates and returns the key material.
+ * A session key must be derived from this key material using a secure key derivation function (KDF).
+ * The KDF used to derive the key is handled externally (i.e. not by {@link JPAKEParticipant}).
+ * <p/>
+ * <p/>
+ * The keying material will be identical for each participant if and only if
+ * each participant's password is the same. i.e. If the participants do not
+ * share the same password, then each participant will derive a different key.
+ * Therefore, if you immediately start using a key derived from
+ * the keying material, then you must handle detection of incorrect keys.
+ * If you want to handle this detection explicitly, you can optionally perform
+ * rounds 3 and 4. See {@link JPAKEParticipant} for details on how to execute
+ * rounds 3 and 4.
+ * <p/>
+ * <p/>
+ * The keying material will be in the range <tt>[0, p-1]</tt>.
+ * <p/>
+ * <p/>
+ * {@link #validateRound2PayloadReceived(JPAKERound2Payload)} must be called prior to this method.
+ * <p/>
+ * <p/>
+ * As a side effect, the internal {@link #password} array is cleared, since it is no longer needed.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_KEY_CALCULATED}.
+ *
+ * @throws IllegalStateException if called prior to {@link #validateRound2PayloadReceived(JPAKERound2Payload)},
+ * or if called multiple times.
+ */
+ public BigInteger calculateKeyingMaterial()
+ {
+ if (this.state >= STATE_KEY_CALCULATED)
+ {
+ throw new IllegalStateException("Key already calculated for " + participantId);
+ }
+ if (this.state < STATE_ROUND_2_VALIDATED)
+ {
+ throw new IllegalStateException("Round2 payload must be validated prior to creating key for " + participantId);
+ }
+ BigInteger s = JPAKEUtil.calculateS(password);
+
+ /*
+ * Clear the password array from memory, since we don't need it anymore.
+ *
+ * Also set the field to null as a flag to indicate that the key has already been calculated.
+ */
+ Arrays.fill(password, (char)0);
+ this.password = null;
+
+ BigInteger keyingMaterial = JPAKEUtil.calculateKeyingMaterial(p, q, gx4, x2, s, b);
+
+ /*
+ * Clear the ephemeral private key fields as well.
+ * Note that we're relying on the garbage collector to do its job to clean these up.
+ * The old objects will hang around in memory until the garbage collector destroys them.
+ *
+ * If the ephemeral private keys x1 and x2 are leaked,
+ * the attacker might be able to brute-force the password.
+ */
+ this.x1 = null;
+ this.x2 = null;
+ this.b = null;
+
+ /*
+ * Do not clear gx* yet, since those are needed by round 3.
+ */
+
+ this.state = STATE_KEY_CALCULATED;
+
+ return keyingMaterial;
+ }
+
+
+ /**
+ * Creates and returns the payload to send to the other participant during round 3.
+ * <p/>
+ * <p/>
+ * See {@link JPAKEParticipant} for more details on round 3.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_CREATED}.
+ *
+ * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}.
+ * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times
+ */
+ public JPAKERound3Payload createRound3PayloadToSend(BigInteger keyingMaterial)
+ {
+ if (this.state >= STATE_ROUND_3_CREATED)
+ {
+ throw new IllegalStateException("Round3 payload already created for " + this.participantId);
+ }
+ if (this.state < STATE_KEY_CALCULATED)
+ {
+ throw new IllegalStateException("Keying material must be calculated prior to creating Round3 payload for " + this.participantId);
+ }
+
+ BigInteger macTag = JPAKEUtil.calculateMacTag(
+ this.participantId,
+ this.partnerParticipantId,
+ this.gx1,
+ this.gx2,
+ this.gx3,
+ this.gx4,
+ keyingMaterial,
+ this.digest);
+
+ this.state = STATE_ROUND_3_CREATED;
+
+ return new JPAKERound3Payload(participantId, macTag);
+ }
+
+ /**
+ * Validates the payload received from the other participant during round 3.
+ * <p/>
+ * <p/>
+ * See {@link JPAKEParticipant} for more details on round 3.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_VALIDATED}.
+ *
+ * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}.
+ * @throws CryptoException if validation fails.
+ * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times
+ */
+ public void validateRound3PayloadReceived(JPAKERound3Payload round3PayloadReceived, BigInteger keyingMaterial)
+ throws CryptoException
+ {
+ if (this.state >= STATE_ROUND_3_VALIDATED)
+ {
+ throw new IllegalStateException("Validation already attempted for round3 payload for" + participantId);
+ }
+ if (this.state < STATE_KEY_CALCULATED)
+ {
+ throw new IllegalStateException("Keying material must be calculated validated prior to validating Round3 payload for " + this.participantId);
+ }
+ JPAKEUtil.validateParticipantIdsDiffer(participantId, round3PayloadReceived.getParticipantId());
+ JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round3PayloadReceived.getParticipantId());
+
+ JPAKEUtil.validateMacTag(
+ this.participantId,
+ this.partnerParticipantId,
+ this.gx1,
+ this.gx2,
+ this.gx3,
+ this.gx4,
+ keyingMaterial,
+ this.digest,
+ round3PayloadReceived.getMacTag());
+
+
+ /*
+ * Clear the rest of the fields.
+ */
+ this.gx1 = null;
+ this.gx2 = null;
+ this.gx3 = null;
+ this.gx4 = null;
+
+ this.state = STATE_ROUND_3_VALIDATED;
+ }
+
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java
new file mode 100644
index 000000000..59e93385c
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java
@@ -0,0 +1,122 @@
+package org.spongycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+
+/**
+ * A pre-computed prime order group for use during a J-PAKE exchange.
+ * <p/>
+ * <p/>
+ * Typically a Schnorr group is used. In general, J-PAKE can use any prime order group
+ * that is suitable for public key cryptography, including elliptic curve cryptography.
+ * <p/>
+ * <p/>
+ * See {@link JPAKEPrimeOrderGroups} for convenient standard groups.
+ * <p/>
+ * <p/>
+ * NIST <a href="http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/DSA2_All.pdf">publishes</a>
+ * many groups that can be used for the desired level of security.
+ */
+public class JPAKEPrimeOrderGroup
+{
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger g;
+
+ /**
+ * Constructs a new {@link JPAKEPrimeOrderGroup}.
+ * <p/>
+ * <p/>
+ * In general, you should use one of the pre-approved groups from
+ * {@link JPAKEPrimeOrderGroups}, rather than manually constructing one.
+ * <p/>
+ * <p/>
+ * The following basic checks are performed:
+ * <ul>
+ * <li>p-1 must be evenly divisible by q</li>
+ * <li>g must be in [2, p-1]</li>
+ * <li>g^q mod p must equal 1</li>
+ * <li>p must be prime (within reasonably certainty)</li>
+ * <li>q must be prime (within reasonably certainty)</li>
+ * </ul>
+ * <p/>
+ * <p/>
+ * The prime checks are performed using {@link BigInteger#isProbablePrime(int)},
+ * and are therefore subject to the same probability guarantees.
+ * <p/>
+ * <p/>
+ * These checks prevent trivial mistakes.
+ * However, due to the small uncertainties if p and q are not prime,
+ * advanced attacks are not prevented.
+ * Use it at your own risk.
+ *
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if any of the above validations fail
+ */
+ public JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g)
+ {
+ /*
+ * Don't skip the checks on user-specified groups.
+ */
+ this(p, q, g, false);
+ }
+
+ /**
+ * Internal package-private constructor used by the pre-approved
+ * groups in {@link JPAKEPrimeOrderGroups}.
+ * These pre-approved groups can avoid the expensive checks.
+ */
+ JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g, boolean skipChecks)
+ {
+ JPAKEUtil.validateNotNull(p, "p");
+ JPAKEUtil.validateNotNull(q, "q");
+ JPAKEUtil.validateNotNull(g, "g");
+
+ if (!skipChecks)
+ {
+ if (!p.subtract(JPAKEUtil.ONE).mod(q).equals(JPAKEUtil.ZERO))
+ {
+ throw new IllegalArgumentException("p-1 must be evenly divisible by q");
+ }
+ if (g.compareTo(BigInteger.valueOf(2)) == -1 || g.compareTo(p.subtract(JPAKEUtil.ONE)) == 1)
+ {
+ throw new IllegalArgumentException("g must be in [2, p-1]");
+ }
+ if (!g.modPow(q, p).equals(JPAKEUtil.ONE))
+ {
+ throw new IllegalArgumentException("g^q mod p must equal 1");
+ }
+ /*
+ * Note that these checks do not guarantee that p and q are prime.
+ * We just have reasonable certainty that they are prime.
+ */
+ if (!p.isProbablePrime(20))
+ {
+ throw new IllegalArgumentException("p must be prime");
+ }
+ if (!q.isProbablePrime(20))
+ {
+ throw new IllegalArgumentException("q must be prime");
+ }
+ }
+
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/digests/SkeinEngine.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/digests/SkeinEngine.java
new file mode 100644
index 000000000..a278ff4e4
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/digests/SkeinEngine.java
@@ -0,0 +1,817 @@
+package org.spongycastle.crypto.digests;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.engines.ThreefishEngine;
+import org.spongycastle.crypto.macs.SkeinMac;
+import org.spongycastle.crypto.params.SkeinParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Memoable;
+
+/**
+ * Implementation of the Skein family of parameterised hash functions in 256, 512 and 1024 bit block
+ * sizes, based on the {@link ThreefishEngine Threefish} tweakable block cipher.
+ * <p/>
+ * This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
+ * competition in October 2010.
+ * <p/>
+ * Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+ * Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+ * <p/>
+ * This implementation is the basis for {@link SkeinDigest} and {@link SkeinMac}, implementing the
+ * parameter based configuration system that allows Skein to be adapted to multiple applications. <br>
+ * Initialising the engine with {@link SkeinParameters} allows standard and arbitrary parameters to
+ * be applied during the Skein hash function.
+ * <p/>
+ * Implemented:
+ * <ul>
+ * <li>256, 512 and 1024 bit internal states.</li>
+ * <li>Full 96 bit input length.</li>
+ * <li>Parameters defined in the Skein specification, and arbitrary other pre and post message
+ * parameters.</li>
+ * <li>Arbitrary output size in 1 byte intervals.</li>
+ * </ul>
+ * <p/>
+ * Not implemented:
+ * <ul>
+ * <li>Sub-byte length input (bit padding).</li>
+ * <li>Tree hashing.</li>
+ * </ul>
+ *
+ * @see SkeinParameters
+ */
+public class SkeinEngine
+ implements Memoable
+{
+ /**
+ * 256 bit block size - Skein 256
+ */
+ public static final int SKEIN_256 = ThreefishEngine.BLOCKSIZE_256;
+ /**
+ * 512 bit block size - Skein 512
+ */
+ public static final int SKEIN_512 = ThreefishEngine.BLOCKSIZE_512;
+ /**
+ * 1024 bit block size - Skein 1024
+ */
+ public static final int SKEIN_1024 = ThreefishEngine.BLOCKSIZE_1024;
+
+ // Minimal at present, but more complex when tree hashing is implemented
+ private static class Configuration
+ {
+ private byte[] bytes = new byte[32];
+
+ public Configuration(long outputSizeBits)
+ {
+ // 0..3 = ASCII SHA3
+ bytes[0] = (byte)'S';
+ bytes[1] = (byte)'H';
+ bytes[2] = (byte)'A';
+ bytes[3] = (byte)'3';
+
+ // 4..5 = version number in LSB order
+ bytes[4] = 1;
+ bytes[5] = 0;
+
+ // 8..15 = output length
+ ThreefishEngine.wordToBytes(outputSizeBits, bytes, 8);
+ }
+
+ public byte[] getBytes()
+ {
+ return bytes;
+ }
+
+ }
+
+ public static class Parameter
+ {
+ private int type;
+ private byte[] value;
+
+ public Parameter(int type, byte[] value)
+ {
+ this.type = type;
+ this.value = value;
+ }
+
+ public int getType()
+ {
+ return type;
+ }
+
+ public byte[] getValue()
+ {
+ return value;
+ }
+
+ }
+
+ /**
+ * The parameter type for the Skein key.
+ */
+ private static final int PARAM_TYPE_KEY = 0;
+
+ /**
+ * The parameter type for the Skein configuration block.
+ */
+ private static final int PARAM_TYPE_CONFIG = 4;
+
+ /**
+ * The parameter type for the message.
+ */
+ private static final int PARAM_TYPE_MESSAGE = 48;
+
+ /**
+ * The parameter type for the output transformation.
+ */
+ private static final int PARAM_TYPE_OUTPUT = 63;
+
+ /**
+ * Precalculated UBI(CFG) states for common state/output combinations without key or other
+ * pre-message params.
+ */
+ private static final Hashtable INITIAL_STATES = new Hashtable();
+
+ static
+ {
+ // From Appendix C of the Skein 1.3 NIST submission
+ initialState(SKEIN_256, 128, new long[]{
+ 0xe1111906964d7260L,
+ 0x883daaa77c8d811cL,
+ 0x10080df491960f7aL,
+ 0xccf7dde5b45bc1c2L});
+
+ initialState(SKEIN_256, 160, new long[]{
+ 0x1420231472825e98L,
+ 0x2ac4e9a25a77e590L,
+ 0xd47a58568838d63eL,
+ 0x2dd2e4968586ab7dL});
+
+ initialState(SKEIN_256, 224, new long[]{
+ 0xc6098a8c9ae5ea0bL,
+ 0x876d568608c5191cL,
+ 0x99cb88d7d7f53884L,
+ 0x384bddb1aeddb5deL});
+
+ initialState(SKEIN_256, 256, new long[]{
+ 0xfc9da860d048b449L,
+ 0x2fca66479fa7d833L,
+ 0xb33bc3896656840fL,
+ 0x6a54e920fde8da69L});
+
+ initialState(SKEIN_512, 128, new long[]{
+ 0xa8bc7bf36fbf9f52L,
+ 0x1e9872cebd1af0aaL,
+ 0x309b1790b32190d3L,
+ 0xbcfbb8543f94805cL,
+ 0x0da61bcd6e31b11bL,
+ 0x1a18ebead46a32e3L,
+ 0xa2cc5b18ce84aa82L,
+ 0x6982ab289d46982dL});
+
+ initialState(SKEIN_512, 160, new long[]{
+ 0x28b81a2ae013bd91L,
+ 0xc2f11668b5bdf78fL,
+ 0x1760d8f3f6a56f12L,
+ 0x4fb747588239904fL,
+ 0x21ede07f7eaf5056L,
+ 0xd908922e63ed70b8L,
+ 0xb8ec76ffeccb52faL,
+ 0x01a47bb8a3f27a6eL});
+
+ initialState(SKEIN_512, 224, new long[]{
+ 0xccd0616248677224L,
+ 0xcba65cf3a92339efL,
+ 0x8ccd69d652ff4b64L,
+ 0x398aed7b3ab890b4L,
+ 0x0f59d1b1457d2bd0L,
+ 0x6776fe6575d4eb3dL,
+ 0x99fbc70e997413e9L,
+ 0x9e2cfccfe1c41ef7L});
+
+ initialState(SKEIN_512, 384, new long[]{
+ 0xa3f6c6bf3a75ef5fL,
+ 0xb0fef9ccfd84faa4L,
+ 0x9d77dd663d770cfeL,
+ 0xd798cbf3b468fddaL,
+ 0x1bc4a6668a0e4465L,
+ 0x7ed7d434e5807407L,
+ 0x548fc1acd4ec44d6L,
+ 0x266e17546aa18ff8L});
+
+ initialState(SKEIN_512, 512, new long[]{
+ 0x4903adff749c51ceL,
+ 0x0d95de399746df03L,
+ 0x8fd1934127c79bceL,
+ 0x9a255629ff352cb1L,
+ 0x5db62599df6ca7b0L,
+ 0xeabe394ca9d5c3f4L,
+ 0x991112c71a75b523L,
+ 0xae18a40b660fcc33L});
+ }
+
+ private static void initialState(int blockSize, int outputSize, long[] state)
+ {
+ INITIAL_STATES.put(variantIdentifier(blockSize / 8, outputSize / 8), state);
+ }
+
+ private static Integer variantIdentifier(int blockSizeBytes, int outputSizeBytes)
+ {
+ return new Integer((outputSizeBytes << 16) | blockSizeBytes);
+ }
+
+ private static class UbiTweak
+ {
+ /**
+ * Point at which position might overflow long, so switch to add with carry logic
+ */
+ private static final long LOW_RANGE = Long.MAX_VALUE - Integer.MAX_VALUE;
+
+ /**
+ * Bit 127 = final
+ */
+ private static final long T1_FINAL = 1L << 63;
+
+ /**
+ * Bit 126 = first
+ */
+ private static final long T1_FIRST = 1L << 62;
+
+ /**
+ * UBI uses a 128 bit tweak
+ */
+ private long tweak[] = new long[2];
+
+ /**
+ * Whether 64 bit position exceeded
+ */
+ private boolean extendedPosition;
+
+ public UbiTweak()
+ {
+ reset();
+ }
+
+ public void reset(UbiTweak tweak)
+ {
+ this.tweak = Arrays.clone(tweak.tweak, this.tweak);
+ this.extendedPosition = tweak.extendedPosition;
+ }
+
+ public void reset()
+ {
+ tweak[0] = 0;
+ tweak[1] = 0;
+ extendedPosition = false;
+ setFirst(true);
+ }
+
+ public void setType(int type)
+ {
+ // Bits 120..125 = type
+ tweak[1] = (tweak[1] & 0xFFFFFFC000000000L) | ((type & 0x3FL) << 56);
+ }
+
+ public int getType()
+ {
+ return (int)((tweak[1] >>> 56) & 0x3FL);
+ }
+
+ public void setFirst(boolean first)
+ {
+ if (first)
+ {
+ tweak[1] |= T1_FIRST;
+ }
+ else
+ {
+ tweak[1] &= ~T1_FIRST;
+ }
+ }
+
+ public boolean isFirst()
+ {
+ return ((tweak[1] & T1_FIRST) != 0);
+ }
+
+ public void setFinal(boolean last)
+ {
+ if (last)
+ {
+ tweak[1] |= T1_FINAL;
+ }
+ else
+ {
+ tweak[1] &= ~T1_FINAL;
+ }
+ }
+
+ public boolean isFinal()
+ {
+ return ((tweak[1] & T1_FINAL) != 0);
+ }
+
+ /**
+ * Advances the position in the tweak by the specified value.
+ */
+ public void advancePosition(int advance)
+ {
+ // Bits 0..95 = position
+ if (extendedPosition)
+ {
+ long[] parts = new long[3];
+ parts[0] = tweak[0] & 0xFFFFFFFFL;
+ parts[1] = (tweak[0] >>> 32) & 0xFFFFFFFFL;
+ parts[2] = tweak[1] & 0xFFFFFFFFL;
+
+ long carry = advance;
+ for (int i = 0; i < parts.length; i++)
+ {
+ carry += parts[i];
+ parts[i] = carry;
+ carry >>>= 32;
+ }
+ tweak[0] = ((parts[1] & 0xFFFFFFFFL) << 32) | (parts[0] & 0xFFFFFFFFL);
+ tweak[1] = (tweak[1] & 0xFFFFFFFF00000000L) | (parts[2] & 0xFFFFFFFFL);
+ }
+ else
+ {
+ long position = tweak[0];
+ position += advance;
+ tweak[0] = position;
+ if (position > LOW_RANGE)
+ {
+ extendedPosition = true;
+ }
+ }
+ }
+
+ public long[] getWords()
+ {
+ return tweak;
+ }
+
+ public String toString()
+ {
+ return getType() + " first: " + isFirst() + ", final: " + isFinal();
+ }
+
+ }
+
+ /**
+ * The Unique Block Iteration chaining mode.
+ */
+ // TODO: This might be better as methods...
+ private class UBI
+ {
+ private final UbiTweak tweak = new UbiTweak();
+
+ /**
+ * Buffer for the current block of message data
+ */
+ private byte[] currentBlock;
+
+ /**
+ * Offset into the current message block
+ */
+ private int currentOffset;
+
+ /**
+ * Buffer for message words for feedback into encrypted block
+ */
+ private long[] message;
+
+ public UBI(int blockSize)
+ {
+ currentBlock = new byte[blockSize];
+ message = new long[currentBlock.length / 8];
+ }
+
+ public void reset(UBI ubi)
+ {
+ currentBlock = Arrays.clone(ubi.currentBlock, currentBlock);
+ currentOffset = ubi.currentOffset;
+ message = Arrays.clone(ubi.message, this.message);
+ tweak.reset(ubi.tweak);
+ }
+
+ public void reset(int type)
+ {
+ tweak.reset();
+ tweak.setType(type);
+ currentOffset = 0;
+ }
+
+ public void update(byte[] value, int offset, int len, long[] output)
+ {
+ /*
+ * Buffer complete blocks for the underlying Threefish cipher, only flushing when there
+ * are subsequent bytes (last block must be processed in doFinal() with final=true set).
+ */
+ int copied = 0;
+ while (len > copied)
+ {
+ if (currentOffset == currentBlock.length)
+ {
+ processBlock(output);
+ tweak.setFirst(false);
+ currentOffset = 0;
+ }
+
+ int toCopy = Math.min((len - copied), currentBlock.length - currentOffset);
+ System.arraycopy(value, offset + copied, currentBlock, currentOffset, toCopy);
+ copied += toCopy;
+ currentOffset += toCopy;
+ tweak.advancePosition(toCopy);
+ }
+ }
+
+ private void processBlock(long[] output)
+ {
+ threefish.init(true, chain, tweak.getWords());
+ for (int i = 0; i < message.length; i++)
+ {
+ message[i] = ThreefishEngine.bytesToWord(currentBlock, i * 8);
+ }
+
+ threefish.processBlock(message, output);
+
+ for (int i = 0; i < output.length; i++)
+ {
+ output[i] ^= message[i];
+ }
+ }
+
+ public void doFinal(long[] output)
+ {
+ // Pad remainder of current block with zeroes
+ for (int i = currentOffset; i < currentBlock.length; i++)
+ {
+ currentBlock[i] = 0;
+ }
+
+ tweak.setFinal(true);
+ processBlock(output);
+ }
+
+ }
+
+ /**
+ * Underlying Threefish tweakable block cipher
+ */
+ private ThreefishEngine threefish;
+
+ /**
+ * Size of the digest output, in bytes
+ */
+ private int outputSizeBytes;
+
+ /**
+ * The current chaining/state value
+ */
+ long[] chain;
+
+ /**
+ * The initial state value
+ */
+ private long[] initialState;
+
+ /**
+ * The (optional) key parameter
+ */
+ private byte[] key;
+
+ /**
+ * Parameters to apply prior to the message
+ */
+ private Parameter[] preMessageParameters;
+
+ /**
+ * Parameters to apply after the message, but prior to output
+ */
+ private Parameter[] postMessageParameters;
+
+ /**
+ * The current UBI operation
+ */
+ private UBI ubi;
+
+ /**
+ * Buffer for single byte update method
+ */
+ private final byte[] singleByte = new byte[1];
+
+ /**
+ * Constructs a Skein engine.
+ *
+ * @param blockSizeBits the internal state size in bits - one of {@link #SKEIN_256}, {@link #SKEIN_512} or
+ * {@link #SKEIN_1024}.
+ * @param outputSizeBits the output/digest size to produce in bits, which must be an integral number of
+ * bytes.
+ */
+ public SkeinEngine(int blockSizeBits, int outputSizeBits)
+ {
+ if (outputSizeBits % 8 != 0)
+ {
+ throw new IllegalArgumentException("Output size must be a multiple of 8 bits. :" + outputSizeBits);
+ }
+ // TODO: Prevent digest sizes > block size?
+ this.outputSizeBytes = outputSizeBits / 8;
+
+ this.threefish = new ThreefishEngine(blockSizeBits);
+ this.ubi = new UBI(threefish.getBlockSize());
+ }
+
+ /**
+ * Creates a SkeinEngine as an exact copy of an existing instance.
+ */
+ public SkeinEngine(SkeinEngine engine)
+ {
+ this(engine.getBlockSize() * 8, engine.getOutputSize() * 8);
+ copyIn(engine);
+ }
+
+ private void copyIn(SkeinEngine engine)
+ {
+ this.ubi.reset(engine.ubi);
+ this.chain = Arrays.clone(engine.chain, this.chain);
+ this.initialState = Arrays.clone(engine.initialState, this.initialState);
+ this.key = Arrays.clone(engine.key, this.key);
+ this.preMessageParameters = clone(engine.preMessageParameters, this.preMessageParameters);
+ this.postMessageParameters = clone(engine.postMessageParameters, this.postMessageParameters);
+ }
+
+ private static Parameter[] clone(Parameter[] data, Parameter[] existing)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ if ((existing == null) || (existing.length != data.length))
+ {
+ existing = new Parameter[data.length];
+ }
+ System.arraycopy(data, 0, existing, 0, existing.length);
+ return existing;
+ }
+
+ public Memoable copy()
+ {
+ return new SkeinEngine(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ SkeinEngine s = (SkeinEngine)other;
+ if ((getBlockSize() != s.getBlockSize()) || (outputSizeBytes != s.outputSizeBytes))
+ {
+ throw new IllegalArgumentException("Incompatible parameters in provided SkeinEngine.");
+ }
+ copyIn(s);
+ }
+
+ public int getOutputSize()
+ {
+ return outputSizeBytes;
+ }
+
+ public int getBlockSize()
+ {
+ return threefish.getBlockSize();
+ }
+
+ /**
+ * Initialises the Skein engine with the provided parameters. See {@link SkeinParameters} for
+ * details on the parameterisation of the Skein hash function.
+ *
+ * @param params the parameters to apply to this engine, or <code>null</code> to use no parameters.
+ */
+ public void init(SkeinParameters params)
+ {
+ this.chain = null;
+ this.key = null;
+ this.preMessageParameters = null;
+ this.postMessageParameters = null;
+
+ if (params != null)
+ {
+ byte[] key = params.getKey();
+ if (key.length < 16)
+ {
+ throw new IllegalArgumentException("Skein key must be at least 128 bits.");
+ }
+ initParams(params.getParameters());
+ }
+ createInitialState();
+
+ // Initialise message block
+ ubiInit(PARAM_TYPE_MESSAGE);
+ }
+
+ private void initParams(Hashtable parameters)
+ {
+ Enumeration keys = parameters.keys();
+ final Vector pre = new Vector();
+ final Vector post = new Vector();
+
+ while (keys.hasMoreElements())
+ {
+ Integer type = (Integer)keys.nextElement();
+ byte[] value = (byte[])parameters.get(type);
+
+ if (type.intValue() == PARAM_TYPE_KEY)
+ {
+ this.key = value;
+ }
+ else if (type.intValue() < PARAM_TYPE_MESSAGE)
+ {
+ pre.addElement(new Parameter(type.intValue(), value));
+ }
+ else
+ {
+ post.addElement(new Parameter(type.intValue(), value));
+ }
+ }
+ preMessageParameters = new Parameter[pre.size()];
+ pre.copyInto(preMessageParameters);
+ sort(preMessageParameters);
+
+ postMessageParameters = new Parameter[post.size()];
+ post.copyInto(postMessageParameters);
+ sort(postMessageParameters);
+ }
+
+ private static void sort(Parameter[] params)
+ {
+ if (params == null)
+ {
+ return;
+ }
+ // Insertion sort, for Java 1.1 compatibility
+ for (int i = 1; i < params.length; i++)
+ {
+ Parameter param = params[i];
+ int hole = i;
+ while (hole > 0 && param.getType() < params[hole - 1].getType())
+ {
+ params[hole] = params[hole - 1];
+ hole = hole - 1;
+ }
+ params[hole] = param;
+ }
+ }
+
+ /**
+ * Calculate the initial (pre message block) chaining state.
+ */
+ private void createInitialState()
+ {
+ long[] precalc = (long[])INITIAL_STATES.get(variantIdentifier(getBlockSize(), getOutputSize()));
+ if ((key == null) && (precalc != null))
+ {
+ // Precalculated UBI(CFG)
+ chain = Arrays.clone(precalc);
+ }
+ else
+ {
+ // Blank initial state
+ chain = new long[getBlockSize() / 8];
+
+ // Process key block
+ if (key != null)
+ {
+ ubiComplete(SkeinParameters.PARAM_TYPE_KEY, key);
+ }
+
+ // Process configuration block
+ ubiComplete(PARAM_TYPE_CONFIG, new Configuration(outputSizeBytes * 8).getBytes());
+ }
+
+ // Process additional pre-message parameters
+ if (preMessageParameters != null)
+ {
+ for (int i = 0; i < preMessageParameters.length; i++)
+ {
+ Parameter param = preMessageParameters[i];
+ ubiComplete(param.getType(), param.getValue());
+ }
+ }
+ initialState = Arrays.clone(chain);
+ }
+
+ /**
+ * Reset the engine to the initial state (with the key and any pre-message parameters , ready to
+ * accept message input.
+ */
+ public void reset()
+ {
+ System.arraycopy(initialState, 0, chain, 0, chain.length);
+
+ ubiInit(PARAM_TYPE_MESSAGE);
+ }
+
+ private void ubiComplete(int type, byte[] value)
+ {
+ ubiInit(type);
+ this.ubi.update(value, 0, value.length, chain);
+ ubiFinal();
+ }
+
+ private void ubiInit(int type)
+ {
+ this.ubi.reset(type);
+ }
+
+ private void ubiFinal()
+ {
+ ubi.doFinal(chain);
+ }
+
+ private void checkInitialised()
+ {
+ if (this.ubi == null)
+ {
+ throw new IllegalArgumentException("Skein engine is not initialised.");
+ }
+ }
+
+ public void update(byte in)
+ {
+ singleByte[0] = in;
+ update(singleByte, 0, 1);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ checkInitialised();
+ ubi.update(in, inOff, len, chain);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ checkInitialised();
+ if (out.length < (outOff + outputSizeBytes))
+ {
+ throw new DataLengthException("Output buffer is too short to hold output of " + outputSizeBytes + " bytes");
+ }
+
+ // Finalise message block
+ ubiFinal();
+
+ // Process additional post-message parameters
+ if (postMessageParameters != null)
+ {
+ for (int i = 0; i < postMessageParameters.length; i++)
+ {
+ Parameter param = postMessageParameters[i];
+ ubiComplete(param.getType(), param.getValue());
+ }
+ }
+
+ // Perform the output transform
+ final int blockSize = getBlockSize();
+ final int blocksRequired = ((outputSizeBytes + blockSize - 1) / blockSize);
+ for (int i = 0; i < blocksRequired; i++)
+ {
+ final int toWrite = Math.min(blockSize, outputSizeBytes - (i * blockSize));
+ output(i, out, outOff + (i * blockSize), toWrite);
+ }
+
+ reset();
+
+ return outputSizeBytes;
+ }
+
+ private void output(long outputSequence, byte[] out, int outOff, int outputBytes)
+ {
+ byte[] currentBytes = new byte[8];
+ ThreefishEngine.wordToBytes(outputSequence, currentBytes, 0);
+
+ // Output is a sequence of UBI invocations all of which use and preserve the pre-output
+ // state
+ long[] outputWords = new long[chain.length];
+ ubiInit(PARAM_TYPE_OUTPUT);
+ this.ubi.update(currentBytes, 0, currentBytes.length, outputWords);
+ ubi.doFinal(outputWords);
+
+ final int wordsRequired = ((outputBytes + 8 - 1) / 8);
+ for (int i = 0; i < wordsRequired; i++)
+ {
+ int toWrite = Math.min(8, outputBytes - (i * 8));
+ if (toWrite == 8)
+ {
+ ThreefishEngine.wordToBytes(outputWords[i], out, outOff + (i * 8));
+ }
+ else
+ {
+ ThreefishEngine.wordToBytes(outputWords[i], currentBytes, 0);
+ System.arraycopy(currentBytes, 0, out, outOff + (i * 8), toWrite);
+ }
+ }
+ }
+
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/encodings/PKCS1Encoding.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/encodings/PKCS1Encoding.java
new file mode 100644
index 000000000..3149a1f37
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/encodings/PKCS1Encoding.java
@@ -0,0 +1,238 @@
+package org.spongycastle.crypto.encodings;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+import java.security.SecureRandom;
+
+/**
+ * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
+ * depends on your application - see PKCS1 Version 2 for details.
+ */
+public class PKCS1Encoding
+ implements AsymmetricBlockCipher
+{
+ /**
+ * some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
+ * work with one of these set the system property org.spongycastle.pkcs1.strict to false.
+ * <p>
+ * The system property is checked during construction of the encoding object, it is set to
+ * true by default.
+ * </p>
+ */
+ public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.spongycastle.pkcs1.strict";
+
+ private static final int HEADER_LENGTH = 10;
+
+ private SecureRandom random;
+ private AsymmetricBlockCipher engine;
+ private boolean forEncryption;
+ private boolean forPrivateKey;
+ private boolean useStrictLength;
+
+ /**
+ * Basic constructor.
+ * @param cipher
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ }
+
+ //
+ // for J2ME compatibility
+ //
+ private boolean useStrict()
+ {
+ String strict = System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY);
+
+ return strict == null || strict.equals("true");
+ }
+
+ public AsymmetricBlockCipher getUnderlyingCipher()
+ {
+ return engine;
+ }
+
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ AsymmetricKeyParameter kParam;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ kParam = (AsymmetricKeyParameter)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ kParam = (AsymmetricKeyParameter)param;
+ }
+
+ engine.init(forEncryption, param);
+
+ this.forPrivateKey = kParam.isPrivate();
+ this.forEncryption = forEncryption;
+ }
+
+ public int getInputBlockSize()
+ {
+ int baseBlockSize = engine.getInputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize - HEADER_LENGTH;
+ }
+ else
+ {
+ return baseBlockSize;
+ }
+ }
+
+ public int getOutputBlockSize()
+ {
+ int baseBlockSize = engine.getOutputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize;
+ }
+ else
+ {
+ return baseBlockSize - HEADER_LENGTH;
+ }
+ }
+
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forEncryption)
+ {
+ return encodeBlock(in, inOff, inLen);
+ }
+ else
+ {
+ return decodeBlock(in, inOff, inLen);
+ }
+ }
+
+ private byte[] encodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (inLen > getInputBlockSize())
+ {
+ throw new IllegalArgumentException("input data too large");
+ }
+
+ byte[] block = new byte[engine.getInputBlockSize()];
+
+ if (forPrivateKey)
+ {
+ block[0] = 0x01; // type code 1
+
+ for (int i = 1; i != block.length - inLen - 1; i++)
+ {
+ block[i] = (byte)0xFF;
+ }
+ }
+ else
+ {
+ random.nextBytes(block); // random fill
+
+ block[0] = 0x02; // type code 2
+
+ //
+ // a zero byte marks the end of the padding, so all
+ // the pad bytes must be non-zero.
+ //
+ for (int i = 1; i != block.length - inLen - 1; i++)
+ {
+ while (block[i] == 0)
+ {
+ block[i] = (byte)random.nextInt();
+ }
+ }
+ }
+
+ block[block.length - inLen - 1] = 0x00; // mark the end of the padding
+ System.arraycopy(in, inOff, block, block.length - inLen, inLen);
+
+ return engine.processBlock(block, 0, block.length);
+ }
+
+ /**
+ * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
+ */
+ private byte[] decodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] block = engine.processBlock(in, inOff, inLen);
+
+ if (block.length < getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block truncated");
+ }
+
+ byte type = block[0];
+
+ if (type != 1 && type != 2)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
+
+ if (useStrictLength && block.length != engine.getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block incorrect size");
+ }
+
+ //
+ // find and extract the message block.
+ //
+ int start;
+
+ for (start = 1; start != block.length; start++)
+ {
+ byte pad = block[start];
+
+ if (pad == 0)
+ {
+ break;
+ }
+ if (type == 1 && pad != (byte)0xff)
+ {
+ throw new InvalidCipherTextException("block padding incorrect");
+ }
+ }
+
+ start++; // data should start at the next byte
+
+ if (start > block.length || start < HEADER_LENGTH)
+ {
+ throw new InvalidCipherTextException("no data in block");
+ }
+
+ byte[] result = new byte[block.length - start];
+
+ System.arraycopy(block, start, result, 0, result.length);
+
+ return result;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/engines/NullEngine.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/engines/NullEngine.java
new file mode 100644
index 000000000..219272722
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/engines/NullEngine.java
@@ -0,0 +1,96 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+
+/**
+ * The no-op engine that just copies bytes through, irrespective of whether encrypting and decrypting.
+ * Provided for the sake of completeness.
+ */
+public class NullEngine implements BlockCipher
+{
+ private boolean initialised;
+ protected static final int DEFAULT_BLOCK_SIZE = 1;
+ private int blockSize;
+
+ /**
+ * Constructs a null engine with a block size of 1 byte.
+ */
+ public NullEngine()
+ {
+ this(DEFAULT_BLOCK_SIZE);
+ }
+
+ /**
+ * Constructs a null engine with a specific block size.
+ *
+ * @param blockSize the block size in bytes.
+ */
+ public NullEngine(int blockSize)
+ {
+ this.blockSize = blockSize;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.crypto.BlockCipher#init(boolean, org.spongycastle.crypto.CipherParameters)
+ */
+ public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException
+ {
+ // we don't mind any parameters that may come in
+ this.initialised = true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.crypto.BlockCipher#getAlgorithmName()
+ */
+ public String getAlgorithmName()
+ {
+ return "Null";
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.crypto.BlockCipher#getBlockSize()
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.crypto.BlockCipher#processBlock(byte[], int, byte[], int)
+ */
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException("Null engine not initialised");
+ }
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < blockSize; ++i)
+ {
+ out[outOff + i] = in[inOff + i];
+ }
+
+ return blockSize;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.crypto.BlockCipher#reset()
+ */
+ public void reset()
+ {
+ // nothing needs to be done
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/params/DSAParameterGenerationParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/params/DSAParameterGenerationParameters.java
new file mode 100644
index 000000000..2b57f23c0
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/params/DSAParameterGenerationParameters.java
@@ -0,0 +1,80 @@
+package org.spongycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+public class DSAParameterGenerationParameters
+{
+ public static final int DIGITAL_SIGNATURE_USAGE = 1;
+ public static final int KEY_ESTABLISHMENT_USAGE = 2;
+
+ private int l;
+ private int n;
+ private int usageIndex;
+ private int certainty;
+ private SecureRandom random;
+
+ /**
+ * Construct without a usage index, this will do a random construction of G.
+ *
+ * @param L desired length of prime P in bits (the effective key size).
+ * @param N desired length of prime Q in bits.
+ * @param certainty certainty level for prime number generation.
+ * @param random the source of randomness to use.
+ */
+ public DSAParameterGenerationParameters(
+ int L,
+ int N,
+ int certainty,
+ SecureRandom random)
+ {
+ this(L, N, certainty, random, -1);
+ }
+
+ /**
+ * Construct for a specific usage index - this has the effect of using verifiable canonical generation of G.
+ *
+ * @param L desired length of prime P in bits (the effective key size).
+ * @param N desired length of prime Q in bits.
+ * @param certainty certainty level for prime number generation.
+ * @param random the source of randomness to use.
+ * @param usageIndex a valid usage index.
+ */
+ public DSAParameterGenerationParameters(
+ int L,
+ int N,
+ int certainty,
+ SecureRandom random,
+ int usageIndex)
+ {
+ this.l = L;
+ this.n = N;
+ this.certainty = certainty;
+ this.usageIndex = usageIndex;
+ this.random = random;
+ }
+
+ public int getL()
+ {
+ return l;
+ }
+
+ public int getN()
+ {
+ return n;
+ }
+
+ public int getCertainty()
+ {
+ return certainty;
+ }
+
+ public SecureRandom getRandom()
+ {
+ return random;
+ }
+
+ public int getUsageIndex()
+ {
+ return usageIndex;
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/params/HKDFParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/params/HKDFParameters.java
new file mode 100644
index 000000000..4b125a7c1
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/params/HKDFParameters.java
@@ -0,0 +1,123 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.util.Arrays;
+
+/**
+ * Parameter class for the HKDFBytesGenerator class.
+ */
+public class HKDFParameters
+ implements DerivationParameters
+{
+ private byte[] ikm;
+ private boolean skipExpand;
+ private byte[] salt;
+ private byte[] info;
+
+ private HKDFParameters(final byte[] ikm, final boolean skip,
+ final byte[] salt, final byte[] info)
+ {
+ if (ikm == null)
+ {
+ throw new IllegalArgumentException(
+ "IKM (input keying material) should not be null");
+ }
+
+ this.ikm = Arrays.clone(ikm);
+
+ this.skipExpand = skip;
+
+ if (salt == null || salt.length == 0)
+ {
+ this.salt = null;
+ }
+ else
+ {
+ this.salt = Arrays.clone(salt);
+ }
+
+ if (info == null)
+ {
+ this.info = new byte[0];
+ }
+ else
+ {
+ this.info = Arrays.clone(info);
+ }
+ }
+
+ /**
+ * Generates parameters for HKDF, specifying both the optional salt and
+ * optional info. Step 1: Extract won't be skipped.
+ *
+ * @param ikm the input keying material or seed
+ * @param salt the salt to use, may be null for a salt for hashLen zeros
+ * @param info the info to use, may be null for an info field of zero bytes
+ */
+ public HKDFParameters(final byte[] ikm, final byte[] salt, final byte[] info)
+ {
+ this(ikm, false, salt, info);
+ }
+
+ /**
+ * Factory method that makes the HKDF skip the extract part of the key
+ * derivation function.
+ *
+ * @param ikm the input keying material or seed, directly used for step 2:
+ * Expand
+ * @param info the info to use, may be null for an info field of zero bytes
+ * @return HKDFParameters that makes the implementation skip step 1
+ */
+ public static HKDFParameters skipExtractParameters(final byte[] ikm,
+ final byte[] info)
+ {
+
+ return new HKDFParameters(ikm, true, null, info);
+ }
+
+ public static HKDFParameters defaultParameters(final byte[] ikm)
+ {
+ return new HKDFParameters(ikm, false, null, null);
+ }
+
+ /**
+ * Returns the input keying material or seed.
+ *
+ * @return the keying material
+ */
+ public byte[] getIKM()
+ {
+ return Arrays.clone(ikm);
+ }
+
+ /**
+ * Returns if step 1: extract has to be skipped or not
+ *
+ * @return true for skipping, false for no skipping of step 1
+ */
+ public boolean skipExtract()
+ {
+ return skipExpand;
+ }
+
+ /**
+ * Returns the salt, or null if the salt should be generated as a byte array
+ * of HashLen zeros.
+ *
+ * @return the salt, or null
+ */
+ public byte[] getSalt()
+ {
+ return Arrays.clone(salt);
+ }
+
+ /**
+ * Returns the info field, which may be empty (null is converted to empty).
+ *
+ * @return the info field, never null
+ */
+ public byte[] getInfo()
+ {
+ return Arrays.clone(info);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/prng/BasicEntropySourceProvider.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/prng/BasicEntropySourceProvider.java
new file mode 100644
index 000000000..31c85036d
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/prng/BasicEntropySourceProvider.java
@@ -0,0 +1,57 @@
+package org.spongycastle.crypto.prng;
+
+import java.security.SecureRandom;
+
+/**
+ * An EntropySourceProvider where entropy generation is based on a SecureRandom output using SecureRandom.generateSeed().
+ */
+public class BasicEntropySourceProvider
+ implements EntropySourceProvider
+{
+ private SecureRandom _sr;
+ private boolean _predictionResistant;
+
+ /**
+ * Create a entropy source provider based on the passed in SecureRandom.
+ *
+ * @param random the SecureRandom to base EntropySource construction on.
+ * @param isPredictionResistant boolean indicating if the SecureRandom is based on prediction resistant entropy or not (true if it is).
+ */
+ public BasicEntropySourceProvider(SecureRandom random, boolean isPredictionResistant)
+ {
+ _sr = random;
+ _predictionResistant = isPredictionResistant;
+ }
+
+ /**
+ * Return an entropy source that will create bitsRequired bits of entropy on
+ * each invocation of getEntropy().
+ *
+ * @param bitsRequired size (in bits) of entropy to be created by the provided source.
+ * @return an EntropySource that generates bitsRequired bits of entropy on each call to its getEntropy() method.
+ */
+ public EntropySource get(final int bitsRequired)
+ {
+ return new EntropySource()
+ {
+ public boolean isPredictionResistant()
+ {
+ return _predictionResistant;
+ }
+
+ public byte[] getEntropy()
+ {
+ byte[] rv = new byte[(bitsRequired + 7) / 8];
+
+ _sr.nextBytes(rv);
+
+ return rv;
+ }
+
+ public int entropySize()
+ {
+ return bitsRequired;
+ }
+ };
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/prng/SP800SecureRandomBuilder.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/prng/SP800SecureRandomBuilder.java
new file mode 100644
index 000000000..e682f6870
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/prng/SP800SecureRandomBuilder.java
@@ -0,0 +1,289 @@
+package org.spongycastle.crypto.prng;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.prng.drbg.CTRSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.DualECPoints;
+import org.spongycastle.crypto.prng.drbg.DualECSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.HMacSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.HashSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.SP80090DRBG;
+
+/**
+ * Builder class for making SecureRandom objects based on SP 800-90A Deterministic Random Bit Generators (DRBG).
+ */
+public class SP800SecureRandomBuilder
+{
+ private SecureRandom random;
+ private EntropySourceProvider entropySourceProvider;
+
+ private byte[] personalizationString;
+ private int securityStrength = 256;
+ private int entropyBitsRequired = 256;
+
+ /**
+ * Basic constructor, creates a builder using an EntropySourceProvider based on the default SecureRandom with
+ * predictionResistant set to false.
+ * <p>
+ * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
+ * the default SecureRandom does for its generateSeed() call.
+ * </p>
+ */
+ public SP800SecureRandomBuilder()
+ {
+ this(new SecureRandom(), false);
+ }
+
+ /**
+ * Construct a builder with an EntropySourceProvider based on the passed in SecureRandom and the passed in value
+ * for prediction resistance.
+ * <p>
+ * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
+ * the passed in SecureRandom does for its generateSeed() call.
+ * </p>
+ * @param entropySource
+ * @param predictionResistant
+ */
+ public SP800SecureRandomBuilder(SecureRandom entropySource, boolean predictionResistant)
+ {
+ this.random = entropySource;
+ this.entropySourceProvider = new BasicEntropySourceProvider(random, predictionResistant);
+ }
+
+ /**
+ * Create a builder which makes creates the SecureRandom objects from a specified entropy source provider.
+ * <p>
+ * <b>Note:</b> If this constructor is used any calls to setSeed() in the resulting SecureRandom will be ignored.
+ * </p>
+ * @param entropySourceProvider a provider of EntropySource objects.
+ */
+ public SP800SecureRandomBuilder(EntropySourceProvider entropySourceProvider)
+ {
+ this.random = null;
+ this.entropySourceProvider = entropySourceProvider;
+ }
+
+ /**
+ * Set the personalization string for DRBG SecureRandoms created by this builder
+ * @param personalizationString the personalisation string for the underlying DRBG.
+ * @return the current builder.
+ */
+ public SP800SecureRandomBuilder setPersonalizationString(byte[] personalizationString)
+ {
+ this.personalizationString = personalizationString;
+
+ return this;
+ }
+
+ /**
+ * Set the security strength required for DRBGs used in building SecureRandom objects.
+ *
+ * @param securityStrength the security strength (in bits)
+ * @return the current builder.
+ */
+ public SP800SecureRandomBuilder setSecurityStrength(int securityStrength)
+ {
+ this.securityStrength = securityStrength;
+
+ return this;
+ }
+
+ /**
+ * Set the amount of entropy bits required for seeding and reseeding DRBGs used in building SecureRandom objects.
+ *
+ * @param entropyBitsRequired the number of bits of entropy to be requested from the entropy source on each seed/reseed.
+ * @return the current builder.
+ */
+ public SP800SecureRandomBuilder setEntropyBitsRequired(int entropyBitsRequired)
+ {
+ this.entropyBitsRequired = entropyBitsRequired;
+
+ return this;
+ }
+
+ /**
+ * Build a SecureRandom based on a SP 800-90A Hash DRBG.
+ *
+ * @param digest digest algorithm to use in the DRBG underneath the SecureRandom.
+ * @param nonce nonce value to use in DRBG construction.
+ * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes.
+ * @return a SecureRandom supported by a Hash DRBG.
+ */
+ public SP800SecureRandom buildHash(Digest digest, byte[] nonce, boolean predictionResistant)
+ {
+ return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new HashDRBGProvider(digest, nonce, personalizationString, securityStrength), predictionResistant);
+ }
+
+ /**
+ * Build a SecureRandom based on a SP 800-90A CTR DRBG.
+ *
+ * @param cipher the block cipher to base the DRBG on.
+ * @param keySizeInBits key size in bits to be used with the block cipher.
+ * @param nonce nonce value to use in DRBG construction.
+ * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes.
+ * @return a SecureRandom supported by a CTR DRBG.
+ */
+ public SP800SecureRandom buildCTR(BlockCipher cipher, int keySizeInBits, byte[] nonce, boolean predictionResistant)
+ {
+ return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new CTRDRBGProvider(cipher, keySizeInBits, nonce, personalizationString, securityStrength), predictionResistant);
+ }
+
+ /**
+ * Build a SecureRandom based on a SP 800-90A HMAC DRBG.
+ *
+ * @param hMac HMAC algorithm to use in the DRBG underneath the SecureRandom.
+ * @param nonce nonce value to use in DRBG construction.
+ * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes.
+ * @return a SecureRandom supported by a HMAC DRBG.
+ */
+ public SP800SecureRandom buildHMAC(Mac hMac, byte[] nonce, boolean predictionResistant)
+ {
+ return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new HMacDRBGProvider(hMac, nonce, personalizationString, securityStrength), predictionResistant);
+ }
+
+ /**
+ * Build a SecureRandom based on a SP 800-90A Dual EC DRBG.
+ *
+ * @param digest digest algorithm to use in the DRBG underneath the SecureRandom.
+ * @param nonce nonce value to use in DRBG construction.
+ * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes.
+ * @return a SecureRandom supported by a Dual EC DRBG.
+ */
+ public SP800SecureRandom buildDualEC(Digest digest, byte[] nonce, boolean predictionResistant)
+ {
+ return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new DualECDRBGProvider(digest, nonce, personalizationString, securityStrength), predictionResistant);
+ }
+
+ /**
+ * Build a SecureRandom based on a SP 800-90A Dual EC DRBG.
+ *
+ * @param pointSet an array of DualECPoints to use for DRB generation.
+ * @param digest digest algorithm to use in the DRBG underneath the SecureRandom.
+ * @param nonce nonce value to use in DRBG construction.
+ * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes.
+ * @return a SecureRandom supported by a Dual EC DRBG.
+ */
+ public SP800SecureRandom buildDualEC(DualECPoints[] pointSet, Digest digest, byte[] nonce, boolean predictionResistant)
+ {
+ return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new ConfigurableDualECDRBGProvider(pointSet, digest, nonce, personalizationString, securityStrength), predictionResistant);
+ }
+
+ private static class HashDRBGProvider
+ implements DRBGProvider
+ {
+ private final Digest digest;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public HashDRBGProvider(Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.digest = digest;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new HashSP800DRBG(digest, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+
+ private static class DualECDRBGProvider
+ implements DRBGProvider
+ {
+ private final Digest digest;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public DualECDRBGProvider(Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.digest = digest;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new DualECSP800DRBG(digest, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+
+ private static class ConfigurableDualECDRBGProvider
+ implements DRBGProvider
+ {
+ private final DualECPoints[] pointSet;
+ private final Digest digest;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public ConfigurableDualECDRBGProvider(DualECPoints[] pointSet, Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.pointSet = new DualECPoints[pointSet.length];
+ System.arraycopy(pointSet, 0, this.pointSet, 0, pointSet.length);
+ this.digest = digest;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new DualECSP800DRBG(pointSet, digest, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+
+ private static class HMacDRBGProvider
+ implements DRBGProvider
+ {
+ private final Mac hMac;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public HMacDRBGProvider(Mac hMac, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.hMac = hMac;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new HMacSP800DRBG(hMac, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+
+ private static class CTRDRBGProvider
+ implements DRBGProvider
+ {
+
+ private final BlockCipher blockCipher;
+ private final int keySizeInBits;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public CTRDRBGProvider(BlockCipher blockCipher, int keySizeInBits, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.blockCipher = blockCipher;
+ this.keySizeInBits = keySizeInBits;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new CTRSP800DRBG(blockCipher, keySizeInBits, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/signers/RSADigestSigner.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/signers/RSADigestSigner.java
new file mode 100644
index 000000000..e6a99d890
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/signers/RSADigestSigner.java
@@ -0,0 +1,238 @@
+package org.spongycastle.crypto.signers;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.nist.NISTObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.DigestInfo;
+import org.spongycastle.asn1.x509.X509ObjectIdentifiers;
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.crypto.encodings.PKCS1Encoding;
+import org.spongycastle.crypto.engines.RSABlindedEngine;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.util.Arrays;
+
+public class RSADigestSigner
+ implements Signer
+{
+ private final AsymmetricBlockCipher rsaEngine = new PKCS1Encoding(new RSABlindedEngine());
+ private AlgorithmIdentifier algId;
+ private Digest digest;
+ private boolean forSigning;
+
+ private static final Hashtable oidMap = new Hashtable();
+
+ /*
+ * Load OID table.
+ */
+ static
+ {
+ oidMap.put("RIPEMD128", TeleTrusTObjectIdentifiers.ripemd128);
+ oidMap.put("RIPEMD160", TeleTrusTObjectIdentifiers.ripemd160);
+ oidMap.put("RIPEMD256", TeleTrusTObjectIdentifiers.ripemd256);
+
+ oidMap.put("SHA-1", X509ObjectIdentifiers.id_SHA1);
+ oidMap.put("SHA-224", NISTObjectIdentifiers.id_sha224);
+ oidMap.put("SHA-256", NISTObjectIdentifiers.id_sha256);
+ oidMap.put("SHA-384", NISTObjectIdentifiers.id_sha384);
+ oidMap.put("SHA-512", NISTObjectIdentifiers.id_sha512);
+
+ oidMap.put("MD2", PKCSObjectIdentifiers.md2);
+ oidMap.put("MD4", PKCSObjectIdentifiers.md4);
+ oidMap.put("MD5", PKCSObjectIdentifiers.md5);
+ }
+
+ public RSADigestSigner(
+ Digest digest)
+ {
+ this(digest, (ASN1ObjectIdentifier)oidMap.get(digest.getAlgorithmName()));
+ }
+
+ public RSADigestSigner(
+ Digest digest,
+ ASN1ObjectIdentifier digestOid)
+ {
+ this.digest = digest;
+ this.algId = new AlgorithmIdentifier(digestOid, DERNull.INSTANCE);
+ }
+
+ /**
+ * @deprecated
+ */
+ public String getAlgorithmName()
+ {
+ return digest.getAlgorithmName() + "withRSA";
+ }
+
+ /**
+ * initialise the signer for signing or verification.
+ *
+ * @param forSigning
+ * true if for signing, false otherwise
+ * @param parameters
+ * necessary parameters.
+ */
+ public void init(
+ boolean forSigning,
+ CipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+ AsymmetricKeyParameter k;
+
+ if (parameters instanceof ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)parameters;
+ }
+
+ if (forSigning && !k.isPrivate())
+ {
+ throw new IllegalArgumentException("signing requires private key");
+ }
+
+ if (!forSigning && k.isPrivate())
+ {
+ throw new IllegalArgumentException("verification requires public key");
+ }
+
+ reset();
+
+ rsaEngine.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 update(
+ byte[] input,
+ int inOff,
+ int length)
+ {
+ digest.update(input, inOff, length);
+ }
+
+ /**
+ * Generate a signature for the message we've been loaded with using the key
+ * we were initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException, DataLengthException
+ {
+ if (!forSigning)
+ {
+ throw new IllegalStateException("RSADigestSigner not initialised for signature generation.");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ try
+ {
+ byte[] data = derEncode(hash);
+ return rsaEngine.processBlock(data, 0, data.length);
+ }
+ catch (IOException e)
+ {
+ throw new CryptoException("unable to encode signature: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * return true if the internal state represents the signature described in
+ * the passed in array.
+ */
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ if (forSigning)
+ {
+ throw new IllegalStateException("RSADigestSigner not initialised for verification");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+
+ digest.doFinal(hash, 0);
+
+ byte[] sig;
+ byte[] expected;
+
+ try
+ {
+ sig = rsaEngine.processBlock(signature, 0, signature.length);
+ expected = derEncode(hash);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ if (sig.length == expected.length)
+ {
+ return Arrays.constantTimeAreEqual(sig, expected);
+ }
+ else if (sig.length == expected.length - 2) // NULL left out
+ {
+ int sigOffset = sig.length - hash.length - 2;
+ int expectedOffset = expected.length - hash.length - 2;
+
+ expected[1] -= 2; // adjust lengths
+ expected[3] -= 2;
+
+ int nonEqual = 0;
+
+ for (int i = 0; i < hash.length; i++)
+ {
+ nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]);
+ }
+
+ for (int i = 0; i < sigOffset; i++)
+ {
+ nonEqual |= (sig[i] ^ expected[i]); // check header less NULL
+ }
+
+ return nonEqual == 0;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public void reset()
+ {
+ digest.reset();
+ }
+
+ private byte[] derEncode(
+ byte[] hash)
+ throws IOException
+ {
+ DigestInfo dInfo = new DigestInfo(algId, hash);
+
+ return dInfo.getEncoded(ASN1Encoding.DER);
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReassembler.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReassembler.java
new file mode 100644
index 000000000..baf9c92fd
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReassembler.java
@@ -0,0 +1,136 @@
+package org.spongycastle.crypto.tls;
+
+import java.util.Vector;
+
+class DTLSReassembler
+{
+
+ private short msg_type;
+ private byte[] body;
+
+ private Vector missing = new Vector();
+
+ DTLSReassembler(short msg_type, int length)
+ {
+ this.msg_type = msg_type;
+ this.body = new byte[length];
+ this.missing.addElement(new Range(0, length));
+ }
+
+ short getType()
+ {
+ return msg_type;
+ }
+
+ byte[] getBodyIfComplete()
+ {
+ return missing.isEmpty() ? body : null;
+ }
+
+ void contributeFragment(short msg_type, int length, byte[] buf, int off, int fragment_offset,
+ int fragment_length)
+ {
+
+ int fragment_end = fragment_offset + fragment_length;
+
+ if (this.msg_type != msg_type || this.body.length != length || fragment_end > length)
+ {
+ return;
+ }
+
+ if (fragment_length == 0)
+ {
+ // NOTE: Empty messages still require an empty fragment to complete it
+ if (fragment_offset == 0 && !missing.isEmpty())
+ {
+ Range firstRange = (Range)missing.firstElement();
+ if (firstRange.getEnd() == 0)
+ {
+ missing.removeElementAt(0);
+ }
+ }
+ return;
+ }
+
+ for (int i = 0; i < missing.size(); ++i)
+ {
+ Range range = (Range)missing.elementAt(i);
+ if (range.getStart() >= fragment_end)
+ {
+ break;
+ }
+ if (range.getEnd() > fragment_offset)
+ {
+
+ int copyStart = Math.max(range.getStart(), fragment_offset);
+ int copyEnd = Math.min(range.getEnd(), fragment_end);
+ int copyLength = copyEnd - copyStart;
+
+ System.arraycopy(buf, off + copyStart - fragment_offset, body, copyStart,
+ copyLength);
+
+ if (copyStart == range.getStart())
+ {
+ if (copyEnd == range.getEnd())
+ {
+ missing.removeElementAt(i--);
+ }
+ else
+ {
+ range.setStart(copyEnd);
+ }
+ }
+ else
+ {
+ if (copyEnd == range.getEnd())
+ {
+ range.setEnd(copyStart);
+ }
+ else
+ {
+ missing.insertElementAt(new Range(copyEnd, range.getEnd()), ++i);
+ range.setEnd(copyStart);
+ }
+ }
+ }
+ }
+ }
+
+ void reset()
+ {
+ this.missing.removeAllElements();
+ this.missing.addElement(new Range(0, body.length));
+ }
+
+ private static class Range
+ {
+
+ private int start, end;
+
+ Range(int start, int end)
+ {
+ this.start = start;
+ this.end = end;
+ }
+
+ public int getStart()
+ {
+ return start;
+ }
+
+ public void setStart(int start)
+ {
+ this.start = start;
+ }
+
+ public int getEnd()
+ {
+ return end;
+ }
+
+ public void setEnd(int end)
+ {
+ this.end = end;
+ }
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReliableHandshake.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReliableHandshake.java
new file mode 100644
index 000000000..1a9911619
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReliableHandshake.java
@@ -0,0 +1,457 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.util.Integers;
+
+class DTLSReliableHandshake
+{
+ private final static int MAX_RECEIVE_AHEAD = 10;
+
+ private DTLSRecordLayer recordLayer;
+
+ private TlsHandshakeHash handshakeHash;
+
+ private Hashtable currentInboundFlight = new Hashtable();
+ private Hashtable previousInboundFlight = null;
+ private Vector outboundFlight = new Vector();
+ private boolean sending = true;
+
+ private int message_seq = 0, next_receive_seq = 0;
+
+ DTLSReliableHandshake(TlsContext context, DTLSRecordLayer transport)
+ {
+ this.recordLayer = transport;
+ this.handshakeHash = new DeferredHash();
+ this.handshakeHash.init(context);
+ }
+
+ void notifyHelloComplete()
+ {
+ this.handshakeHash = handshakeHash.notifyPRFDetermined();
+ }
+
+ TlsHandshakeHash getHandshakeHash()
+ {
+ return handshakeHash;
+ }
+
+ TlsHandshakeHash prepareToFinish()
+ {
+ TlsHandshakeHash result = handshakeHash;
+ this.handshakeHash = handshakeHash.stopTracking();
+ return result;
+ }
+
+ void sendMessage(short msg_type, byte[] body)
+ throws IOException
+ {
+ TlsUtils.checkUint24(body.length);
+
+ if (!sending)
+ {
+ checkInboundFlight();
+ sending = true;
+ outboundFlight.removeAllElements();
+ }
+
+ Message message = new Message(message_seq++, msg_type, body);
+
+ outboundFlight.addElement(message);
+
+ writeMessage(message);
+ updateHandshakeMessagesDigest(message);
+ }
+
+ byte[] receiveMessageBody(short msg_type)
+ throws IOException
+ {
+ Message message = receiveMessage();
+ if (message.getType() != msg_type)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ return message.getBody();
+ }
+
+ Message receiveMessage()
+ throws IOException
+ {
+ if (sending)
+ {
+ sending = false;
+ prepareInboundFlight();
+ }
+
+ // Check if we already have the next message waiting
+ {
+ DTLSReassembler next = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(next_receive_seq));
+ if (next != null)
+ {
+ byte[] body = next.getBodyIfComplete();
+ if (body != null)
+ {
+ previousInboundFlight = null;
+ return updateHandshakeMessagesDigest(new Message(next_receive_seq++, next.getType(), body));
+ }
+ }
+ }
+
+ byte[] buf = null;
+
+ // TODO Check the conditions under which we should reset this
+ int readTimeoutMillis = 1000;
+
+ for (; ; )
+ {
+ int receiveLimit = recordLayer.getReceiveLimit();
+ if (buf == null || buf.length < receiveLimit)
+ {
+ buf = new byte[receiveLimit];
+ }
+
+ // TODO Handle records containing multiple handshake messages
+
+ try
+ {
+ for (; ; )
+ {
+ int received = recordLayer.receive(buf, 0, receiveLimit, readTimeoutMillis);
+ if (received < 0)
+ {
+ break;
+ }
+ if (received < 12)
+ {
+ continue;
+ }
+ int fragment_length = TlsUtils.readUint24(buf, 9);
+ if (received != (fragment_length + 12))
+ {
+ continue;
+ }
+ int seq = TlsUtils.readUint16(buf, 4);
+ if (seq > (next_receive_seq + MAX_RECEIVE_AHEAD))
+ {
+ continue;
+ }
+ short msg_type = TlsUtils.readUint8(buf, 0);
+ int length = TlsUtils.readUint24(buf, 1);
+ int fragment_offset = TlsUtils.readUint24(buf, 6);
+ if (fragment_offset + fragment_length > length)
+ {
+ continue;
+ }
+
+ if (seq < next_receive_seq)
+ {
+ /*
+ * NOTE: If we receive the previous flight of incoming messages in full
+ * again, retransmit our last flight
+ */
+ if (previousInboundFlight != null)
+ {
+ DTLSReassembler reassembler = (DTLSReassembler)previousInboundFlight.get(Integers
+ .valueOf(seq));
+ if (reassembler != null)
+ {
+
+ reassembler.contributeFragment(msg_type, length, buf, 12, fragment_offset,
+ fragment_length);
+
+ if (checkAll(previousInboundFlight))
+ {
+
+ resendOutboundFlight();
+
+ /*
+ * TODO[DTLS] implementations SHOULD back off handshake packet
+ * size during the retransmit backoff.
+ */
+ readTimeoutMillis = Math.min(readTimeoutMillis * 2, 60000);
+
+ resetAll(previousInboundFlight);
+ }
+ }
+ }
+ }
+ else
+ {
+
+ DTLSReassembler reassembler = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(seq));
+ if (reassembler == null)
+ {
+ reassembler = new DTLSReassembler(msg_type, length);
+ currentInboundFlight.put(Integers.valueOf(seq), reassembler);
+ }
+
+ reassembler.contributeFragment(msg_type, length, buf, 12, fragment_offset, fragment_length);
+
+ if (seq == next_receive_seq)
+ {
+ byte[] body = reassembler.getBodyIfComplete();
+ if (body != null)
+ {
+ previousInboundFlight = null;
+ return updateHandshakeMessagesDigest(new Message(next_receive_seq++,
+ reassembler.getType(), body));
+ }
+ }
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ // NOTE: Assume this is a timeout for the moment
+ }
+
+ resendOutboundFlight();
+
+ /*
+ * TODO[DTLS] implementations SHOULD back off handshake packet size during the
+ * retransmit backoff.
+ */
+ readTimeoutMillis = Math.min(readTimeoutMillis * 2, 60000);
+ }
+ }
+
+ void finish()
+ {
+ DTLSHandshakeRetransmit retransmit = null;
+ if (!sending)
+ {
+ checkInboundFlight();
+ }
+ else if (currentInboundFlight != null)
+ {
+ /*
+ * RFC 6347 4.2.4. In addition, for at least twice the default MSL defined for [TCP],
+ * when in the FINISHED state, the node that transmits the last flight (the server in an
+ * ordinary handshake or the client in a resumed handshake) MUST respond to a retransmit
+ * of the peer's last flight with a retransmit of the last flight.
+ */
+ retransmit = new DTLSHandshakeRetransmit()
+ {
+ public void receivedHandshakeRecord(int epoch, byte[] buf, int off, int len)
+ throws IOException
+ {
+ /*
+ * TODO Need to handle the case where the previous inbound flight contains
+ * messages from two epochs.
+ */
+ if (len < 12)
+ {
+ return;
+ }
+ int fragment_length = TlsUtils.readUint24(buf, off + 9);
+ if (len != (fragment_length + 12))
+ {
+ return;
+ }
+ int seq = TlsUtils.readUint16(buf, off + 4);
+ if (seq >= next_receive_seq)
+ {
+ return;
+ }
+
+ short msg_type = TlsUtils.readUint8(buf, off);
+
+ // TODO This is a hack that only works until we try to support renegotiation
+ int expectedEpoch = msg_type == HandshakeType.finished ? 1 : 0;
+ if (epoch != expectedEpoch)
+ {
+ return;
+ }
+
+ int length = TlsUtils.readUint24(buf, off + 1);
+ int fragment_offset = TlsUtils.readUint24(buf, off + 6);
+ if (fragment_offset + fragment_length > length)
+ {
+ return;
+ }
+
+ DTLSReassembler reassembler = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(seq));
+ if (reassembler != null)
+ {
+ reassembler.contributeFragment(msg_type, length, buf, off + 12, fragment_offset,
+ fragment_length);
+ if (checkAll(currentInboundFlight))
+ {
+ resendOutboundFlight();
+ resetAll(currentInboundFlight);
+ }
+ }
+ }
+ };
+ }
+
+ recordLayer.handshakeSuccessful(retransmit);
+ }
+
+ void resetHandshakeMessagesDigest()
+ {
+ handshakeHash.reset();
+ }
+
+ /**
+ * Check that there are no "extra" messages left in the current inbound flight
+ */
+ private void checkInboundFlight()
+ {
+ Enumeration e = currentInboundFlight.keys();
+ while (e.hasMoreElements())
+ {
+ Integer key = (Integer)e.nextElement();
+ if (key.intValue() >= next_receive_seq)
+ {
+ // TODO Should this be considered an error?
+ }
+ }
+ }
+
+ private void prepareInboundFlight()
+ {
+ resetAll(currentInboundFlight);
+ previousInboundFlight = currentInboundFlight;
+ currentInboundFlight = new Hashtable();
+ }
+
+ private void resendOutboundFlight()
+ throws IOException
+ {
+ recordLayer.resetWriteEpoch();
+ for (int i = 0; i < outboundFlight.size(); ++i)
+ {
+ writeMessage((Message)outboundFlight.elementAt(i));
+ }
+ }
+
+ private Message updateHandshakeMessagesDigest(Message message)
+ throws IOException
+ {
+ if (message.getType() != HandshakeType.hello_request)
+ {
+ byte[] body = message.getBody();
+ byte[] buf = new byte[12];
+ TlsUtils.writeUint8(message.getType(), buf, 0);
+ TlsUtils.writeUint24(body.length, buf, 1);
+ TlsUtils.writeUint16(message.getSeq(), buf, 4);
+ TlsUtils.writeUint24(0, buf, 6);
+ TlsUtils.writeUint24(body.length, buf, 9);
+ handshakeHash.update(buf, 0, buf.length);
+ handshakeHash.update(body, 0, body.length);
+ }
+ return message;
+ }
+
+ private void writeMessage(Message message)
+ throws IOException
+ {
+ int sendLimit = recordLayer.getSendLimit();
+ int fragmentLimit = sendLimit - 12;
+
+ // TODO Support a higher minimum fragment size?
+ if (fragmentLimit < 1)
+ {
+ // TODO Should we be throwing an exception here?
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ int length = message.getBody().length;
+
+ // NOTE: Must still send a fragment if body is empty
+ int fragment_offset = 0;
+ do
+ {
+ int fragment_length = Math.min(length - fragment_offset, fragmentLimit);
+ writeHandshakeFragment(message, fragment_offset, fragment_length);
+ fragment_offset += fragment_length;
+ }
+ while (fragment_offset < length);
+ }
+
+ private void writeHandshakeFragment(Message message, int fragment_offset, int fragment_length)
+ throws IOException
+ {
+ RecordLayerBuffer fragment = new RecordLayerBuffer(12 + fragment_length);
+ TlsUtils.writeUint8(message.getType(), fragment);
+ TlsUtils.writeUint24(message.getBody().length, fragment);
+ TlsUtils.writeUint16(message.getSeq(), fragment);
+ TlsUtils.writeUint24(fragment_offset, fragment);
+ TlsUtils.writeUint24(fragment_length, fragment);
+ fragment.write(message.getBody(), fragment_offset, fragment_length);
+
+ fragment.sendToRecordLayer(recordLayer);
+ }
+
+ private static boolean checkAll(Hashtable inboundFlight)
+ {
+ Enumeration e = inboundFlight.elements();
+ while (e.hasMoreElements())
+ {
+ if (((DTLSReassembler)e.nextElement()).getBodyIfComplete() == null)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static void resetAll(Hashtable inboundFlight)
+ {
+ Enumeration e = inboundFlight.elements();
+ while (e.hasMoreElements())
+ {
+ ((DTLSReassembler)e.nextElement()).reset();
+ }
+ }
+
+ static class Message
+ {
+ private final int message_seq;
+ private final short msg_type;
+ private final byte[] body;
+
+ private Message(int message_seq, short msg_type, byte[] body)
+ {
+ this.message_seq = message_seq;
+ this.msg_type = msg_type;
+ this.body = body;
+ }
+
+ public int getSeq()
+ {
+ return message_seq;
+ }
+
+ public short getType()
+ {
+ return msg_type;
+ }
+
+ public byte[] getBody()
+ {
+ return body;
+ }
+ }
+
+ static class RecordLayerBuffer extends ByteArrayOutputStream
+ {
+ RecordLayerBuffer(int size)
+ {
+ super(size);
+ }
+
+ void sendToRecordLayer(DTLSRecordLayer recordLayer) throws IOException
+ {
+ recordLayer.send(buf, 0, count);
+ buf = null;
+ }
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/UDPTransport.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/UDPTransport.java
new file mode 100644
index 000000000..913c1e552
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/UDPTransport.java
@@ -0,0 +1,106 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+
+public class UDPTransport
+ implements DatagramTransport
+{
+ protected final static int MIN_IP_OVERHEAD = 20;
+ protected final static int MAX_IP_OVERHEAD = MIN_IP_OVERHEAD + 64;
+ protected final static int UDP_OVERHEAD = 8;
+
+ protected final DatagramSocket socket;
+ protected final int receiveLimit, sendLimit;
+
+ public UDPTransport(DatagramSocket socket, int mtu)
+ throws IOException
+ {
+ //
+ // In 1.3 and earlier sockets were bound and connected during creation
+ //
+ //if (!socket.isBound() || !socket.isConnected())
+ //{
+ // throw new IllegalArgumentException("'socket' must be bound and connected");
+ //}
+
+ this.socket = socket;
+
+ // NOTE: As of JDK 1.6, can use NetworkInterface.getMTU
+
+ this.receiveLimit = mtu - MIN_IP_OVERHEAD - UDP_OVERHEAD;
+ this.sendLimit = mtu - MAX_IP_OVERHEAD - UDP_OVERHEAD;
+ }
+
+ public int getReceiveLimit()
+ {
+ return receiveLimit;
+ }
+
+ public int getSendLimit()
+ {
+ // TODO[DTLS] Implement Path-MTU discovery?
+ return sendLimit;
+ }
+
+ public int receive(byte[] buf, int off, int len, int waitMillis)
+ throws IOException
+ {
+ socket.setSoTimeout(waitMillis);
+
+ if (off == 0)
+ {
+ DatagramPacket packet = new DatagramPacket(buf, len);
+ socket.receive(packet);
+
+ return packet.getLength();
+ }
+ else
+ {
+ byte[] rv = new byte[len];
+
+ DatagramPacket packet = new DatagramPacket(rv, len);
+ socket.receive(packet);
+
+ System.arraycopy(rv, 0, buf, off, packet.getLength());
+
+ return packet.getLength();
+ }
+ }
+
+ public void send(byte[] buf, int off, int len)
+ throws IOException
+ {
+ if (len > getSendLimit())
+ {
+ /*
+ * RFC 4347 4.1.1. "If the application attempts to send a record larger than the MTU,
+ * the DTLS implementation SHOULD generate an error, thus avoiding sending a packet
+ * which will be fragmented."
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ if (off == 0)
+ {
+ DatagramPacket packet = new DatagramPacket(buf, len);
+ socket.send(packet);
+ }
+ else
+ {
+ byte[] data = new byte[len];
+
+ System.arraycopy(buf, off, data, 0, len);
+
+ DatagramPacket packet = new DatagramPacket(data, len);
+ socket.send(packet);
+ }
+ }
+
+ public void close()
+ throws IOException
+ {
+ socket.close();
+ }
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/i18n/LocalizedMessage.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/i18n/LocalizedMessage.java
new file mode 100644
index 000000000..1eab110cb
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/i18n/LocalizedMessage.java
@@ -0,0 +1,464 @@
+package org.spongycastle.i18n;
+
+import org.spongycastle.i18n.filter.Filter;
+import org.spongycastle.i18n.filter.TrustedInput;
+import org.spongycastle.i18n.filter.UntrustedInput;
+import org.spongycastle.i18n.filter.UntrustedUrlInput;
+
+import java.io.UnsupportedEncodingException;
+import java.text.DateFormat;
+import java.text.Format;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.TimeZone;
+
+public class LocalizedMessage
+{
+ protected static final int NO_FILTER = 0;
+ protected static final int FILTER = 1;
+ protected static final int FILTER_URL = 2;
+
+ protected String id;
+ protected String resource;
+
+ // ISO-8859-1 is the default encoding
+ public static final String DEFAULT_ENCODING = "ISO-8859-1";
+ protected String encoding = DEFAULT_ENCODING;
+
+ protected FilteredArguments arguments;
+ protected FilteredArguments extraArgs = null;
+
+ protected Filter filter = null;
+
+ protected ClassLoader loader = null;
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public LocalizedMessage(String resource,String id) throws NullPointerException
+ {
+ if (resource == null || id == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ arguments = new FilteredArguments();
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public LocalizedMessage(String resource,String id, String encoding) throws NullPointerException, UnsupportedEncodingException
+ {
+ if (resource == null || id == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ arguments = new FilteredArguments();
+ this.encoding = encoding;
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public LocalizedMessage(String resource, String id, Object[] arguments) throws NullPointerException
+ {
+ if (resource == null || id == null || arguments == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ this.arguments = new FilteredArguments(arguments);
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public LocalizedMessage(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
+ {
+ if (resource == null || id == null || arguments == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ this.arguments = new FilteredArguments(arguments);
+ this.encoding = encoding;
+ }
+
+ /**
+ * Reads the entry <code>id + "." + key</code> from the resource file and returns a
+ * formated message for the given Locale and TimeZone.
+ * @param key second part of the entry id
+ * @param loc the used {@link Locale}
+ * @param timezone the used {@link TimeZone}
+ * @return a Strng containing the localized message
+ * @throws MissingEntryException if the resource file is not available or the entry does not exist.
+ */
+ public String getEntry(String key,Locale loc, TimeZone timezone) throws MissingEntryException
+ {
+ String entry = id;
+ if (key != null)
+ {
+ entry += "." + key;
+ }
+
+ try
+ {
+ ResourceBundle bundle;
+ if (loader == null)
+ {
+ bundle = ResourceBundle.getBundle(resource,loc);
+ }
+ else
+ {
+ bundle = ResourceBundle.getBundle(resource, loc);
+ }
+ String result = bundle.getString(entry);
+ if (!encoding.equals(DEFAULT_ENCODING))
+ {
+ result = new String(result.getBytes(DEFAULT_ENCODING), encoding);
+ }
+ if (!arguments.isEmpty())
+ {
+ result = formatWithTimeZone(result,arguments.getFilteredArgs(loc),loc,timezone);
+ }
+ result = addExtraArgs(result, loc);
+ return result;
+ }
+ catch (MissingResourceException mre)
+ {
+ throw new MissingEntryException("Can't find entry " + entry + " in resource file " + resource + ".",
+ resource,
+ entry,
+ loc,
+ loader != null ? loader : this.getClassLoader());
+ }
+ catch (UnsupportedEncodingException use)
+ {
+ // should never occur - cause we already test this in the constructor
+ throw new RuntimeException(use.toString());
+ }
+ }
+
+ protected String formatWithTimeZone(
+ String template,
+ Object[] arguments,
+ Locale locale,
+ TimeZone timezone)
+ {
+ MessageFormat mf = new MessageFormat(" ");
+ mf.setLocale(locale);
+ mf.applyPattern(template);
+ if (!timezone.equals(TimeZone.getDefault()))
+ {
+ Format[] formats = mf.getFormats();
+ for (int i = 0; i < formats.length; i++)
+ {
+ if (formats[i] instanceof DateFormat)
+ {
+ DateFormat temp = (DateFormat) formats[i];
+ temp.setTimeZone(timezone);
+ mf.setFormat(i,temp);
+ }
+ }
+ }
+ return mf.format(arguments);
+ }
+
+ protected String addExtraArgs(String msg, Locale locale)
+ {
+ if (extraArgs != null)
+ {
+ StringBuffer sb = new StringBuffer(msg);
+ Object[] filteredArgs = extraArgs.getFilteredArgs(locale);
+ for (int i = 0; i < filteredArgs.length; i++)
+ {
+ sb.append(filteredArgs[i]);
+ }
+ msg = sb.toString();
+ }
+ return msg;
+ }
+
+ /**
+ * Sets the {@link Filter} that is used to filter the arguments of this message
+ * @param filter the {@link Filter} to use. <code>null</code> to disable filtering.
+ */
+ public void setFilter(Filter filter)
+ {
+ arguments.setFilter(filter);
+ if (extraArgs != null)
+ {
+ extraArgs.setFilter(filter);
+ }
+ this.filter = filter;
+ }
+
+ /**
+ * Returns the current filter.
+ * @return the current filter
+ */
+ public Filter getFilter()
+ {
+ return filter;
+ }
+
+ /**
+ * Set the {@link ClassLoader} which loads the resource files. If it is set to <code>null</code>
+ * then the default {@link ClassLoader} is used.
+ * @param loader the {@link ClassLoader} which loads the resource files
+ */
+ public void setClassLoader(ClassLoader loader)
+ {
+ this.loader = loader;
+ }
+
+ /**
+ * Returns the {@link ClassLoader} which loads the resource files or <code>null</code>
+ * if the default ClassLoader is used.
+ * @return the {@link ClassLoader} which loads the resource files
+ */
+ public ClassLoader getClassLoader()
+ {
+ return loader;
+ }
+
+ /**
+ * Returns the id of the message in the resource bundle.
+ * @return the id of the message
+ */
+ public String getId()
+ {
+ return id;
+ }
+
+ /**
+ * Returns the name of the resource bundle for this message
+ * @return name of the resource file
+ */
+ public String getResource()
+ {
+ return resource;
+ }
+
+ /**
+ * Returns an <code>Object[]</code> containing the message arguments.
+ * @return the message arguments
+ */
+ public Object[] getArguments()
+ {
+ return arguments.getArguments();
+ }
+
+ /**
+ *
+ * @param extraArg
+ */
+ public void setExtraArgument(Object extraArg)
+ {
+ setExtraArguments(new Object[] {extraArg});
+ }
+
+ /**
+ *
+ * @param extraArgs
+ */
+ public void setExtraArguments(Object[] extraArgs)
+ {
+ if (extraArgs != null)
+ {
+ this.extraArgs = new FilteredArguments(extraArgs);
+ this.extraArgs.setFilter(filter);
+ }
+ else
+ {
+ this.extraArgs = null;
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Object[] getExtraArgs()
+ {
+ return (extraArgs == null) ? null : extraArgs.getArguments();
+ }
+
+ protected class FilteredArguments
+ {
+
+ protected Filter filter = null;
+
+ protected boolean[] isLocaleSpecific;
+ protected int[] argFilterType;
+ protected Object[] arguments;
+ protected Object[] unpackedArgs;
+ protected Object[] filteredArgs;
+
+ FilteredArguments()
+ {
+ this(new Object[0]);
+ }
+
+ FilteredArguments(Object[] args)
+ {
+ this.arguments = args;
+ this.unpackedArgs = new Object[args.length];
+ this.filteredArgs = new Object[args.length];
+ this.isLocaleSpecific = new boolean[args.length];
+ this.argFilterType = new int[args.length];
+ for (int i = 0; i < args.length; i++)
+ {
+ if (args[i] instanceof TrustedInput)
+ {
+ this.unpackedArgs[i] = ((TrustedInput) args[i]).getInput();
+ argFilterType[i] = NO_FILTER;
+ }
+ else if (args[i] instanceof UntrustedInput)
+ {
+ this.unpackedArgs[i] = ((UntrustedInput) args[i]).getInput();
+ if (args[i] instanceof UntrustedUrlInput)
+ {
+ argFilterType[i] = FILTER_URL;
+ }
+ else
+ {
+ argFilterType[i] = FILTER;
+ }
+ }
+ else
+ {
+ this.unpackedArgs[i] = args[i];
+ argFilterType[i] = FILTER;
+ }
+
+ // locale specific
+ this.isLocaleSpecific[i] = (this.unpackedArgs[i] instanceof LocaleString);
+ }
+ }
+
+ public boolean isEmpty()
+ {
+ return unpackedArgs.length == 0;
+ }
+
+ public Object[] getArguments()
+ {
+ return arguments;
+ }
+
+ public Object[] getFilteredArgs(Locale locale)
+ {
+ Object[] result = new Object[unpackedArgs.length];
+ for (int i = 0; i < unpackedArgs.length; i++)
+ {
+ Object arg;
+ if (filteredArgs[i] != null)
+ {
+ arg = filteredArgs[i];
+ }
+ else
+ {
+ arg = unpackedArgs[i];
+ if (isLocaleSpecific[i])
+ {
+ // get locale
+ arg = ((LocaleString) arg).getLocaleString(locale);
+ arg = filter(argFilterType[i], arg);
+ }
+ else
+ {
+ arg = filter(argFilterType[i], arg);
+ filteredArgs[i] = arg;
+ }
+ }
+ result[i] = arg;
+ }
+ return result;
+ }
+
+ private Object filter(int type, Object obj)
+ {
+ if (filter != null)
+ {
+ Object o = (null == obj) ? "null" : obj;
+ switch (type)
+ {
+ case NO_FILTER:
+ return o;
+ case FILTER:
+ return filter.doFilter(o.toString());
+ case FILTER_URL:
+ return filter.doFilterUrl(o.toString());
+ default:
+ return null;
+ }
+ }
+ else
+ {
+ return obj;
+ }
+ }
+
+ public Filter getFilter()
+ {
+ return filter;
+ }
+
+ public void setFilter(Filter filter)
+ {
+ if (filter != this.filter)
+ {
+ for (int i = 0; i < unpackedArgs.length; i++)
+ {
+ filteredArgs[i] = null;
+ }
+ }
+ this.filter = filter;
+ }
+
+ }
+
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Resource: \"").append(resource);
+ sb.append("\" Id: \"").append(id).append("\"");
+ sb.append(" Arguments: ").append(arguments.getArguments().length).append(" normal, ")
+ .append(extraArgs.getArguments().length).append(" extra");
+ sb.append(" Encoding: ").append(encoding);
+ sb.append(" ClassLoader: ").append(loader);
+ return sb.toString();
+ }
+
+}
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/i18n/MissingEntryException.java b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/i18n/MissingEntryException.java
new file mode 100644
index 000000000..d876a91af
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/jdk1.1/org/spongycastle/i18n/MissingEntryException.java
@@ -0,0 +1,63 @@
+package org.spongycastle.i18n;
+
+import java.net.URL;
+import java.util.Locale;
+
+public class MissingEntryException extends RuntimeException
+{
+
+ protected final String resource;
+ protected final String key;
+ protected final ClassLoader loader;
+ protected final Locale locale;
+
+ private String debugMsg;
+
+ public MissingEntryException(String message, String resource, String key, Locale locale, ClassLoader loader)
+ {
+ super(message);
+ this.resource = resource;
+ this.key = key;
+ this.locale = locale;
+ this.loader = loader;
+ }
+
+ public MissingEntryException(String message, Throwable cause, String resource, String key, Locale locale, ClassLoader loader)
+ {
+ super(message + ": " + cause);
+ this.resource = resource;
+ this.key = key;
+ this.locale = locale;
+ this.loader = loader;
+ }
+
+ public String getKey()
+ {
+ return key;
+ }
+
+ public String getResource()
+ {
+ return resource;
+ }
+
+ public ClassLoader getClassLoader()
+ {
+ return loader;
+ }
+
+ public Locale getLocale()
+ {
+ return locale;
+ }
+
+ public String getDebugMsg()
+ {
+ if (debugMsg == null)
+ {
+ debugMsg = "Can not find entry " + key + " in resource file " + resource + " for the locale " + locale + ".";
+ }
+ return debugMsg;
+ }
+
+}