summaryrefslogtreecommitdiffstats
path: root/bcprov
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2013-12-11 16:35:05 -0800
committerKenny Root <kroot@google.com>2013-12-12 16:48:48 -0800
commit5db505e1f6a68c8d5dfdb0fed0b8607dea7bed96 (patch)
treeba9d9a42f9ed5478b4205c83c13a0e94b55a8c6c /bcprov
parentc0444a1be12b67cbad8b4858f0d65a0d75db15a9 (diff)
downloadandroid_external_bouncycastle-5db505e1f6a68c8d5dfdb0fed0b8607dea7bed96.tar.gz
android_external_bouncycastle-5db505e1f6a68c8d5dfdb0fed0b8607dea7bed96.tar.bz2
android_external_bouncycastle-5db505e1f6a68c8d5dfdb0fed0b8607dea7bed96.zip
Upgrade to Bouncycastle 1.50
SHA256 sums of source packages: 0be5bb948ec481b3d1f30ee80ef593b298b3782697f9eeee5c74cf270689b520 bcpkix-jdk15on-150.tar.gz 468259c9166fbcf87ad284ae46fae45408cb7cfc9c406862ea75d5b8696f4f2a bcprov-jdk15on-150.tar.gz Change-Id: Id566e9137f85d8328e9f0cb0472ff2f6ae7a71d3
Diffstat (limited to 'bcprov')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java25
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java61
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java60
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java36
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/Attributes.java36
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java35
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/GCMParameters.java102
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java81
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java113
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java46
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java119
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java50
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java70
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java26
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java46
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java22
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java156
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java238
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java84
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java38
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java51
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/Holder.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java106
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Name.java58
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java98
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java107
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java18
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java21
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java167
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/DerivationFunction.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/io/CipherInputStream.java244
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/io/CipherOutputStream.java188
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java142
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java88
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java487
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/DSAKCalculator.java41
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java42
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java61
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java26
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceUtils.java53
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/io/MacOutputStream.java38
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java56
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java90
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java39
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java57
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java54
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java65
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java164
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java155
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java172
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java27
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java32
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java60
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java35
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCRLUtil.java38
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java59
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/spec/ECParameterSpec.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/spec/ECPublicKeySpec.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java105
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java433
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java493
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java1596
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/FpNafMultiplier.java39
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java766
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java1995
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java101
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WNafMultiplier.java240
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java32
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java393
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/Arrays.java140
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java58
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/X509Store.java79
135 files changed, 9333 insertions, 2762 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java
index 7281a6a..98ab0d6 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java
@@ -11,9 +11,9 @@ public interface BERTags
public static final int EXTERNAL = 0x08;
public static final int ENUMERATED = 0x0a;
public static final int SEQUENCE = 0x10;
- public static final int SEQUENCE_OF = 0x10; // for completeness
+ public static final int SEQUENCE_OF = 0x10; // for completeness - used to model a SEQUENCE of the same type.
public static final int SET = 0x11;
- public static final int SET_OF = 0x11; // for completeness
+ public static final int SET_OF = 0x11; // for completeness - used to model a SET of the same type.
public static final int NUMERIC_STRING = 0x12;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java
index 74acda6..634f5a8 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java
@@ -177,7 +177,7 @@ public class DERBoolean
{
if (value.length != 1)
{
- throw new IllegalArgumentException("byte value should have 1 byte in it");
+ throw new IllegalArgumentException("BOOLEAN value should have 1 byte in it");
}
if (value[0] == 0)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java b/bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java
index 2f299ee..9b1ef55 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java
@@ -5,6 +5,9 @@ import java.math.BigInteger;
import org.bouncycastle.util.Arrays;
+/**
+ * Use ASN1Enumerated instead of this.
+ */
public class DEREnumerated
extends ASN1Primitive
{
@@ -52,7 +55,7 @@ public class DEREnumerated
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
*/
- public static DEREnumerated getInstance(
+ public static ASN1Enumerated getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
@@ -68,18 +71,27 @@ public class DEREnumerated
}
}
+ /**
+ * @deprecated use ASN1Enumerated
+ */
public DEREnumerated(
int value)
{
bytes = BigInteger.valueOf(value).toByteArray();
}
+ /**
+ * @deprecated use ASN1Enumerated
+ */
public DEREnumerated(
BigInteger value)
{
bytes = value.toByteArray();
}
+ /**
+ * @deprecated use ASN1Enumerated
+ */
public DEREnumerated(
byte[] bytes)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java
index 3804450..57cc84a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java
@@ -5,6 +5,9 @@ import java.math.BigInteger;
import org.bouncycastle.util.Arrays;
+/**
+ * Use ASN1Integer instead of this,
+ */
public class DERInteger
extends ASN1Primitive
{
@@ -67,18 +70,27 @@ public class DERInteger
}
}
+ /**
+ * @deprecated use ASN1Integer constructor
+ */
public DERInteger(
long value)
{
bytes = BigInteger.valueOf(value).toByteArray();
}
+ /**
+ * @deprecated use ASN1Integer constructor
+ */
public DERInteger(
BigInteger value)
{
bytes = value.toByteArray();
}
+ /**
+ * @deprecated use ASN1Integer constructor
+ */
public DERInteger(
byte[] bytes)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
index 13e1195..b82647e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
@@ -6,6 +6,9 @@ import java.math.BigInteger;
import org.bouncycastle.util.Arrays;
+/**
+ * Use ASN1ObjectIdentifier instead of this,
+ */
public class DERObjectIdentifier
extends ASN1Primitive
{
@@ -38,7 +41,22 @@ public class DERObjectIdentifier
if (obj instanceof byte[])
{
- return ASN1ObjectIdentifier.fromOctetString((byte[])obj);
+ byte[] enc = (byte[])obj;
+ if (enc[0] == BERTags.OBJECT_IDENTIFIER)
+ {
+ try
+ {
+ return (ASN1ObjectIdentifier)fromByteArray(enc);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct sequence from byte[]: " + e.getMessage());
+ }
+ }
+ else
+ { // TODO: this really shouldn't be supported here...
+ return ASN1ObjectIdentifier.fromOctetString((byte[])obj);
+ }
}
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
@@ -154,6 +172,9 @@ public class DERObjectIdentifier
this.body = Arrays.clone(bytes);
}
+ /**
+ * @deprecated use ASN1ObjectIdentifier constructor.
+ */
public DERObjectIdentifier(
String identifier)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java b/bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java
index bb8ec4e..b5cc59a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java
@@ -3,20 +3,23 @@ package org.bouncycastle.asn1;
import java.io.IOException;
import java.util.Enumeration;
+/**
+ * The DLSequence encodes a SEQUENCE using definite length form.
+ */
public class DLSequence
extends ASN1Sequence
{
private int bodyLength = -1;
/**
- * create an empty sequence
+ * Create an empty sequence
*/
public DLSequence()
{
}
/**
- * create a sequence containing one object
+ * Create a sequence containing one object
*/
public DLSequence(
ASN1Encodable obj)
@@ -25,7 +28,7 @@ public class DLSequence
}
/**
- * create a sequence containing a vector of objects.
+ * Create a sequence containing a vector of objects.
*/
public DLSequence(
ASN1EncodableVector v)
@@ -34,7 +37,7 @@ public class DLSequence
}
/**
- * create a sequence containing an array of objects.
+ * Create a sequence containing an array of objects.
*/
public DLSequence(
ASN1Encodable[] array)
@@ -51,7 +54,7 @@ public class DLSequence
for (Enumeration e = this.getObjects(); e.hasMoreElements();)
{
- Object obj = e.nextElement();
+ Object obj = e.nextElement();
length += ((ASN1Encodable)obj).toASN1Primitive().toDLObject().encodedLength();
}
@@ -65,12 +68,12 @@ public class DLSequence
int encodedLength()
throws IOException
{
- int length = getBodyLength();
+ int length = getBodyLength();
return 1 + StreamUtil.calculateBodyLength(length) + length;
}
- /*
+ /**
* A note on the implementation:
* <p>
* As DL requires the constructed, definite-length model to
@@ -82,17 +85,17 @@ public class DLSequence
ASN1OutputStream out)
throws IOException
{
- ASN1OutputStream dOut = out.getDLSubStream();
- int length = getBodyLength();
+ ASN1OutputStream dOut = out.getDLSubStream();
+ int length = getBodyLength();
out.write(BERTags.SEQUENCE | BERTags.CONSTRUCTED);
out.writeLength(length);
for (Enumeration e = this.getObjects(); e.hasMoreElements();)
{
- Object obj = e.nextElement();
+ Object obj = e.nextElement();
dOut.writeObject((ASN1Encodable)obj);
}
}
-}
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java b/bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java
index 755754b..91e83fa 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java
@@ -4,7 +4,52 @@ import java.io.IOException;
import java.util.Enumeration;
/**
- * A DER encoded set object
+ * The DLSet encodes ASN.1 SET value without element ordering,
+ * and always using definite length form.
+ * <hr>
+ * <h2>X.690</h2>
+ * <h3>8: Basic encoding rules</h3>
+ * <h4>8.11 Encoding of a set value </h4>
+ * <b>8.11.1</b> The encoding of a set value shall be constructed
+ * <p/>
+ * <b>8.11.2</b> The contents octets shall consist of the complete
+ * encoding of a data value from each of the types listed in the
+ * ASN.1 definition of the set type, in an order chosen by the sender,
+ * unless the type was referenced with the keyword
+ * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
+ * <p/>
+ * <b>8.11.3</b> The encoding of a data value may, but need not,
+ * be present for a type which was referenced with the keyword
+ * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
+ * <blockquote>
+ * NOTE &mdash; The order of data values in a set value is not significant,
+ * and places no constraints on the order during transfer
+ * </blockquote>
+ * <h3>9: Canonical encoding rules</h3>
+ * <h4>9.3 Set components</h4>
+ * The encodings of the component values of a set value shall
+ * appear in an order determined by their tags as specified
+ * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
+ * Additionally, for the purposes of determining the order in which
+ * components are encoded when one or more component is an untagged
+ * choice type, each untagged choice type is ordered as though it
+ * has a tag equal to that of the smallest tag in that choice type
+ * or any untagged choice types nested within.
+ * <h3>10: Distinguished encoding rules</h3>
+ * <h4>10.3 Set components</h4>
+ * The encodings of the component values of a set value shall appear
+ * in an order determined by their tags as specified
+ * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
+ * <blockquote>
+ * NOTE &mdash; Where a component of the set is an untagged choice type,
+ * the location of that component in the ordering will depend on
+ * the tag of the choice component being encoded.
+ * </blockquote>
+ * <h3>11: Restrictions on BER employed by both CER and DER</h3>
+ * <h4>11.5 Set and sequence components with default value </h4>
+ * The encoding of a set value or sequence value shall not include
+ * an encoding for any component value which is equal to
+ * its default value.
*/
public class DLSet
extends ASN1Set
@@ -54,7 +99,7 @@ public class DLSet
for (Enumeration e = this.getObjects(); e.hasMoreElements();)
{
- Object obj = e.nextElement();
+ Object obj = e.nextElement();
length += ((ASN1Encodable)obj).toASN1Primitive().toDLObject().encodedLength();
}
@@ -68,12 +113,12 @@ public class DLSet
int encodedLength()
throws IOException
{
- int length = getBodyLength();
+ int length = getBodyLength();
return 1 + StreamUtil.calculateBodyLength(length) + length;
}
- /*
+ /**
* A note on the implementation:
* <p>
* As DL requires the constructed, definite-length model to
@@ -85,17 +130,17 @@ public class DLSet
ASN1OutputStream out)
throws IOException
{
- ASN1OutputStream dOut = out.getDLSubStream();
- int length = getBodyLength();
+ ASN1OutputStream dOut = out.getDLSubStream();
+ int length = getBodyLength();
out.write(BERTags.SET | BERTags.CONSTRUCTED);
out.writeLength(length);
for (Enumeration e = this.getObjects(); e.hasMoreElements();)
{
- Object obj = e.nextElement();
+ Object obj = e.nextElement();
dOut.writeObject((ASN1Encodable)obj);
}
}
-}
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java
index 18fc66c..16a6768 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java
@@ -2,50 +2,70 @@ package org.bouncycastle.asn1.bc;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * iso.org.dod.internet.private.enterprise.legion-of-the-bouncy-castle
+ * <p>
+ * 1.3.6.1.4.1.22554
+ */
public interface BCObjectIdentifiers
{
/**
* iso.org.dod.internet.private.enterprise.legion-of-the-bouncy-castle
- *
+ *<p>
* 1.3.6.1.4.1.22554
*/
public static final ASN1ObjectIdentifier bc = new ASN1ObjectIdentifier("1.3.6.1.4.1.22554");
/**
* pbe(1) algorithms
+ * <p>
+ * 1.3.6.1.4.1.22554.1
*/
- public static final ASN1ObjectIdentifier bc_pbe = new ASN1ObjectIdentifier(bc.getId() + ".1");
+ public static final ASN1ObjectIdentifier bc_pbe = bc.branch("1");
/**
* SHA-1(1)
+ * <p>
+ * 1.3.6.1.4.1.22554.1.1
*/
- public static final ASN1ObjectIdentifier bc_pbe_sha1 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".1");
+ public static final ASN1ObjectIdentifier bc_pbe_sha1 = bc_pbe.branch("1");
- /**
- * SHA-2(2) . (SHA-256(1)|SHA-384(2)|SHA-512(3)|SHA-224(4))
- */
- public static final ASN1ObjectIdentifier bc_pbe_sha256 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".2.1");
- public static final ASN1ObjectIdentifier bc_pbe_sha384 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".2.2");
- public static final ASN1ObjectIdentifier bc_pbe_sha512 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".2.3");
- public static final ASN1ObjectIdentifier bc_pbe_sha224 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".2.4");
+ /** SHA-2.SHA-256; 1.3.6.1.4.1.22554.1.2.1 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha256 = bc_pbe.branch("2.1");
+ /** SHA-2.SHA-384; 1.3.6.1.4.1.22554.1.2.2 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha384 = bc_pbe.branch("2.2");
+ /** SHA-2.SHA-512; 1.3.6.1.4.1.22554.1.2.3 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha512 = bc_pbe.branch("2.3");
+ /** SHA-2.SHA-224; 1.3.6.1.4.1.22554.1.2.4 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha224 = bc_pbe.branch("2.4");
/**
* PKCS-5(1)|PKCS-12(2)
*/
- public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs5 = new ASN1ObjectIdentifier(bc_pbe_sha1.getId() + ".1");
- public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12 = new ASN1ObjectIdentifier(bc_pbe_sha1.getId() + ".2");
+ /** SHA-1.PKCS5; 1.3.6.1.4.1.22554.1.1.1 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs5 = bc_pbe_sha1.branch("1");
+ /** SHA-1.PKCS12; 1.3.6.1.4.1.22554.1.1.2 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12 = bc_pbe_sha1.branch("2");
- public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs5 = new ASN1ObjectIdentifier(bc_pbe_sha256.getId() + ".1");
- public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12 = new ASN1ObjectIdentifier(bc_pbe_sha256.getId() + ".2");
+ /** SHA-256.PKCS12; 1.3.6.1.4.1.22554.1.2.1.1 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs5 = bc_pbe_sha256.branch("1");
+ /** SHA-256.PKCS12; 1.3.6.1.4.1.22554.1.2.1.2 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12 = bc_pbe_sha256.branch("2");
/**
* AES(1) . (CBC-128(2)|CBC-192(22)|CBC-256(42))
*/
- public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes128_cbc = new ASN1ObjectIdentifier(bc_pbe_sha1_pkcs12.getId() + ".1.2");
- public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes192_cbc = new ASN1ObjectIdentifier(bc_pbe_sha1_pkcs12.getId() + ".1.22");
- public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes256_cbc = new ASN1ObjectIdentifier(bc_pbe_sha1_pkcs12.getId() + ".1.42");
+ /** 1.3.6.1.4.1.22554.1.1.2.1.2 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes128_cbc = bc_pbe_sha1_pkcs12.branch("1.2");
+ /** 1.3.6.1.4.1.22554.1.1.2.1.22 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes192_cbc = bc_pbe_sha1_pkcs12.branch("1.22");
+ /** 1.3.6.1.4.1.22554.1.1.2.1.42 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes256_cbc = bc_pbe_sha1_pkcs12.branch("1.42");
- public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes128_cbc = new ASN1ObjectIdentifier(bc_pbe_sha256_pkcs12.getId() + ".1.2");
- public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes192_cbc = new ASN1ObjectIdentifier(bc_pbe_sha256_pkcs12.getId() + ".1.22");
- public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes256_cbc = new ASN1ObjectIdentifier(bc_pbe_sha256_pkcs12.getId() + ".1.42");
+ /** 1.3.6.1.4.1.22554.1.1.2.2.2 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes128_cbc = bc_pbe_sha256_pkcs12.branch("1.2");
+ /** 1.3.6.1.4.1.22554.1.1.2.2.22 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes192_cbc = bc_pbe_sha256_pkcs12.branch("1.22");
+ /** 1.3.6.1.4.1.22554.1.1.2.2.42 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes256_cbc = bc_pbe_sha256_pkcs12.branch("1.42");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java
index b5a2f34..066cf69 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java
@@ -10,6 +10,27 @@ import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSequence;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#page-14">RFC 5652</a>:
+ * Attribute is a pair of OID (as type identifier) + set of values.
+ * <p>
+ * <pre>
+ * Attribute ::= SEQUENCE {
+ * attrType OBJECT IDENTIFIER,
+ * attrValues SET OF AttributeValue
+ * }
+ *
+ * AttributeValue ::= ANY
+ * </pre>
+ * <p>
+ * General rule on values is that same AttributeValue must not be included
+ * multiple times into the set. That is, if the value is a SET OF INTEGERs,
+ * then having same value repeated is wrong: (1, 1), but different values is OK: (1, 2).
+ * Normally the AttributeValue syntaxes are more complicated than that.
+ * <p>
+ * General rule of Attribute usage is that the {@link Attributes} containers
+ * must not have multiple Attribute:s with same attrType (OID) there.
+ */
public class Attribute
extends ASN1Object
{
@@ -17,7 +38,14 @@ public class Attribute
private ASN1Set attrValues;
/**
- * return an Attribute object from the given object.
+ * Return an Attribute object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link Attribute} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with Attribute structure inside
+ * </ul>
*
* @param o the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -81,12 +109,6 @@ public class Attribute
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * Attribute ::= SEQUENCE {
- * attrType OBJECT IDENTIFIER,
- * attrValues SET OF AttributeValue
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java
index f114623..02b6cc1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java
@@ -11,6 +11,9 @@ import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSet;
+/**
+ * This is helper tool to construct {@link Attributes} sets.
+ */
public class AttributeTable
{
private Hashtable attributes = new Hashtable();
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attributes.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attributes.java
index 614e224..e21c8a7 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attributes.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attributes.java
@@ -6,6 +6,21 @@ import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DLSet;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652">RFC 5652</a> defines
+ * 5 "SET OF Attribute" entities with 5 different names.
+ * This is common implementation for them all:
+ * <pre>
+ * SignedAttributes ::= SET SIZE (1..MAX) OF Attribute
+ * UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute
+ * UnprotectedAttributes ::= SET SIZE (1..MAX) OF Attribute
+ * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * Attributes ::=
+ * SET SIZE(1..MAX) OF Attribute
+ * </pre>
+ */
public class Attributes
extends ASN1Object
{
@@ -21,6 +36,19 @@ public class Attributes
attributes = new DLSet(v);
}
+ /**
+ * Return an Attribute set object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link Attributes} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Set#getInstance(java.lang.Object) ASN1Set} input formats with Attributes structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static Attributes getInstance(Object obj)
{
if (obj instanceof Attributes)
@@ -47,12 +75,8 @@ public class Attributes
return rv;
}
- /**
- * <pre>
- * Attributes ::=
- * SET SIZE(1..MAX) OF Attribute -- according to RFC 5652
- * </pre>
- * @return
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java
index 5e97324..d2fc7d1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java
@@ -3,11 +3,28 @@ package org.bouncycastle.asn1.cms;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652">RFC 5652</a> CMS attribute OID constants.
+ * <pre>
+ * contentType ::= 1.2.840.113549.1.9.3
+ * messageDigest ::= 1.2.840.113549.1.9.4
+ * signingTime ::= 1.2.840.113549.1.9.5
+ * counterSignature ::= 1.2.840.113549.1.9.6
+ *
+ * contentHint ::= 1.2.840.113549.1.9.16.2.4
+ * </pre>
+ */
+
public interface CMSAttributes
{
+ /** PKCS#9: 1.2.840.113549.1.9.3 */
public static final ASN1ObjectIdentifier contentType = PKCSObjectIdentifiers.pkcs_9_at_contentType;
+ /** PKCS#9: 1.2.840.113549.1.9.4 */
public static final ASN1ObjectIdentifier messageDigest = PKCSObjectIdentifiers.pkcs_9_at_messageDigest;
+ /** PKCS#9: 1.2.840.113549.1.9.5 */
public static final ASN1ObjectIdentifier signingTime = PKCSObjectIdentifiers.pkcs_9_at_signingTime;
+ /** PKCS#9: 1.2.840.113549.1.9.6 */
public static final ASN1ObjectIdentifier counterSignature = PKCSObjectIdentifiers.pkcs_9_at_counterSignature;
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.4 - See <a href="http://tools.ietf.org/html/rfc2634">RFC 2634</a> */
public static final ASN1ObjectIdentifier contentHint = PKCSObjectIdentifiers.id_aa_contentHint;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java
index 6294d97..b88bf6e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java
@@ -5,24 +5,39 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
public interface CMSObjectIdentifiers
{
+ /** PKCS#7: 1.2.840.113549.1.7.1 */
static final ASN1ObjectIdentifier data = PKCSObjectIdentifiers.data;
+ /** PKCS#7: 1.2.840.113549.1.7.2 */
static final ASN1ObjectIdentifier signedData = PKCSObjectIdentifiers.signedData;
+ /** PKCS#7: 1.2.840.113549.1.7.3 */
static final ASN1ObjectIdentifier envelopedData = PKCSObjectIdentifiers.envelopedData;
+ /** PKCS#7: 1.2.840.113549.1.7.4 */
static final ASN1ObjectIdentifier signedAndEnvelopedData = PKCSObjectIdentifiers.signedAndEnvelopedData;
+ /** PKCS#7: 1.2.840.113549.1.7.5 */
static final ASN1ObjectIdentifier digestedData = PKCSObjectIdentifiers.digestedData;
+ /** PKCS#7: 1.2.840.113549.1.7.6 */
static final ASN1ObjectIdentifier encryptedData = PKCSObjectIdentifiers.encryptedData;
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.2 -- smime ct authData */
static final ASN1ObjectIdentifier authenticatedData = PKCSObjectIdentifiers.id_ct_authData;
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.9 -- smime ct compressedData */
static final ASN1ObjectIdentifier compressedData = PKCSObjectIdentifiers.id_ct_compressedData;
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.23 -- smime ct authEnvelopedData */
static final ASN1ObjectIdentifier authEnvelopedData = PKCSObjectIdentifiers.id_ct_authEnvelopedData;
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.31 -- smime ct timestampedData*/
static final ASN1ObjectIdentifier timestampedData = PKCSObjectIdentifiers.id_ct_timestampedData;
/**
* The other Revocation Info arc
+ * <p>
+ * <pre>
* id-ri OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
- * dod(6) internet(1) security(5) mechanisms(5) pkix(7) ri(16) }
+ * dod(6) internet(1) security(5) mechanisms(5) pkix(7) ri(16) }
+ * </pre>
*/
static final ASN1ObjectIdentifier id_ri = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.16");
+ /** 1.3.6.1.5.5.7.16.2 */
static final ASN1ObjectIdentifier id_ri_ocsp_response = id_ri.branch("2");
+ /** 1.3.6.1.5.5.7.16.4 */
static final ASN1ObjectIdentifier id_ri_scvp = id_ri.branch("4");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java
index 688ac58..1592c75 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java
@@ -10,6 +10,22 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.BERSequence;
import org.bouncycastle.asn1.BERTaggedObject;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-3">RFC 5652</a> ContentInfo, and
+ * <a href="http://tools.ietf.org/html/rfc5652#section-5.2">RFC 5652</a> EncapsulatedContentInfo objects.
+ *
+ * <pre>
+ * ContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
+ * }
+ *
+ * EncapsulatedContentInfo ::= SEQUENCE {
+ * eContentType ContentType,
+ * eContent [0] EXPLICIT OCTET STRING OPTIONAL
+ * }
+ * </pre>
+ */
public class ContentInfo
extends ASN1Object
// BEGIN android-removed
@@ -19,6 +35,19 @@ public class ContentInfo
private ASN1ObjectIdentifier contentType;
private ASN1Encodable content;
+ /**
+ * Return an ContentInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link ContentInfo} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with ContentInfo structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static ContentInfo getInstance(
Object obj)
{
@@ -86,12 +115,6 @@ public class ContentInfo
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * ContentInfo ::= SEQUENCE {
- * contentType ContentType,
- * content
- * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/GCMParameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/GCMParameters.java
new file mode 100644
index 0000000..0f03c87
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/GCMParameters.java
@@ -0,0 +1,102 @@
+package org.bouncycastle.asn1.cms;
+
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1Object;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * <a href="http://tools.ietf.org/html/rfc5084">RFC 5084</a>: GCMParameters object.
+ * <p>
+ * <pre>
+ GCMParameters ::= SEQUENCE {
+ aes-nonce OCTET STRING, -- recommended size is 12 octets
+ aes-ICVlen AES-GCM-ICVlen DEFAULT 12 }
+ * </pre>
+ */
+public class GCMParameters
+ extends ASN1Object
+{
+ private byte[] nonce;
+ private int icvLen;
+
+ /**
+ * Return an GCMParameters object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link org.bouncycastle.asn1.cms.GCMParameters} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(Object) ASN1Sequence} input formats with GCMParameters structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static GCMParameters getInstance(
+ Object obj)
+ {
+ if (obj instanceof GCMParameters)
+ {
+ return (GCMParameters)obj;
+ }
+ else if (obj != null)
+ {
+ return new GCMParameters(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private GCMParameters(
+ ASN1Sequence seq)
+ {
+ this.nonce = ASN1OctetString.getInstance(seq.getObjectAt(0)).getOctets();
+
+ if (seq.size() == 2)
+ {
+ this.icvLen = ASN1Integer.getInstance(seq.getObjectAt(1)).getValue().intValue();
+ }
+ else
+ {
+ this.icvLen = 12;
+ }
+ }
+
+ public GCMParameters(
+ byte[] nonce,
+ int icvLen)
+ {
+ this.nonce = Arrays.clone(nonce);
+ this.icvLen = icvLen;
+ }
+
+ public byte[] getNonce()
+ {
+ return Arrays.clone(nonce);
+ }
+
+ public int getIcvLen()
+ {
+ return icvLen;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new DEROctetString(nonce));
+
+ if (icvLen != 12)
+ {
+ v.add(new ASN1Integer(icvLen));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java
index ad0dbb1..d46cbfb 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java
@@ -13,12 +13,37 @@ import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.asn1.x509.X509CertificateStructure;
import org.bouncycastle.asn1.x509.X509Name;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-10.2.4">RFC 5652</a>: IssuerAndSerialNumber object.
+ * <p>
+ * <pre>
+ * IssuerAndSerialNumber ::= SEQUENCE {
+ * issuer Name,
+ * serialNumber CertificateSerialNumber
+ * }
+ *
+ * CertificateSerialNumber ::= INTEGER -- See RFC 5280
+ * </pre>
+ */
public class IssuerAndSerialNumber
extends ASN1Object
{
private X500Name name;
private ASN1Integer serialNumber;
+ /**
+ * Return an IssuerAndSerialNumber object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link IssuerAndSerialNumber} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with IssuerAndSerialNumber structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static IssuerAndSerialNumber getInstance(
Object obj)
{
@@ -36,7 +61,6 @@ public class IssuerAndSerialNumber
/**
* @deprecated use getInstance() method.
- * @param seq
*/
public IssuerAndSerialNumber(
ASN1Sequence seq)
@@ -52,6 +76,9 @@ public class IssuerAndSerialNumber
this.serialNumber = certificate.getSerialNumber();
}
+ /**
+ * @deprecated use constructor taking Certificate
+ */
public IssuerAndSerialNumber(
X509CertificateStructure certificate)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java
index fd2718a..8c7fcc2 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java
@@ -16,7 +16,45 @@ import org.bouncycastle.asn1.BERTaggedObject;
import org.bouncycastle.asn1.DERTaggedObject;
/**
- * a signed data object.
+ * <a href="http://tools.ietf.org/html/rfc5652#section-5.1">RFC 5652</a>:
+ * <p>
+ * A signed data object containing multitude of {@link SignerInfo}s.
+ * <pre>
+ * SignedData ::= SEQUENCE {
+ * version CMSVersion,
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * encapContentInfo EncapsulatedContentInfo,
+ * certificates [0] IMPLICIT CertificateSet OPTIONAL,
+ * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ * signerInfos SignerInfos
+ * }
+ *
+ * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
+ *
+ * SignerInfos ::= SET OF SignerInfo
+ * </pre>
+ * <p>
+ * The version calculation uses following ruleset from RFC 3852 section 5.1:
+ * <pre>
+ * IF ((certificates is present) AND
+ * (any certificates with a type of other are present)) OR
+ * ((crls is present) AND
+ * (any crls with a type of other are present))
+ * THEN version MUST be 5
+ * ELSE
+ * IF (certificates is present) AND
+ * (any version 2 attribute certificates are present)
+ * THEN version MUST be 4
+ * ELSE
+ * IF ((certificates is present) AND
+ * (any version 1 attribute certificates are present)) OR
+ * (any SignerInfo structures are version 3) OR
+ * (encapContentInfo eContentType is other than id-data)
+ * THEN version MUST be 3
+ * ELSE version MUST be 1
+ * </pre>
+ * <p>
+ * @todo Check possible update for this to RFC 5652 level
*/
public class SignedData
extends ASN1Object
@@ -35,6 +73,19 @@ public class SignedData
private boolean certsBer;
private boolean crlsBer;
+ /**
+ * Return a SignedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link SignedData} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with SignedData structure inside
+ * </ul>
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static SignedData getInstance(
Object o)
{
@@ -68,24 +119,6 @@ public class SignedData
}
- // RFC3852, section 5.1:
- // IF ((certificates is present) AND
- // (any certificates with a type of other are present)) OR
- // ((crls is present) AND
- // (any crls with a type of other are present))
- // THEN version MUST be 5
- // ELSE
- // IF (certificates is present) AND
- // (any version 2 attribute certificates are present)
- // THEN version MUST be 4
- // ELSE
- // IF ((certificates is present) AND
- // (any version 1 attribute certificates are present)) OR
- // (any SignerInfo structures are version 3) OR
- // (encapContentInfo eContentType is other than id-data)
- // THEN version MUST be 3
- // ELSE version MUST be 1
- //
private ASN1Integer calculateVersion(
ASN1ObjectIdentifier contentOid,
ASN1Set certs,
@@ -257,16 +290,6 @@ public class SignedData
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * SignedData ::= SEQUENCE {
- * version CMSVersion,
- * digestAlgorithms DigestAlgorithmIdentifiers,
- * encapContentInfo EncapsulatedContentInfo,
- * certificates [0] IMPLICIT CertificateSet OPTIONAL,
- * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
- * signerInfos SignerInfos
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java
index 37b6b31..2543eb1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java
@@ -8,6 +8,21 @@ import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERTaggedObject;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-5.3">RFC 5652</a>:
+ * Identify who signed the containing {@link SignerInfo} object.
+ * <p>
+ * The certificates referred to by this are at containing {@link SignedData} structure.
+ * <p>
+ * <pre>
+ * SignerIdentifier ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier
+ * }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ * </pre>
+ */
public class SignerIdentifier
extends ASN1Object
implements ASN1Choice
@@ -33,7 +48,16 @@ public class SignerIdentifier
}
/**
- * return a SignerIdentifier object from the given object.
+ * Return a SignerIdentifier object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link SignerIdentifier} object
+ * <li> {@link IssuerAndSerialNumber} object
+ * <li> {@link org.bouncycastle.asn1.ASN1OctetString#getInstance(java.lang.Object) ASN1OctetString} input formats with SignerIdentifier structure inside
+ * <li> {@link org.bouncycastle.asn1.ASN1Primitive ASN1Primitive} for SignerIdentifier constructor.
+ * </ul>
*
* @param o the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -82,14 +106,6 @@ public class SignerIdentifier
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * SignerIdentifier ::= CHOICE {
- * issuerAndSerialNumber IssuerAndSerialNumber,
- * subjectKeyIdentifier [0] SubjectKeyIdentifier
- * }
- *
- * SubjectKeyIdentifier ::= OCTET STRING
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java
index 8aafd67..4209045 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java
@@ -15,6 +15,63 @@ import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-5.3">RFC 5652</a>:
+ * Signature container per Signer, see {@link SignerIdentifier}.
+ * <pre>
+ * PKCS#7:
+ *
+ * SignerInfo ::= SEQUENCE {
+ * version Version,
+ * sid SignerIdentifier,
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+ * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+ * encryptedDigest EncryptedDigest,
+ * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+ * }
+ *
+ * EncryptedDigest ::= OCTET STRING
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * -----------------------------------------
+ *
+ * RFC 5256:
+ *
+ * SignerInfo ::= SEQUENCE {
+ * version CMSVersion,
+ * sid SignerIdentifier,
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
+ * signatureAlgorithm SignatureAlgorithmIdentifier,
+ * signature SignatureValue,
+ * unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL
+ * }
+ *
+ * -- {@link SignerIdentifier} referenced certificates are at containing
+ * -- {@link SignedData} certificates element.
+ *
+ * SignerIdentifier ::= CHOICE {
+ * issuerAndSerialNumber {@link IssuerAndSerialNumber},
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier }
+ *
+ * -- See {@link Attributes} for generalized SET OF {@link Attribute}
+ *
+ * SignedAttributes ::= SET SIZE (1..MAX) OF Attribute
+ * UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * {@link Attribute} ::= SEQUENCE {
+ * attrType OBJECT IDENTIFIER,
+ * attrValues SET OF AttributeValue }
+ *
+ * AttributeValue ::= ANY
+ *
+ * SignatureValue ::= OCTET STRING
+ * </pre>
+ */
public class SignerInfo
extends ASN1Object
{
@@ -26,22 +83,44 @@ public class SignerInfo
private ASN1OctetString encryptedDigest;
private ASN1Set unauthenticatedAttributes;
+ /**
+ * Return a SignerInfo object from the given input
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link SignerInfo} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with SignerInfo structure inside
+ * </ul>
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static SignerInfo getInstance(
Object o)
throws IllegalArgumentException
{
- if (o == null || o instanceof SignerInfo)
+ if (o instanceof SignerInfo)
{
return (SignerInfo)o;
}
- else if (o instanceof ASN1Sequence)
+ else if (o != null)
{
- return new SignerInfo((ASN1Sequence)o);
+ return new SignerInfo(ASN1Sequence.getInstance(o));
}
- throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
+ return null;
}
+ /**
+ *
+ * @param sid
+ * @param digAlgorithm CMS knows as 'digestAlgorithm'
+ * @param authenticatedAttributes CMS knows as 'signedAttrs'
+ * @param digEncryptionAlgorithm CMS knows as 'signatureAlgorithm'
+ * @param encryptedDigest CMS knows as 'signature'
+ * @param unauthenticatedAttributes CMS knows as 'unsignedAttrs'
+ */
public SignerInfo(
SignerIdentifier sid,
AlgorithmIdentifier digAlgorithm,
@@ -67,6 +146,15 @@ public class SignerInfo
this.unauthenticatedAttributes = unauthenticatedAttributes;
}
+ /**
+ *
+ * @param sid
+ * @param digAlgorithm CMS knows as 'digestAlgorithm'
+ * @param authenticatedAttributes CMS knows as 'signedAttrs'
+ * @param digEncryptionAlgorithm CMS knows as 'signatureAlgorithm'
+ * @param encryptedDigest CMS knows as 'signature'
+ * @param unauthenticatedAttributes CMS knows as 'unsignedAttrs'
+ */
public SignerInfo(
SignerIdentifier sid,
AlgorithmIdentifier digAlgorithm,
@@ -167,23 +255,6 @@ public class SignerInfo
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * SignerInfo ::= SEQUENCE {
- * version Version,
- * SignerIdentifier sid,
- * digestAlgorithm DigestAlgorithmIdentifier,
- * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
- * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
- * encryptedDigest EncryptedDigest,
- * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
- * }
- *
- * EncryptedDigest ::= OCTET STRING
- *
- * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
- *
- * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java
index 2087248..977fce6 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java
@@ -12,6 +12,22 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERGeneralizedTime;
import org.bouncycastle.asn1.DERUTCTime;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-11.3">RFC 5652</a>:
+ * Dual-mode timestamp format producing either UTCTIme or GeneralizedTime.
+ * <p>
+ * <pre>
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ * </pre>
+ * <p>
+ * This has a constructor using java.util.Date for input which generates
+ * a {@link org.bouncycastle.asn1.DERUTCTime DERUTCTime} object if the
+ * supplied datetime is in range 1950-01-01-00:00:00 UTC until 2049-12-31-23:59:60 UTC.
+ * If the datetime value is outside that range, the generated object will be
+ * {@link org.bouncycastle.asn1.DERGeneralizedTime DERGeneralizedTime}.
+ */
public class Time
extends ASN1Object
implements ASN1Choice
@@ -25,6 +41,9 @@ public class Time
return getInstance(obj.getObject());
}
+ /**
+ * @deprecated use getInstance()
+ */
public Time(
ASN1Primitive time)
{
@@ -38,7 +57,7 @@ public class Time
}
/**
- * creates a time object from a given date - if the date is between 1950
+ * Create a time object from a given date - if the year is in between 1950
* and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
* is used.
*/
@@ -63,6 +82,20 @@ public class Time
}
}
+ /**
+ * Return a Time object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link Time} object
+ * <li> {@link org.bouncycastle.asn1.DERUTCTime DERUTCTime} object
+ * <li> {@link org.bouncycastle.asn1.DERGeneralizedTime DERGeneralizedTime} object
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static Time getInstance(
Object obj)
{
@@ -82,6 +115,9 @@ public class Time
throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
}
+ /**
+ * Get the date+tine as a String in full form century format.
+ */
public String getTime()
{
if (time instanceof DERUTCTime)
@@ -94,6 +130,9 @@ public class Time
}
}
+ /**
+ * Get java.util.Date version of date+time.
+ */
public Date getDate()
{
try
@@ -115,11 +154,6 @@ public class Time
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * Time ::= CHOICE {
- * utcTime UTCTime,
- * generalTime GeneralizedTime }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java
index bef8620..77416dc 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java
@@ -2,54 +2,109 @@ package org.bouncycastle.asn1.eac;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * German Federal Office for Information Security
+ * (Bundesamt für Sicherheit in der Informationstechnik)
+ * <a href="http://www.bsi.bund.de/">http://www.bsi.bund.de/</a>
+ * <p>
+ * <a href="https://www.bsi.bund.de/EN/Publications/TechnicalGuidelines/TR03110/BSITR03110.html">BSI TR-03110</a>
+ * Technical Guideline Advanced Security Mechanisms for Machine Readable Travel Documents
+ * <p>
+ * <a href="https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03110/TR-03110_v2.1_P3pdf.pdf?__blob=publicationFile">Technical Guideline TR-03110-3</a>
+ * Advanced Security Mechanisms for Machine Readable Travel Documents;
+ * Part 3: Common Specifications.
+ */
+
public interface EACObjectIdentifiers
{
- // bsi-de OBJECT IDENTIFIER ::= {
- // itu-t(0) identified-organization(4) etsi(0)
- // reserved(127) etsi-identified-organization(0) 7
- // }
+ /**
+ * <pre>
+ * bsi-de OBJECT IDENTIFIER ::= {
+ * itu-t(0) identified-organization(4) etsi(0)
+ * reserved(127) etsi-identified-organization(0) 7
+ * }
+ * </pre>
+ * OID: 0.4.0.127.0.7
+ */
static final ASN1ObjectIdentifier bsi_de = new ASN1ObjectIdentifier("0.4.0.127.0.7");
- // id-PK OBJECT IDENTIFIER ::= {
- // bsi-de protocols(2) smartcard(2) 1
- // }
- static final ASN1ObjectIdentifier id_PK = bsi_de.branch("2.2.1");
+ /**
+ * <pre>
+ * id-PK OBJECT IDENTIFIER ::= {
+ * bsi-de protocols(2) smartcard(2) 1
+ * }
+ * </pre>
+ * OID: 0.4.0.127.0.7.2.2.1
+ */
+ static final ASN1ObjectIdentifier id_PK = bsi_de.branch("2.2.1");
- static final ASN1ObjectIdentifier id_PK_DH = id_PK.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.1.1 */
+ static final ASN1ObjectIdentifier id_PK_DH = id_PK.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.1.2 */
static final ASN1ObjectIdentifier id_PK_ECDH = id_PK.branch("2");
- // id-CA OBJECT IDENTIFIER ::= {
- // bsi-de protocols(2) smartcard(2) 3
- // }
- static final ASN1ObjectIdentifier id_CA = bsi_de.branch("2.2.3");
- static final ASN1ObjectIdentifier id_CA_DH = id_CA.branch("1");
- static final ASN1ObjectIdentifier id_CA_DH_3DES_CBC_CBC = id_CA_DH.branch("1");
- static final ASN1ObjectIdentifier id_CA_ECDH = id_CA.branch("2");
+ /**
+ * <pre>
+ * id-CA OBJECT IDENTIFIER ::= {
+ * bsi-de protocols(2) smartcard(2) 3
+ * }
+ * </pre>
+ * OID: 0.4.0.127.0.7.2.2.3
+ */
+ static final ASN1ObjectIdentifier id_CA = bsi_de.branch("2.2.3");
+ /** OID: 0.4.0.127.0.7.2.2.3.1 */
+ static final ASN1ObjectIdentifier id_CA_DH = id_CA.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.3.1.1 */
+ static final ASN1ObjectIdentifier id_CA_DH_3DES_CBC_CBC = id_CA_DH.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.3.2 */
+ static final ASN1ObjectIdentifier id_CA_ECDH = id_CA.branch("2");
+ /** OID: 0.4.0.127.0.7.2.2.3.2.1 */
static final ASN1ObjectIdentifier id_CA_ECDH_3DES_CBC_CBC = id_CA_ECDH.branch("1");
- //
- // id-TA OBJECT IDENTIFIER ::= {
- // bsi-de protocols(2) smartcard(2) 2
- // }
+ /**
+ * <pre>
+ * id-TA OBJECT IDENTIFIER ::= {
+ * bsi-de protocols(2) smartcard(2) 2
+ * }
+ * </pre>
+ * OID: 0.4.0.127.0.7.2.2.2
+ */
static final ASN1ObjectIdentifier id_TA = bsi_de.branch("2.2.2");
- static final ASN1ObjectIdentifier id_TA_RSA = id_TA.branch("1");
- static final ASN1ObjectIdentifier id_TA_RSA_v1_5_SHA_1 = id_TA_RSA .branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.2.1 */
+ static final ASN1ObjectIdentifier id_TA_RSA = id_TA.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.2.1.1 */
+ static final ASN1ObjectIdentifier id_TA_RSA_v1_5_SHA_1 = id_TA_RSA.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.2.1.2 */
static final ASN1ObjectIdentifier id_TA_RSA_v1_5_SHA_256 = id_TA_RSA.branch("2");
- static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_1 = id_TA_RSA.branch("3");
- static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_256 = id_TA_RSA.branch("4");
+ /** OID: 0.4.0.127.0.7.2.2.2.1.3 */
+ static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_1 = id_TA_RSA.branch("3");
+ /** OID: 0.4.0.127.0.7.2.2.2.1.4 */
+ static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_256 = id_TA_RSA.branch("4");
+ /** OID: 0.4.0.127.0.7.2.2.2.1.5 */
static final ASN1ObjectIdentifier id_TA_RSA_v1_5_SHA_512 = id_TA_RSA.branch("5");
- static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_512 = id_TA_RSA.branch("6");
- static final ASN1ObjectIdentifier id_TA_ECDSA = id_TA.branch("2");
- static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_1 = id_TA_ECDSA.branch("1");
- static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_224 = id_TA_ECDSA.branch("2");
- static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_256 = id_TA_ECDSA.branch("3");
- static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_384 = id_TA_ECDSA.branch("4");
- static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_512 = id_TA_ECDSA.branch("5");
+ /** OID: 0.4.0.127.0.7.2.2.2.1.6 */
+ static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_512 = id_TA_RSA.branch("6");
+ /** OID: 0.4.0.127.0.7.2.2.2.2 */
+ static final ASN1ObjectIdentifier id_TA_ECDSA = id_TA.branch("2");
+ /** OID: 0.4.0.127.0.7.2.2.2.2.1 */
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_1 = id_TA_ECDSA.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.2.2.2 */
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_224 = id_TA_ECDSA.branch("2");
+ /** OID: 0.4.0.127.0.7.2.2.2.2.3 */
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_256 = id_TA_ECDSA.branch("3");
+ /** OID: 0.4.0.127.0.7.2.2.2.2.4 */
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_384 = id_TA_ECDSA.branch("4");
+ /** OID: 0.4.0.127.0.7.2.2.2.2.5 */
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_512 = id_TA_ECDSA.branch("5");
/**
+ * <pre>
* id-EAC-ePassport OBJECT IDENTIFIER ::= {
- * bsi-de applications(3) mrtd(1) roles(2) 1}
+ * bsi-de applications(3) mrtd(1) roles(2) 1
+ * }
+ * </pre>
+ * OID: 0.4.0.127.0.7.3.1.2.1
*/
static final ASN1ObjectIdentifier id_EAC_ePassport = bsi_de.branch("3.1.2.1");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java
index e9ab8d6..5bfdbab 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java
@@ -2,19 +2,59 @@ package org.bouncycastle.asn1.iana;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * IANA:
+ * { iso(1) identifier-organization(3) dod(6) internet(1) } == IETF defined things
+ */
public interface IANAObjectIdentifiers
{
+
+ /** { iso(1) identifier-organization(3) dod(6) internet(1) } == IETF defined things */
+ static final ASN1ObjectIdentifier internet = new ASN1ObjectIdentifier("1.3.6.1");
+ /** 1.3.6.1.1: Internet directory: X.500 */
+ static final ASN1ObjectIdentifier directory = internet.branch("1");
+ /** 1.3.6.1.2: Internet management */
+ static final ASN1ObjectIdentifier mgmt = internet.branch("2");
+ /** 1.3.6.1.3: */
+ static final ASN1ObjectIdentifier experimental = internet.branch("3");
+ /** 1.3.6.1.4: */
+ static final ASN1ObjectIdentifier _private = internet.branch("4");
+ /** 1.3.6.1.5: Security services */
+ static final ASN1ObjectIdentifier security = internet.branch("5");
+ /** 1.3.6.1.6: SNMPv2 -- never really used */
+ static final ASN1ObjectIdentifier SNMPv2 = internet.branch("6");
+ /** 1.3.6.1.7: mail -- never really used */
+ static final ASN1ObjectIdentifier mail = internet.branch("7");
+
+
// id-SHA1 OBJECT IDENTIFIER ::=
// {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1)}
//
- static final ASN1ObjectIdentifier isakmpOakley = new ASN1ObjectIdentifier("1.3.6.1.5.5.8.1");
- static final ASN1ObjectIdentifier hmacMD5 = new ASN1ObjectIdentifier(isakmpOakley + ".1");
- static final ASN1ObjectIdentifier hmacSHA1 = new ASN1ObjectIdentifier(isakmpOakley + ".2");
+ /** IANA security mechanisms; 1.3.6.1.5.5 */
+ static final ASN1ObjectIdentifier security_mechanisms = security.branch("5");
+ /** IANA security nametypes; 1.3.6.1.5.6 */
+ static final ASN1ObjectIdentifier security_nametypes = security.branch("6");
+
+ /** PKIX base OID: 1.3.6.1.5.6.6 */
+ static final ASN1ObjectIdentifier pkix = security_mechanisms.branch("6");
+
+
+ /** IPSEC base OID: 1.3.6.1.5.5.8 */
+ static final ASN1ObjectIdentifier ipsec = security_mechanisms.branch("8");
+ /** IPSEC ISAKMP-Oakley OID: 1.3.6.1.5.5.8.1 */
+ static final ASN1ObjectIdentifier isakmpOakley = ipsec.branch("1");
+
+ /** IPSEC ISAKMP-Oakley hmacMD5 OID: 1.3.6.1.5.5.8.1.1 */
+ static final ASN1ObjectIdentifier hmacMD5 = isakmpOakley.branch("1");
+ /** IPSEC ISAKMP-Oakley hmacSHA1 OID: 1.3.6.1.5.5.8.1.2 */
+ static final ASN1ObjectIdentifier hmacSHA1 = isakmpOakley.branch("2");
- static final ASN1ObjectIdentifier hmacTIGER = new ASN1ObjectIdentifier(isakmpOakley + ".3");
+ /** IPSEC ISAKMP-Oakley hmacTIGER OID: 1.3.6.1.5.5.8.1.3 */
+ static final ASN1ObjectIdentifier hmacTIGER = isakmpOakley.branch("3");
- static final ASN1ObjectIdentifier hmacRIPEMD160 = new ASN1ObjectIdentifier(isakmpOakley + ".4");
+ /** IPSEC ISAKMP-Oakley hmacRIPEMD160 OID: 1.3.6.1.5.5.8.1.4 */
+ static final ASN1ObjectIdentifier hmacRIPEMD160 = isakmpOakley.branch("4");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java
index bc2ac8d..6b75fde 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java
@@ -2,11 +2,16 @@ package org.bouncycastle.asn1.isismtt;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * ISISMT -- Industrial Signature Interoperability Specification
+ */
public interface ISISMTTObjectIdentifiers
{
+ /** 1.3.36.8 */
static final ASN1ObjectIdentifier id_isismtt = new ASN1ObjectIdentifier("1.3.36.8");
+ /** 1.3.36.8.1 */
static final ASN1ObjectIdentifier id_isismtt_cp = id_isismtt.branch("1");
/**
@@ -15,29 +20,37 @@ public interface ISISMTTObjectIdentifiers
* Parliament and of the Council of 13 December 1999 on a Community
* Framework for Electronic Signatures, which additionally conforms the
* special requirements of the SigG and has been issued by an accredited CA.
+ * <p>
+ * 1.3.36.8.1.1
*/
+
static final ASN1ObjectIdentifier id_isismtt_cp_accredited = id_isismtt_cp.branch("1");
+ /** 1.3.36.8.3 */
static final ASN1ObjectIdentifier id_isismtt_at = id_isismtt.branch("3");
/**
* Certificate extensionDate of certificate generation
- *
* <pre>
- * DateOfCertGenSyntax ::= GeneralizedTime
+ * DateOfCertGenSyntax ::= GeneralizedTime
* </pre>
+ * OID: 1.3.36.8.3.1
*/
static final ASN1ObjectIdentifier id_isismtt_at_dateOfCertGen = id_isismtt_at.branch("1");
/**
* Attribute to indicate that the certificate holder may sign in the name of
* a third person. May also be used as extension in a certificate.
+ * <p>
+ * OID: 1.3.36.8.3.2
*/
static final ASN1ObjectIdentifier id_isismtt_at_procuration = id_isismtt_at.branch("2");
/**
* Attribute to indicate admissions to certain professions. May be used as
* attribute in attribute certificate or as extension in a certificate
+ * <p>
+ * OID: 1.3.36.8.3.3
*/
static final ASN1ObjectIdentifier id_isismtt_at_admission = id_isismtt_at.branch("3");
@@ -47,33 +60,37 @@ public interface ISISMTTObjectIdentifiers
* MonetaryLimit since January 1, 2004. For the sake of backward
* compatibility with certificates already in use, SigG conforming
* components MUST support MonetaryLimit (as well as QcEuLimitValue).
+ * <p>
+ * OID: 1.3.36.8.3.4
*/
static final ASN1ObjectIdentifier id_isismtt_at_monetaryLimit = id_isismtt_at.branch("4");
/**
* A declaration of majority. May be used as attribute in attribute
* certificate or as extension in a certificate
+ * <p>
+ * OID: 1.3.36.8.3.5
*/
static final ASN1ObjectIdentifier id_isismtt_at_declarationOfMajority = id_isismtt_at.branch("5");
/**
- *
* Serial number of the smart card containing the corresponding private key
- *
* <pre>
- * ICCSNSyntax ::= OCTET STRING (SIZE(8..20))
+ * ICCSNSyntax ::= OCTET STRING (SIZE(8..20))
* </pre>
+ * <p>
+ * OID: 1.3.36.8.3.6
*/
static final ASN1ObjectIdentifier id_isismtt_at_iCCSN = id_isismtt_at.branch("6");
/**
- *
* Reference for a file of a smartcard that stores the public key of this
- * certificate and that is used as �security anchor�.
- *
+ * certificate and that is used as "security anchor".
* <pre>
- * PKReferenceSyntax ::= OCTET STRING (SIZE(20))
+ * PKReferenceSyntax ::= OCTET STRING (SIZE(20))
* </pre>
+ * <p>
+ * OID: 1.3.36.8.3.7
*/
static final ASN1ObjectIdentifier id_isismtt_at_PKReference = id_isismtt_at.branch("7");
@@ -81,28 +98,28 @@ public interface ISISMTTObjectIdentifiers
* Some other restriction regarding the usage of this certificate. May be
* used as attribute in attribute certificate or as extension in a
* certificate.
- *
* <pre>
- * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+ * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
* </pre>
+ * <p>
+ * OID: 1.3.36.8.3.8
*
* @see org.bouncycastle.asn1.isismtt.x509.Restriction
*/
static final ASN1ObjectIdentifier id_isismtt_at_restriction = id_isismtt_at.branch("8");
/**
- *
* (Single)Request extension: Clients may include this extension in a
* (single) Request to request the responder to send the certificate in the
* response message along with the status information. Besides the LDAP
* service, this extension provides another mechanism for the distribution
* of certificates, which MAY optionally be provided by certificate
* repositories.
- *
* <pre>
- * RetrieveIfAllowed ::= BOOLEAN
- *
+ * RetrieveIfAllowed ::= BOOLEAN
* </pre>
+ * <p>
+ * OID: 1.3.36.8.3.9
*/
static final ASN1ObjectIdentifier id_isismtt_at_retrieveIfAllowed = id_isismtt_at.branch("9");
@@ -110,6 +127,8 @@ public interface ISISMTTObjectIdentifiers
* SingleOCSPResponse extension: The certificate requested by the client by
* inserting the RetrieveIfAllowed extension in the request, will be
* returned in this extension.
+ * <p>
+ * OID: 1.3.36.8.3.10
*
* @see org.bouncycastle.asn1.isismtt.ocsp.RequestedCertificate
*/
@@ -117,6 +136,8 @@ public interface ISISMTTObjectIdentifiers
/**
* Base ObjectIdentifier for naming authorities
+ * <p>
+ * OID: 1.3.36.8.3.11
*/
static final ASN1ObjectIdentifier id_isismtt_at_namingAuthorities = id_isismtt_at.branch("11");
@@ -127,13 +148,17 @@ public interface ISISMTTObjectIdentifiers
* this extension in the responses.
*
* <pre>
- * CertInDirSince ::= GeneralizedTime
+ * CertInDirSince ::= GeneralizedTime
* </pre>
+ * <p>
+ * OID: 1.3.36.8.3.12
*/
static final ASN1ObjectIdentifier id_isismtt_at_certInDirSince = id_isismtt_at.branch("12");
/**
* Hash of a certificate in OCSP.
+ * <p>
+ * OID: 1.3.36.8.3.13
*
* @see org.bouncycastle.asn1.isismtt.ocsp.CertHash
*/
@@ -141,11 +166,13 @@ public interface ISISMTTObjectIdentifiers
/**
* <pre>
- * NameAtBirth ::= DirectoryString(SIZE(1..64)
+ * NameAtBirth ::= DirectoryString(SIZE(1..64)
* </pre>
*
* Used in
* {@link org.bouncycastle.asn1.x509.SubjectDirectoryAttributes SubjectDirectoryAttributes}
+ * <p>
+ * OID: 1.3.36.8.3.14
*/
static final ASN1ObjectIdentifier id_isismtt_at_nameAtBirth = id_isismtt_at.branch("14");
@@ -155,8 +182,10 @@ public interface ISISMTTObjectIdentifiers
* extension in a certificate.
*
* <pre>
- * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+ * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
* </pre>
+ * <p>
+ * OID: 1.3.36.8.3.15
*
* @see org.bouncycastle.asn1.isismtt.x509.AdditionalInformationSyntax
*/
@@ -171,10 +200,11 @@ public interface ISISMTTObjectIdentifiers
* PKC as base certificate) contains some attribute that restricts the
* usability of the PKC too. Attribute certificates with restricting content
* MUST always be included in the signed document.
- *
* <pre>
- * LiabilityLimitationFlagSyntax ::= BOOLEAN
+ * LiabilityLimitationFlagSyntax ::= BOOLEAN
* </pre>
+ * <p>
+ * OID: 0.2.262.1.10.12.0
*/
static final ASN1ObjectIdentifier id_isismtt_at_liabilityLimitationFlag = new ASN1ObjectIdentifier("0.2.262.1.10.12.0");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java
index 73e0c58..73575f1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java
@@ -2,8 +2,30 @@ package org.bouncycastle.asn1.kisa;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * Korea Information Security Agency (KISA)
+ * ({iso(1) member-body(2) kr(410) kisa(200004)})
+ * <p>
+ * See <a href="http://tools.ietf.org/html/rfc4010">RFC 4010</a>
+ * Use of the SEED Encryption Algorithm
+ * in Cryptographic Message Syntax (CMS),
+ * and <a href="http://tools.ietf.org/html/rfc4269">RFC 4269</a>
+ * The SEED Encryption Algorithm
+ */
public interface KISAObjectIdentifiers
{
- public static final ASN1ObjectIdentifier id_seedCBC = new ASN1ObjectIdentifier("1.2.410.200004.1.4");
- public static final ASN1ObjectIdentifier id_npki_app_cmsSeed_wrap = new ASN1ObjectIdentifier("1.2.410.200004.7.1.1.1");
+ /** RFC 4010, 4269: id-seedCBC; OID 1.2.410.200004.1.4 */
+ static final ASN1ObjectIdentifier id_seedCBC = new ASN1ObjectIdentifier("1.2.410.200004.1.4");
+
+ /** RFC 4269: id-seedMAC; OID 1.2.410.200004.1.7 */
+ static final ASN1ObjectIdentifier id_seedMAC = new ASN1ObjectIdentifier("1.2.410.200004.1.7");
+
+ /** RFC 4269: pbeWithSHA1AndSEED-CBC; OID 1.2.410.200004.1.15 */
+ static final ASN1ObjectIdentifier pbeWithSHA1AndSEED_CBC = new ASN1ObjectIdentifier("1.2.410.200004.1.15");
+
+ /** RFC 4010: id-npki-app-cmsSeed-wrap; OID 1.2.410.200004.7.1.1.1 */
+ static final ASN1ObjectIdentifier id_npki_app_cmsSeed_wrap = new ASN1ObjectIdentifier("1.2.410.200004.7.1.1.1");
+
+ /** RFC 4010: SeedEncryptionAlgorithmInCMS; OID 1.2.840.113549.1.9.16.0.24 */
+ static final ASN1ObjectIdentifier id_mod_cms_seed = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.0.24");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
index debf268..6aff988 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
@@ -8,40 +8,52 @@ public interface MiscObjectIdentifiers
// Netscape
// iso/itu(2) joint-assign(16) us(840) uscompany(1) netscape(113730) cert-extensions(1) }
//
+ /** Netscape cert extensions OID base: 2.16.840.1.113730.1 */
static final ASN1ObjectIdentifier netscape = new ASN1ObjectIdentifier("2.16.840.1.113730.1");
+ /** Netscape cert CertType OID: 2.16.840.1.113730.1.1 */
static final ASN1ObjectIdentifier netscapeCertType = netscape.branch("1");
+ /** Netscape cert BaseURL OID: 2.16.840.1.113730.1.2 */
static final ASN1ObjectIdentifier netscapeBaseURL = netscape.branch("2");
+ /** Netscape cert RevocationURL OID: 2.16.840.1.113730.1.3 */
static final ASN1ObjectIdentifier netscapeRevocationURL = netscape.branch("3");
+ /** Netscape cert CARevocationURL OID: 2.16.840.1.113730.1.4 */
static final ASN1ObjectIdentifier netscapeCARevocationURL = netscape.branch("4");
+ /** Netscape cert RenewalURL OID: 2.16.840.1.113730.1.7 */
static final ASN1ObjectIdentifier netscapeRenewalURL = netscape.branch("7");
+ /** Netscape cert CApolicyURL OID: 2.16.840.1.113730.1.8 */
static final ASN1ObjectIdentifier netscapeCApolicyURL = netscape.branch("8");
+ /** Netscape cert SSLServerName OID: 2.16.840.1.113730.1.12 */
static final ASN1ObjectIdentifier netscapeSSLServerName = netscape.branch("12");
+ /** Netscape cert CertComment OID: 2.16.840.1.113730.1.13 */
static final ASN1ObjectIdentifier netscapeCertComment = netscape.branch("13");
//
// Verisign
// iso/itu(2) joint-assign(16) us(840) uscompany(1) verisign(113733) cert-extensions(1) }
//
+ /** Verisign OID base: 2.16.840.1.113733.1 */
static final ASN1ObjectIdentifier verisign = new ASN1ObjectIdentifier("2.16.840.1.113733.1");
- //
- // CZAG - country, zip, age, and gender
- //
+ /** Verisign CZAG (Country,Zip,Age,Gender) Extension OID: 2.16.840.1.113733.1.6.3 */
static final ASN1ObjectIdentifier verisignCzagExtension = verisign.branch("6.3");
- // D&B D-U-N-S number
+ /** Verisign D&B D-U-N-S number Extension OID: 2.16.840.1.113733.1.6.15 */
static final ASN1ObjectIdentifier verisignDnbDunsNumber = verisign.branch("6.15");
//
// Novell
// iso/itu(2) country(16) us(840) organization(1) novell(113719)
//
+ /** Novell OID base: 2.16.840.1.113719 */
static final ASN1ObjectIdentifier novell = new ASN1ObjectIdentifier("2.16.840.1.113719");
+ /** Novell SecurityAttribs OID: 2.16.840.1.113719.1.9.4.1 */
static final ASN1ObjectIdentifier novellSecurityAttribs = novell.branch("1.9.4.1");
//
// Entrust
// iso(1) member-body(16) us(840) nortelnetworks(113533) entrust(7)
//
+ /** NortelNetworks Entrust OID base: 1.2.840.113533.7 */
static final ASN1ObjectIdentifier entrust = new ASN1ObjectIdentifier("1.2.840.113533.7");
+ /** NortelNetworks Entrust VersionExtension OID: 1.2.840.113533.7.65.0 */
static final ASN1ObjectIdentifier entrustVersionExtension = entrust.branch("65.0");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java
index afa93c4..e3613c6 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java
@@ -2,59 +2,95 @@ package org.bouncycastle.asn1.nist;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ *
+ * NIST:
+ * iso/itu(2) joint-assign(16) us(840) organization(1) gov(101) csor(3)
+ */
public interface NISTObjectIdentifiers
{
//
- // NIST
- // iso/itu(2) joint-assign(16) us(840) organization(1) gov(101) csor(3)
-
- //
// nistalgorithms(4)
//
+ /** 2.16.840.1.101.3.4 -- algorithms */
static final ASN1ObjectIdentifier nistAlgorithm = new ASN1ObjectIdentifier("2.16.840.1.101.3.4");
+ /** 2.16.840.1.101.3.4.2 */
static final ASN1ObjectIdentifier hashAlgs = nistAlgorithm.branch("2");
+ /** 2.16.840.1.101.3.4.2.1 */
static final ASN1ObjectIdentifier id_sha256 = hashAlgs.branch("1");
+ /** 2.16.840.1.101.3.4.2.2 */
static final ASN1ObjectIdentifier id_sha384 = hashAlgs.branch("2");
+ /** 2.16.840.1.101.3.4.2.3 */
static final ASN1ObjectIdentifier id_sha512 = hashAlgs.branch("3");
+ /** 2.16.840.1.101.3.4.2.4 */
static final ASN1ObjectIdentifier id_sha224 = hashAlgs.branch("4");
+ /** 2.16.840.1.101.3.4.2.5 */
static final ASN1ObjectIdentifier id_sha512_224 = hashAlgs.branch("5");
+ /** 2.16.840.1.101.3.4.2.6 */
static final ASN1ObjectIdentifier id_sha512_256 = hashAlgs.branch("6");
- static final ASN1ObjectIdentifier aes = nistAlgorithm.branch("1");
+ /** 2.16.840.1.101.3.4.1 */
+ static final ASN1ObjectIdentifier aes = nistAlgorithm.branch("1");
+ /** 2.16.840.1.101.3.4.1.1 */
static final ASN1ObjectIdentifier id_aes128_ECB = aes.branch("1");
+ /** 2.16.840.1.101.3.4.1.2 */
static final ASN1ObjectIdentifier id_aes128_CBC = aes.branch("2");
+ /** 2.16.840.1.101.3.4.1.3 */
static final ASN1ObjectIdentifier id_aes128_OFB = aes.branch("3");
+ /** 2.16.840.1.101.3.4.1.4 */
static final ASN1ObjectIdentifier id_aes128_CFB = aes.branch("4");
+ /** 2.16.840.1.101.3.4.1.5 */
static final ASN1ObjectIdentifier id_aes128_wrap = aes.branch("5");
+ /** 2.16.840.1.101.3.4.1.6 */
static final ASN1ObjectIdentifier id_aes128_GCM = aes.branch("6");
+ /** 2.16.840.1.101.3.4.1.7 */
static final ASN1ObjectIdentifier id_aes128_CCM = aes.branch("7");
+ /** 2.16.840.1.101.3.4.1.21 */
static final ASN1ObjectIdentifier id_aes192_ECB = aes.branch("21");
+ /** 2.16.840.1.101.3.4.1.22 */
static final ASN1ObjectIdentifier id_aes192_CBC = aes.branch("22");
+ /** 2.16.840.1.101.3.4.1.23 */
static final ASN1ObjectIdentifier id_aes192_OFB = aes.branch("23");
+ /** 2.16.840.1.101.3.4.1.24 */
static final ASN1ObjectIdentifier id_aes192_CFB = aes.branch("24");
+ /** 2.16.840.1.101.3.4.1.25 */
static final ASN1ObjectIdentifier id_aes192_wrap = aes.branch("25");
+ /** 2.16.840.1.101.3.4.1.26 */
static final ASN1ObjectIdentifier id_aes192_GCM = aes.branch("26");
+ /** 2.16.840.1.101.3.4.1.27 */
static final ASN1ObjectIdentifier id_aes192_CCM = aes.branch("27");
+ /** 2.16.840.1.101.3.4.1.41 */
static final ASN1ObjectIdentifier id_aes256_ECB = aes.branch("41");
+ /** 2.16.840.1.101.3.4.1.42 */
static final ASN1ObjectIdentifier id_aes256_CBC = aes.branch("42");
+ /** 2.16.840.1.101.3.4.1.43 */
static final ASN1ObjectIdentifier id_aes256_OFB = aes.branch("43");
+ /** 2.16.840.1.101.3.4.1.44 */
static final ASN1ObjectIdentifier id_aes256_CFB = aes.branch("44");
+ /** 2.16.840.1.101.3.4.1.45 */
static final ASN1ObjectIdentifier id_aes256_wrap = aes.branch("45");
+ /** 2.16.840.1.101.3.4.1.46 */
static final ASN1ObjectIdentifier id_aes256_GCM = aes.branch("46");
+ /** 2.16.840.1.101.3.4.1.47 */
static final ASN1ObjectIdentifier id_aes256_CCM = aes.branch("47");
//
// signatures
//
+ /** 2.16.840.1.101.3.4.3 */
static final ASN1ObjectIdentifier id_dsa_with_sha2 = nistAlgorithm.branch("3");
+ /** 2.16.840.1.101.3.4.3.1 */
static final ASN1ObjectIdentifier dsa_with_sha224 = id_dsa_with_sha2.branch("1");
+ /** 2.16.840.1.101.3.4.3.2 */
static final ASN1ObjectIdentifier dsa_with_sha256 = id_dsa_with_sha2.branch("2");
+ /** 2.16.840.1.101.3.4.3.3 */
static final ASN1ObjectIdentifier dsa_with_sha384 = id_dsa_with_sha2.branch("3");
+ /** 2.16.840.1.101.3.4.3.4 */
static final ASN1ObjectIdentifier dsa_with_sha512 = id_dsa_with_sha2.branch("4");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java
index 2e4132a..fa32068 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java
@@ -3,15 +3,23 @@ package org.bouncycastle.asn1.ntt;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
/**
- * From RFC 3657
+ * From <a href="http://tools.ietf.org/html/rfc3657">RFC 3657</a>
+ * Use of the Camellia Encryption Algorithm
+ * in Cryptographic Message Syntax (CMS)
*/
public interface NTTObjectIdentifiers
{
- public static final ASN1ObjectIdentifier id_camellia128_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.2");
- public static final ASN1ObjectIdentifier id_camellia192_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.3");
- public static final ASN1ObjectIdentifier id_camellia256_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.4");
+ /** id-camellia128-cbc; OID 1.2.392.200011.61.1.1.1.2 */
+ static final ASN1ObjectIdentifier id_camellia128_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.2");
+ /** id-camellia192-cbc; OID 1.2.392.200011.61.1.1.1.3 */
+ static final ASN1ObjectIdentifier id_camellia192_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.3");
+ /** id-camellia256-cbc; OID 1.2.392.200011.61.1.1.1.4 */
+ static final ASN1ObjectIdentifier id_camellia256_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.4");
- public static final ASN1ObjectIdentifier id_camellia128_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.2");
- public static final ASN1ObjectIdentifier id_camellia192_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.3");
- public static final ASN1ObjectIdentifier id_camellia256_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.4");
+ /** id-camellia128-wrap; OID 1.2.392.200011.61.1.1.3.2 */
+ static final ASN1ObjectIdentifier id_camellia128_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.2");
+ /** id-camellia192-wrap; OID 1.2.392.200011.61.1.1.3.3 */
+ static final ASN1ObjectIdentifier id_camellia192_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.3");
+ /** id-camellia256-wrap; OID 1.2.392.200011.61.1.1.3.4 */
+ static final ASN1ObjectIdentifier id_camellia256_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.4");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java
index c8ce26b..c169c16 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java
@@ -2,30 +2,49 @@ package org.bouncycastle.asn1.oiw;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * OIW organization's OIDs:
+ * <p>
+ * id-SHA1 OBJECT IDENTIFIER ::=
+ * {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 }
+ */
public interface OIWObjectIdentifiers
{
- // id-SHA1 OBJECT IDENTIFIER ::=
- // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } //
+ /** OID: 1.3.14.3.2.2 */
static final ASN1ObjectIdentifier md4WithRSA = new ASN1ObjectIdentifier("1.3.14.3.2.2");
+ /** OID: 1.3.14.3.2.3 */
static final ASN1ObjectIdentifier md5WithRSA = new ASN1ObjectIdentifier("1.3.14.3.2.3");
+ /** OID: 1.3.14.3.2.4 */
static final ASN1ObjectIdentifier md4WithRSAEncryption = new ASN1ObjectIdentifier("1.3.14.3.2.4");
+ /** OID: 1.3.14.3.2.6 */
static final ASN1ObjectIdentifier desECB = new ASN1ObjectIdentifier("1.3.14.3.2.6");
+ /** OID: 1.3.14.3.2.7 */
static final ASN1ObjectIdentifier desCBC = new ASN1ObjectIdentifier("1.3.14.3.2.7");
+ /** OID: 1.3.14.3.2.8 */
static final ASN1ObjectIdentifier desOFB = new ASN1ObjectIdentifier("1.3.14.3.2.8");
+ /** OID: 1.3.14.3.2.9 */
static final ASN1ObjectIdentifier desCFB = new ASN1ObjectIdentifier("1.3.14.3.2.9");
+ /** OID: 1.3.14.3.2.17 */
static final ASN1ObjectIdentifier desEDE = new ASN1ObjectIdentifier("1.3.14.3.2.17");
+ /** OID: 1.3.14.3.2.26 */
static final ASN1ObjectIdentifier idSHA1 = new ASN1ObjectIdentifier("1.3.14.3.2.26");
+ /** OID: 1.3.14.3.2.27 */
static final ASN1ObjectIdentifier dsaWithSHA1 = new ASN1ObjectIdentifier("1.3.14.3.2.27");
+ /** OID: 1.3.14.3.2.29 */
static final ASN1ObjectIdentifier sha1WithRSA = new ASN1ObjectIdentifier("1.3.14.3.2.29");
- // ElGamal Algorithm OBJECT IDENTIFIER ::=
- // {iso(1) identified-organization(3) oiw(14) dirservsig(7) algorithm(2) encryption(1) 1 }
- //
+ /**
+ * <pre>
+ * ElGamal Algorithm OBJECT IDENTIFIER ::=
+ * {iso(1) identified-organization(3) oiw(14) dirservsig(7) algorithm(2) encryption(1) 1 }
+ * </pre>
+ * OID: 1.3.14.7.2.1.1
+ */
static final ASN1ObjectIdentifier elGamalAlgorithm = new ASN1ObjectIdentifier("1.3.14.7.2.1.1");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
index 65c0fa8..92c4e8f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
@@ -9,16 +9,39 @@ import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
-
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * <pre>
+ * PBKDF2-params ::= SEQUENCE {
+ * salt CHOICE {
+ * specified OCTET STRING,
+ * otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
+ * },
+ * iterationCount INTEGER (1..MAX),
+ * keyLength INTEGER (1..MAX) OPTIONAL,
+ * prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
+ * </pre>
+ */
public class PBKDF2Params
extends ASN1Object
{
+ private static final AlgorithmIdentifier algid_hmacWithSHA1 = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA1, DERNull.INSTANCE);
+
private ASN1OctetString octStr;
private ASN1Integer iterationCount;
private ASN1Integer keyLength;
-
+ private AlgorithmIdentifier prf;
+
+ /**
+ * Create PBKDF2Params from the passed in object,
+ *
+ * @param obj either PBKDF2Params or an ASN2Sequence.
+ * @return a PBKDF2Params instance.
+ */
public static PBKDF2Params getInstance(
Object obj)
{
@@ -34,7 +57,13 @@ public class PBKDF2Params
return null;
}
-
+
+ /**
+ * Create a PBKDF2Params with the specified salt, iteration count, and algid-hmacWithSHA1 for the prf.
+ *
+ * @param salt input salt.
+ * @param iterationCount input iteration count.
+ */
public PBKDF2Params(
byte[] salt,
int iterationCount)
@@ -43,6 +72,13 @@ public class PBKDF2Params
this.iterationCount = new ASN1Integer(iterationCount);
}
+ /**
+ * Create a PBKDF2Params with the specified salt, iteration count, keyLength, and algid-hmacWithSHA1 for the prf.
+ *
+ * @param salt input salt.
+ * @param iterationCount input iteration count.
+ * @param keyLength intended key length to be produced.
+ */
public PBKDF2Params(
byte[] salt,
int iterationCount,
@@ -53,6 +89,42 @@ public class PBKDF2Params
this.keyLength = new ASN1Integer(keyLength);
}
+ /**
+ * Create a PBKDF2Params with the specified salt, iteration count, keyLength, and a defined prf.
+ *
+ * @param salt input salt.
+ * @param iterationCount input iteration count.
+ * @param keyLength intended key length to be produced.
+ * @param prf the pseudo-random function to use.
+ */
+ public PBKDF2Params(
+ byte[] salt,
+ int iterationCount,
+ int keyLength,
+ AlgorithmIdentifier prf)
+ {
+ this(salt, iterationCount);
+
+ this.keyLength = new ASN1Integer(keyLength);
+ this.prf = prf;
+ }
+
+ /**
+ * Create a PBKDF2Params with the specified salt, iteration count, and a defined prf.
+ *
+ * @param salt input salt.
+ * @param iterationCount input iteration count.
+ * @param prf the pseudo-random function to use.
+ */
+ public PBKDF2Params(
+ byte[] salt,
+ int iterationCount,
+ AlgorithmIdentifier prf)
+ {
+ this(salt, iterationCount);
+ this.prf = prf;
+ }
+
private PBKDF2Params(
ASN1Sequence seq)
{
@@ -63,24 +135,57 @@ public class PBKDF2Params
if (e.hasMoreElements())
{
- keyLength = (ASN1Integer)e.nextElement();
- }
- else
- {
- keyLength = null;
+ Object o = e.nextElement();
+
+ if (o instanceof ASN1Integer)
+ {
+ keyLength = ASN1Integer.getInstance(o);
+ if (e.hasMoreElements())
+ {
+ o = e.nextElement();
+ }
+ else
+ {
+ o = null;
+ }
+ }
+ else
+ {
+ keyLength = null;
+ }
+
+ if (o != null)
+ {
+ prf = AlgorithmIdentifier.getInstance(o);
+ }
}
}
+ /**
+ * Return the salt to use.
+ *
+ * @return the input salt.
+ */
public byte[] getSalt()
{
return octStr.getOctets();
}
+ /**
+ * Return the iteration count to use.
+ *
+ * @return the input iteration count.
+ */
public BigInteger getIterationCount()
{
return iterationCount.getValue();
}
+ /**
+ * Return the intended length in octets of the derived key.
+ *
+ * @return length in octets for derived key, if specified.
+ */
public BigInteger getKeyLength()
{
if (keyLength != null)
@@ -91,6 +196,36 @@ public class PBKDF2Params
return null;
}
+ /**
+ * Return true if the PRF is the default (hmacWithSHA1)
+ *
+ * @return true if PRF is default, false otherwise.
+ */
+ public boolean isDefaultPrf()
+ {
+ return prf == null || prf.equals(algid_hmacWithSHA1);
+ }
+
+ /**
+ * Return the algId of the underlying pseudo random function to use.
+ *
+ * @return the prf algorithm identifier.
+ */
+ public AlgorithmIdentifier getPrf()
+ {
+ if (prf != null)
+ {
+ return prf;
+ }
+
+ return algid_hmacWithSHA1;
+ }
+
+ /**
+ * Return an ASN.1 structure suitable for encoding.
+ *
+ * @return the object as an ASN.1 encodable structure.
+ */
public ASN1Primitive toASN1Primitive()
{
ASN1EncodableVector v = new ASN1EncodableVector();
@@ -103,6 +238,11 @@ public class PBKDF2Params
v.add(keyLength);
}
+ if (prf != null && !prf.equals(algid_hmacWithSHA1))
+ {
+ v.add(prf);
+ }
+
return new DERSequence(v);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
index 37f94fe..82f1f94 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
@@ -2,73 +2,104 @@ package org.bouncycastle.asn1.pkcs;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * pkcs-1 OBJECT IDENTIFIER ::=<p>
+ * { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
+ *
+ */
public interface PKCSObjectIdentifiers
{
- //
- // pkcs-1 OBJECT IDENTIFIER ::= {
- // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
- //
+ /** PKCS#1: 1.2.840.113549.1.1 */
static final ASN1ObjectIdentifier pkcs_1 = new ASN1ObjectIdentifier("1.2.840.113549.1.1");
+ /** PKCS#1: 1.2.840.113549.1.1.1 */
static final ASN1ObjectIdentifier rsaEncryption = pkcs_1.branch("1");
// BEGIN android-removed
+ // /** PKCS#1: 1.2.840.113549.1.1.2 */
// static final ASN1ObjectIdentifier md2WithRSAEncryption = pkcs_1.branch("2");
+ // /** PKCS#1: 1.2.840.113549.1.1.3 */
// static final ASN1ObjectIdentifier md4WithRSAEncryption = pkcs_1.branch("3");
// END android-removed
+ /** PKCS#1: 1.2.840.113549.1.1.4 */
static final ASN1ObjectIdentifier md5WithRSAEncryption = pkcs_1.branch("4");
+ /** PKCS#1: 1.2.840.113549.1.1.5 */
static final ASN1ObjectIdentifier sha1WithRSAEncryption = pkcs_1.branch("5");
+ /** PKCS#1: 1.2.840.113549.1.1.6 */
static final ASN1ObjectIdentifier srsaOAEPEncryptionSET = pkcs_1.branch("6");
+ /** PKCS#1: 1.2.840.113549.1.1.7 */
static final ASN1ObjectIdentifier id_RSAES_OAEP = pkcs_1.branch("7");
+ /** PKCS#1: 1.2.840.113549.1.1.8 */
static final ASN1ObjectIdentifier id_mgf1 = pkcs_1.branch("8");
+ /** PKCS#1: 1.2.840.113549.1.1.9 */
static final ASN1ObjectIdentifier id_pSpecified = pkcs_1.branch("9");
+ /** PKCS#1: 1.2.840.113549.1.1.10 */
static final ASN1ObjectIdentifier id_RSASSA_PSS = pkcs_1.branch("10");
+ /** PKCS#1: 1.2.840.113549.1.1.11 */
static final ASN1ObjectIdentifier sha256WithRSAEncryption = pkcs_1.branch("11");
+ /** PKCS#1: 1.2.840.113549.1.1.12 */
static final ASN1ObjectIdentifier sha384WithRSAEncryption = pkcs_1.branch("12");
+ /** PKCS#1: 1.2.840.113549.1.1.13 */
static final ASN1ObjectIdentifier sha512WithRSAEncryption = pkcs_1.branch("13");
+ /** PKCS#1: 1.2.840.113549.1.1.14 */
static final ASN1ObjectIdentifier sha224WithRSAEncryption = pkcs_1.branch("14");
//
// pkcs-3 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 }
//
+ /** PKCS#3: 1.2.840.113549.1.3 */
static final ASN1ObjectIdentifier pkcs_3 = new ASN1ObjectIdentifier("1.2.840.113549.1.3");
+ /** PKCS#3: 1.2.840.113549.1.3.1 */
static final ASN1ObjectIdentifier dhKeyAgreement = pkcs_3.branch("1");
//
// pkcs-5 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 }
//
+ /** PKCS#5: 1.2.840.113549.1.5 */
static final ASN1ObjectIdentifier pkcs_5 = new ASN1ObjectIdentifier("1.2.840.113549.1.5");
+ /** PKCS#5: 1.2.840.113549.1.5.1 */
static final ASN1ObjectIdentifier pbeWithMD2AndDES_CBC = pkcs_5.branch("1");
+ /** PKCS#5: 1.2.840.113549.1.5.4 */
static final ASN1ObjectIdentifier pbeWithMD2AndRC2_CBC = pkcs_5.branch("4");
+ /** PKCS#5: 1.2.840.113549.1.5.3 */
static final ASN1ObjectIdentifier pbeWithMD5AndDES_CBC = pkcs_5.branch("3");
+ /** PKCS#5: 1.2.840.113549.1.5.6 */
static final ASN1ObjectIdentifier pbeWithMD5AndRC2_CBC = pkcs_5.branch("6");
+ /** PKCS#5: 1.2.840.113549.1.5.10 */
static final ASN1ObjectIdentifier pbeWithSHA1AndDES_CBC = pkcs_5.branch("10");
+ /** PKCS#5: 1.2.840.113549.1.5.11 */
static final ASN1ObjectIdentifier pbeWithSHA1AndRC2_CBC = pkcs_5.branch("11");
-
+ /** PKCS#5: 1.2.840.113549.1.5.13 */
static final ASN1ObjectIdentifier id_PBES2 = pkcs_5.branch("13");
-
+ /** PKCS#5: 1.2.840.113549.1.5.12 */
static final ASN1ObjectIdentifier id_PBKDF2 = pkcs_5.branch("12");
//
// encryptionAlgorithm OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) 3 }
//
+ /** 1.2.840.113549.3 */
static final ASN1ObjectIdentifier encryptionAlgorithm = new ASN1ObjectIdentifier("1.2.840.113549.3");
+ /** 1.2.840.113549.3.7 */
static final ASN1ObjectIdentifier des_EDE3_CBC = encryptionAlgorithm.branch("7");
+ /** 1.2.840.113549.3.2 */
static final ASN1ObjectIdentifier RC2_CBC = encryptionAlgorithm.branch("2");
+ /** 1.2.840.113549.3.4 */
static final ASN1ObjectIdentifier rc4 = encryptionAlgorithm.branch("4");
//
// object identifiers for digests
//
+ /** 1.2.840.113549.2 */
static final ASN1ObjectIdentifier digestAlgorithm = new ASN1ObjectIdentifier("1.2.840.113549.2");
//
// md2 OBJECT IDENTIFIER ::=
// {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 2}
//
// BEGIN android-removed
+ // /** 1.2.840.113549.2.2 */
// static final ASN1ObjectIdentifier md2 = digestAlgorithm.branch("2");
// END android-removed
@@ -77,188 +108,289 @@ public interface PKCSObjectIdentifiers
// {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 4}
//
// BEGIN android-removed
- // static final ASN1ObjectIdentifier md4 = digestAlgorithm.branch("4");
+ // /** 1.2.840.113549.2.4 */
+ // static final ASN1ObjectIdentifier md4 = digestAlgorithm.branch("4");
// END android-removed
//
// md5 OBJECT IDENTIFIER ::=
// {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
//
- static final ASN1ObjectIdentifier md5 = digestAlgorithm.branch("5");
+ /** 1.2.840.113549.2.5 */
+ static final ASN1ObjectIdentifier md5 = digestAlgorithm.branch("5");
- static final ASN1ObjectIdentifier id_hmacWithSHA1 = digestAlgorithm.branch("7");
- static final ASN1ObjectIdentifier id_hmacWithSHA224 = digestAlgorithm.branch("8");
- static final ASN1ObjectIdentifier id_hmacWithSHA256 = digestAlgorithm.branch("9");
- static final ASN1ObjectIdentifier id_hmacWithSHA384 = digestAlgorithm.branch("10");
- static final ASN1ObjectIdentifier id_hmacWithSHA512 = digestAlgorithm.branch("11");
+ /** 1.2.840.113549.2.7 */
+ static final ASN1ObjectIdentifier id_hmacWithSHA1 = digestAlgorithm.branch("7");
+ /** 1.2.840.113549.2.8 */
+ static final ASN1ObjectIdentifier id_hmacWithSHA224 = digestAlgorithm.branch("8");
+ /** 1.2.840.113549.2.9 */
+ static final ASN1ObjectIdentifier id_hmacWithSHA256 = digestAlgorithm.branch("9");
+ /** 1.2.840.113549.2.10 */
+ static final ASN1ObjectIdentifier id_hmacWithSHA384 = digestAlgorithm.branch("10");
+ /** 1.2.840.113549.2.11 */
+ static final ASN1ObjectIdentifier id_hmacWithSHA512 = digestAlgorithm.branch("11");
//
// pkcs-7 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 }
//
- static final String pkcs_7 = "1.2.840.113549.1.7";
- static final ASN1ObjectIdentifier data = new ASN1ObjectIdentifier(pkcs_7 + ".1");
- static final ASN1ObjectIdentifier signedData = new ASN1ObjectIdentifier(pkcs_7 + ".2");
- static final ASN1ObjectIdentifier envelopedData = new ASN1ObjectIdentifier(pkcs_7 + ".3");
- static final ASN1ObjectIdentifier signedAndEnvelopedData = new ASN1ObjectIdentifier(pkcs_7 + ".4");
- static final ASN1ObjectIdentifier digestedData = new ASN1ObjectIdentifier(pkcs_7 + ".5");
- static final ASN1ObjectIdentifier encryptedData = new ASN1ObjectIdentifier(pkcs_7 + ".6");
+ /** pkcs#7: 1.2.840.113549.1.7 */
+ static final ASN1ObjectIdentifier pkcs_7 = new ASN1ObjectIdentifier("1.2.840.113549.1.7");
+ /** PKCS#7: 1.2.840.113549.1.7.1 */
+ static final ASN1ObjectIdentifier data = new ASN1ObjectIdentifier("1.2.840.113549.1.7.1");
+ /** PKCS#7: 1.2.840.113549.1.7.2 */
+ static final ASN1ObjectIdentifier signedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.2");
+ /** PKCS#7: 1.2.840.113549.1.7.3 */
+ static final ASN1ObjectIdentifier envelopedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.3");
+ /** PKCS#7: 1.2.840.113549.1.7.4 */
+ static final ASN1ObjectIdentifier signedAndEnvelopedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.4");
+ /** PKCS#7: 1.2.840.113549.1.7.5 */
+ static final ASN1ObjectIdentifier digestedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.5");
+ /** PKCS#7: 1.2.840.113549.1.7.76 */
+ static final ASN1ObjectIdentifier encryptedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.6");
//
// pkcs-9 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
//
+ /** PKCS#9: 1.2.840.113549.1.9 */
static final ASN1ObjectIdentifier pkcs_9 = new ASN1ObjectIdentifier("1.2.840.113549.1.9");
- static final ASN1ObjectIdentifier pkcs_9_at_emailAddress = pkcs_9.branch("1");
- static final ASN1ObjectIdentifier pkcs_9_at_unstructuredName = pkcs_9.branch("2");
- static final ASN1ObjectIdentifier pkcs_9_at_contentType = pkcs_9.branch("3");
- static final ASN1ObjectIdentifier pkcs_9_at_messageDigest = pkcs_9.branch("4");
- static final ASN1ObjectIdentifier pkcs_9_at_signingTime = pkcs_9.branch("5");
- static final ASN1ObjectIdentifier pkcs_9_at_counterSignature = pkcs_9.branch("6");
- static final ASN1ObjectIdentifier pkcs_9_at_challengePassword = pkcs_9.branch("7");
+ /** PKCS#9: 1.2.840.113549.1.9.1 */
+ static final ASN1ObjectIdentifier pkcs_9_at_emailAddress = pkcs_9.branch("1");
+ /** PKCS#9: 1.2.840.113549.1.9.2 */
+ static final ASN1ObjectIdentifier pkcs_9_at_unstructuredName = pkcs_9.branch("2");
+ /** PKCS#9: 1.2.840.113549.1.9.3 */
+ static final ASN1ObjectIdentifier pkcs_9_at_contentType = pkcs_9.branch("3");
+ /** PKCS#9: 1.2.840.113549.1.9.4 */
+ static final ASN1ObjectIdentifier pkcs_9_at_messageDigest = pkcs_9.branch("4");
+ /** PKCS#9: 1.2.840.113549.1.9.5 */
+ static final ASN1ObjectIdentifier pkcs_9_at_signingTime = pkcs_9.branch("5");
+ /** PKCS#9: 1.2.840.113549.1.9.6 */
+ static final ASN1ObjectIdentifier pkcs_9_at_counterSignature = pkcs_9.branch("6");
+ /** PKCS#9: 1.2.840.113549.1.9.7 */
+ static final ASN1ObjectIdentifier pkcs_9_at_challengePassword = pkcs_9.branch("7");
+ /** PKCS#9: 1.2.840.113549.1.9.8 */
static final ASN1ObjectIdentifier pkcs_9_at_unstructuredAddress = pkcs_9.branch("8");
+ /** PKCS#9: 1.2.840.113549.1.9.9 */
static final ASN1ObjectIdentifier pkcs_9_at_extendedCertificateAttributes = pkcs_9.branch("9");
+ /** PKCS#9: 1.2.840.113549.1.9.13 */
static final ASN1ObjectIdentifier pkcs_9_at_signingDescription = pkcs_9.branch("13");
- static final ASN1ObjectIdentifier pkcs_9_at_extensionRequest = pkcs_9.branch("14");
- static final ASN1ObjectIdentifier pkcs_9_at_smimeCapabilities = pkcs_9.branch("15");
-
+ /** PKCS#9: 1.2.840.113549.1.9.14 */
+ static final ASN1ObjectIdentifier pkcs_9_at_extensionRequest = pkcs_9.branch("14");
+ /** PKCS#9: 1.2.840.113549.1.9.15 */
+ static final ASN1ObjectIdentifier pkcs_9_at_smimeCapabilities = pkcs_9.branch("15");
+ /** PKCS#9: 1.2.840.113549.1.9.16 */
+ static final ASN1ObjectIdentifier id_smime = pkcs_9.branch("16");
+
+ /** PKCS#9: 1.2.840.113549.1.9.20 */
static final ASN1ObjectIdentifier pkcs_9_at_friendlyName = pkcs_9.branch("20");
+ /** PKCS#9: 1.2.840.113549.1.9.21 */
static final ASN1ObjectIdentifier pkcs_9_at_localKeyId = pkcs_9.branch("21");
- /** @deprecated use x509Certificate instead */
+ /** PKCS#9: 1.2.840.113549.1.9.22.1
+ * @deprecated use x509Certificate instead */
static final ASN1ObjectIdentifier x509certType = pkcs_9.branch("22.1");
+ /** PKCS#9: 1.2.840.113549.1.9.22 */
static final ASN1ObjectIdentifier certTypes = pkcs_9.branch("22");
+ /** PKCS#9: 1.2.840.113549.1.9.22.1 */
static final ASN1ObjectIdentifier x509Certificate = certTypes.branch("1");
+ /** PKCS#9: 1.2.840.113549.1.9.22.2 */
static final ASN1ObjectIdentifier sdsiCertificate = certTypes.branch("2");
+ /** PKCS#9: 1.2.840.113549.1.9.23 */
static final ASN1ObjectIdentifier crlTypes = pkcs_9.branch("23");
+ /** PKCS#9: 1.2.840.113549.1.9.23.1 */
static final ASN1ObjectIdentifier x509Crl = crlTypes.branch("1");
- static final ASN1ObjectIdentifier id_alg_PWRI_KEK = pkcs_9.branch("16.3.9");
-
//
// SMIME capability sub oids.
//
+ /** PKCS#9: 1.2.840.113549.1.9.15.1 -- smime capability */
static final ASN1ObjectIdentifier preferSignedData = pkcs_9.branch("15.1");
+ /** PKCS#9: 1.2.840.113549.1.9.15.2 -- smime capability */
static final ASN1ObjectIdentifier canNotDecryptAny = pkcs_9.branch("15.2");
+ /** PKCS#9: 1.2.840.113549.1.9.15.3 -- smime capability */
static final ASN1ObjectIdentifier sMIMECapabilitiesVersions = pkcs_9.branch("15.3");
//
// id-ct OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
// rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1)}
//
+ /** PKCS#9: 1.2.840.113549.1.9.16.1 -- smime ct */
static final ASN1ObjectIdentifier id_ct = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.1");
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.2 -- smime ct authData */
static final ASN1ObjectIdentifier id_ct_authData = id_ct.branch("2");
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.4 -- smime ct TSTInfo*/
static final ASN1ObjectIdentifier id_ct_TSTInfo = id_ct.branch("4");
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.9 -- smime ct compressedData */
static final ASN1ObjectIdentifier id_ct_compressedData = id_ct.branch("9");
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.23 -- smime ct authEnvelopedData */
static final ASN1ObjectIdentifier id_ct_authEnvelopedData = id_ct.branch("23");
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.31 -- smime ct timestampedData*/
static final ASN1ObjectIdentifier id_ct_timestampedData = id_ct.branch("31");
+
+ /** S/MIME: Algorithm Identifiers ; 1.2.840.113549.1.9.16.3 */
+ static final ASN1ObjectIdentifier id_alg = id_smime.branch("3");
+ /** PKCS#9: 1.2.840.113549.1.9.16.3.9 */
+ static final ASN1ObjectIdentifier id_alg_PWRI_KEK = id_alg.branch("9");
+
//
// id-cti OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
// rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) cti(6)}
//
+ /** PKCS#9: 1.2.840.113549.1.9.16.6 -- smime cti */
static final ASN1ObjectIdentifier id_cti = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.6");
- static final ASN1ObjectIdentifier id_cti_ets_proofOfOrigin = id_cti.branch("1");
- static final ASN1ObjectIdentifier id_cti_ets_proofOfReceipt = id_cti.branch("2");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.1 -- smime cti proofOfOrigin */
+ static final ASN1ObjectIdentifier id_cti_ets_proofOfOrigin = id_cti.branch("1");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2 -- smime cti proofOfReceipt*/
+ static final ASN1ObjectIdentifier id_cti_ets_proofOfReceipt = id_cti.branch("2");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.3 -- smime cti proofOfDelivery */
static final ASN1ObjectIdentifier id_cti_ets_proofOfDelivery = id_cti.branch("3");
- static final ASN1ObjectIdentifier id_cti_ets_proofOfSender = id_cti.branch("4");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.4 -- smime cti proofOfSender */
+ static final ASN1ObjectIdentifier id_cti_ets_proofOfSender = id_cti.branch("4");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.5 -- smime cti proofOfApproval */
static final ASN1ObjectIdentifier id_cti_ets_proofOfApproval = id_cti.branch("5");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.6 -- smime cti proofOfCreation */
static final ASN1ObjectIdentifier id_cti_ets_proofOfCreation = id_cti.branch("6");
//
// id-aa OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
// rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) attributes(2)}
//
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2 - smime attributes */
static final ASN1ObjectIdentifier id_aa = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.2");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.1 -- smime attribute receiptRequest */
static final ASN1ObjectIdentifier id_aa_receiptRequest = id_aa.branch("1");
- static final ASN1ObjectIdentifier id_aa_contentHint = id_aa.branch("4"); // See RFC 2634
- static final ASN1ObjectIdentifier id_aa_msgSigDigest = id_aa.branch("5");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.4 - See <a href="http://tools.ietf.org/html/rfc2634">RFC 2634</a> */
+ static final ASN1ObjectIdentifier id_aa_contentHint = id_aa.branch("4"); // See RFC 2634
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.5 */
+ static final ASN1ObjectIdentifier id_aa_msgSigDigest = id_aa.branch("5");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.10 */
static final ASN1ObjectIdentifier id_aa_contentReference = id_aa.branch("10");
/*
* id-aa-encrypKeyPref OBJECT IDENTIFIER ::= {id-aa 11}
*
*/
- static final ASN1ObjectIdentifier id_aa_encrypKeyPref = id_aa.branch("11");
- static final ASN1ObjectIdentifier id_aa_signingCertificate = id_aa.branch("12");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.11 */
+ static final ASN1ObjectIdentifier id_aa_encrypKeyPref = id_aa.branch("11");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.12 */
+ static final ASN1ObjectIdentifier id_aa_signingCertificate = id_aa.branch("12");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.47 */
static final ASN1ObjectIdentifier id_aa_signingCertificateV2 = id_aa.branch("47");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.7 - See <a href="http://tools.ietf.org/html/rfc2634">RFC 2634</a> */
static final ASN1ObjectIdentifier id_aa_contentIdentifier = id_aa.branch("7"); // See RFC 2634
/*
* RFC 3126
*/
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.14 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_signatureTimeStampToken = id_aa.branch("14");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.15 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_ets_sigPolicyId = id_aa.branch("15");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.16 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_ets_commitmentType = id_aa.branch("16");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.17 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_ets_signerLocation = id_aa.branch("17");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.18 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_ets_signerAttr = id_aa.branch("18");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.19 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_ets_otherSigCert = id_aa.branch("19");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.20 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_ets_contentTimestamp = id_aa.branch("20");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.21 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_ets_certificateRefs = id_aa.branch("21");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.22 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_ets_revocationRefs = id_aa.branch("22");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.23 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_ets_certValues = id_aa.branch("23");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.24 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_ets_revocationValues = id_aa.branch("24");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.25 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_ets_escTimeStamp = id_aa.branch("25");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.26 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_ets_certCRLTimestamp = id_aa.branch("26");
+ /** PKCS#9: 1.2.840.113549.1.9.16.6.2.27 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
static final ASN1ObjectIdentifier id_aa_ets_archiveTimestamp = id_aa.branch("27");
/** @deprecated use id_aa_ets_sigPolicyId instead */
- static final ASN1ObjectIdentifier id_aa_sigPolicyId = id_aa_ets_sigPolicyId;
+ static final ASN1ObjectIdentifier id_aa_sigPolicyId = id_aa_ets_sigPolicyId;
/** @deprecated use id_aa_ets_commitmentType instead */
static final ASN1ObjectIdentifier id_aa_commitmentType = id_aa_ets_commitmentType;
/** @deprecated use id_aa_ets_signerLocation instead */
static final ASN1ObjectIdentifier id_aa_signerLocation = id_aa_ets_signerLocation;
/** @deprecated use id_aa_ets_otherSigCert instead */
- static final ASN1ObjectIdentifier id_aa_otherSigCert = id_aa_ets_otherSigCert;
+ static final ASN1ObjectIdentifier id_aa_otherSigCert = id_aa_ets_otherSigCert;
- //
- // id-spq OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
- // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) id-spq(5)}
- //
+ /**
+ * id-spq OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ * rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) id-spq(5)}; <p>
+ * 1.2.840.113549.1.9.16.5
+ */
final String id_spq = "1.2.840.113549.1.9.16.5";
- static final ASN1ObjectIdentifier id_spq_ets_uri = new ASN1ObjectIdentifier(id_spq + ".1");
+ /** SMIME SPQ URI: 1.2.840.113549.1.9.16.5.1 */
+ static final ASN1ObjectIdentifier id_spq_ets_uri = new ASN1ObjectIdentifier(id_spq + ".1");
+ /** SMIME SPQ UNOTICE: 1.2.840.113549.1.9.16.5.2 */
static final ASN1ObjectIdentifier id_spq_ets_unotice = new ASN1ObjectIdentifier(id_spq + ".2");
//
// pkcs-12 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 }
//
+ /** PKCS#12: 1.2.840.113549.1.12 */
static final ASN1ObjectIdentifier pkcs_12 = new ASN1ObjectIdentifier("1.2.840.113549.1.12");
+ /** PKCS#12: 1.2.840.113549.1.12.10.1 */
static final ASN1ObjectIdentifier bagtypes = pkcs_12.branch("10.1");
+ /** PKCS#12: 1.2.840.113549.1.12.10.1.1 */
static final ASN1ObjectIdentifier keyBag = bagtypes.branch("1");
+ /** PKCS#12: 1.2.840.113549.1.12.10.1.2 */
static final ASN1ObjectIdentifier pkcs8ShroudedKeyBag = bagtypes.branch("2");
+ /** PKCS#12: 1.2.840.113549.1.12.10.1.3 */
static final ASN1ObjectIdentifier certBag = bagtypes.branch("3");
+ /** PKCS#12: 1.2.840.113549.1.12.10.1.4 */
static final ASN1ObjectIdentifier crlBag = bagtypes.branch("4");
+ /** PKCS#12: 1.2.840.113549.1.12.10.1.5 */
static final ASN1ObjectIdentifier secretBag = bagtypes.branch("5");
+ /** PKCS#12: 1.2.840.113549.1.12.10.1.6 */
static final ASN1ObjectIdentifier safeContentsBag = bagtypes.branch("6");
- static final ASN1ObjectIdentifier pkcs_12PbeIds = pkcs_12.branch("1");
+ /** PKCS#12: 1.2.840.113549.1.12.1 */
+ static final ASN1ObjectIdentifier pkcs_12PbeIds = pkcs_12.branch("1");
- static final ASN1ObjectIdentifier pbeWithSHAAnd128BitRC4 = pkcs_12PbeIds.branch("1");
- static final ASN1ObjectIdentifier pbeWithSHAAnd40BitRC4 = pkcs_12PbeIds.branch("2");
+ /** PKCS#12: 1.2.840.113549.1.12.1.1 */
+ static final ASN1ObjectIdentifier pbeWithSHAAnd128BitRC4 = pkcs_12PbeIds.branch("1");
+ /** PKCS#12: 1.2.840.113549.1.12.1.2 */
+ static final ASN1ObjectIdentifier pbeWithSHAAnd40BitRC4 = pkcs_12PbeIds.branch("2");
+ /** PKCS#12: 1.2.840.113549.1.12.1.3 */
static final ASN1ObjectIdentifier pbeWithSHAAnd3_KeyTripleDES_CBC = pkcs_12PbeIds.branch("3");
+ /** PKCS#12: 1.2.840.113549.1.12.1.4 */
static final ASN1ObjectIdentifier pbeWithSHAAnd2_KeyTripleDES_CBC = pkcs_12PbeIds.branch("4");
- static final ASN1ObjectIdentifier pbeWithSHAAnd128BitRC2_CBC = pkcs_12PbeIds.branch("5");
- static final ASN1ObjectIdentifier pbeWithSHAAnd40BitRC2_CBC = pkcs_12PbeIds.branch("6");
+ /** PKCS#12: 1.2.840.113549.1.12.1.5 */
+ static final ASN1ObjectIdentifier pbeWithSHAAnd128BitRC2_CBC = pkcs_12PbeIds.branch("5");
+ /** PKCS#12: 1.2.840.113549.1.12.1.6 */
+ static final ASN1ObjectIdentifier pbeWithSHAAnd40BitRC2_CBC = pkcs_12PbeIds.branch("6");
/**
+ * PKCS#12: 1.2.840.113549.1.12.1.6
* @deprecated use pbeWithSHAAnd40BitRC2_CBC
*/
static final ASN1ObjectIdentifier pbewithSHAAnd40BitRC2_CBC = pkcs_12PbeIds.branch("6");
+ /** PKCS#9: 1.2.840.113549.1.9.16.3.6 */
static final ASN1ObjectIdentifier id_alg_CMS3DESwrap = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.6");
- static final ASN1ObjectIdentifier id_alg_CMSRC2wrap = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.7");
+ /** PKCS#9: 1.2.840.113549.1.9.16.3.7 */
+ static final ASN1ObjectIdentifier id_alg_CMSRC2wrap = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.7");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java
index 515b515..e707fd1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java
@@ -57,7 +57,11 @@ public class RSAESOAEPparams
this.maskGenAlgorithm = maskGenAlgorithm;
this.pSourceAlgorithm = pSourceAlgorithm;
}
-
+
+ /**
+ * @deprecated use getInstance()
+ * @param seq
+ */
public RSAESOAEPparams(
ASN1Sequence seq)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java
index 4bf6b2b..df2238a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java
@@ -62,7 +62,7 @@ public class ECPrivateKey
public ECPrivateKey(
BigInteger key,
- ASN1Object parameters)
+ ASN1Encodable parameters)
{
this(key, null, parameters);
}
@@ -70,7 +70,7 @@ public class ECPrivateKey
public ECPrivateKey(
BigInteger key,
DERBitString publicKey,
- ASN1Object parameters)
+ ASN1Encodable parameters)
{
byte[] bytes = BigIntegers.asUnsignedByteArray(key);
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java
index 44c811b..50a7a63 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java
@@ -15,6 +15,21 @@ import org.bouncycastle.util.encoders.Hex;
public class SECNamedCurves
{
+ private static ECCurve configureCurve(ECCurve curve)
+ {
+// int coord = ECCurve.COORD_JACOBIAN_MODIFIED;
+//
+// if (curve.getCoordinateSystem() != coord && curve.supportsCoordinateSystem(coord))
+// {
+// return curve.configure()
+// .setCoordinateSystem(coord)
+//// .setMultiplier(new WNafL2RMultiplier())
+// .create();
+// }
+
+ return curve;
+ }
+
private static BigInteger fromHex(
String hex)
{
@@ -36,7 +51,7 @@ public class SECNamedCurves
BigInteger n = fromHex("DB7C2ABF62E35E7628DFAC6561C5");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "09487239995A5EE76B55F9C2F098"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -62,7 +77,7 @@ public class SECNamedCurves
BigInteger n = fromHex("36DF0AAFD8B8D7597CA10520D04B");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "4BA30AB5E892B4E1649DD0928643"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -88,7 +103,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFE0000000075A30D1B9038A115");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "161FF7528B899B2D0C28607CA52C5B86"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -114,7 +129,7 @@ public class SECNamedCurves
BigInteger n = fromHex("3FFFFFFF7FFFFFFFBE0024720613B5A3");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "7B6AA5D85E572983E6FB32A7CDEBC140"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -140,7 +155,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
// ECPoint G = curve.decodePoint(Hex.decode("02"
// + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -166,7 +181,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0100000000000000000001F4C8F927AED3CA752257");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "4A96B5688EF573284664698968C38BB913CBFC82"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -192,7 +207,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0100000000000000000000351EE786A818F3A1A16B");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -218,7 +233,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -244,7 +259,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -270,7 +285,7 @@ public class SECNamedCurves
BigInteger n = fromHex("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -296,7 +311,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -322,7 +337,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -348,7 +363,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -374,7 +389,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -400,7 +415,8 @@ public class SECNamedCurves
BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -410,7 +426,7 @@ public class SECNamedCurves
return new X9ECParameters(curve, G, n, h, S);
}
};
-
+
/*
* sect113r1
*/
@@ -427,7 +443,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0100000000000000D9CCEC8A39E56F");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "009D73616F35F4AB1407D73562C10F"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -454,7 +470,7 @@ public class SECNamedCurves
BigInteger n = fromHex("010000000000000108789B2496AF93");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "01A57A6A7B26CA5EF52FCDB8164797"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -483,7 +499,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0400000000000000023123953A9464B54D");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "0081BAF91FDF9833C40F9C181343638399"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -512,7 +528,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0400000000000000016954A233049BA98F");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "0356DCD8F2F95031AD652D23951BB366A8"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -541,7 +557,7 @@ public class SECNamedCurves
BigInteger n = fromHex("04000000000000000000020108A2E0CC0D99F8A5EF");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -570,7 +586,7 @@ public class SECNamedCurves
BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "0369979697AB43897789566789567F787A7876A654"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -599,7 +615,7 @@ public class SECNamedCurves
BigInteger n = fromHex("040000000000000000000292FE77E70C12A4234C33");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "03F0EBA16286A2D57EA0991168D4994637E8343E36"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -626,7 +642,7 @@ public class SECNamedCurves
BigInteger n = fromHex("01000000000000000000000000C7F34A778F443ACC920EBA49");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -653,7 +669,7 @@ public class SECNamedCurves
BigInteger n = fromHex("010000000000000000000000015AAB561B005413CCD4EE99D5");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -680,7 +696,7 @@ public class SECNamedCurves
BigInteger n = fromHex("8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -707,7 +723,7 @@ public class SECNamedCurves
BigInteger n = fromHex("01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -734,7 +750,7 @@ public class SECNamedCurves
BigInteger n = fromHex("2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -763,7 +779,7 @@ public class SECNamedCurves
BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -792,7 +808,7 @@ public class SECNamedCurves
BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -819,7 +835,7 @@ public class SECNamedCurves
BigInteger n = fromHex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -846,7 +862,7 @@ public class SECNamedCurves
BigInteger n = fromHex("010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -875,7 +891,7 @@ public class SECNamedCurves
BigInteger n = fromHex("020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -904,7 +920,7 @@ public class SECNamedCurves
BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"));
ECPoint G = curve.decodePoint(Hex.decode("04"
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java
index 8b19cd6..fb60aca 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java
@@ -3,48 +3,85 @@ package org.bouncycastle.asn1.sec;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+/**
+ * Certicom object identifiers
+ * <pre>
+ * ellipticCurve OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) certicom(132) curve(0)
+ * }
+ * </pre>
+ */
public interface SECObjectIdentifiers
{
- /**
- * ellipticCurve OBJECT IDENTIFIER ::= {
- * iso(1) identified-organization(3) certicom(132) curve(0)
- * }
- */
+ /** Base OID: 1.3.132.0 */
static final ASN1ObjectIdentifier ellipticCurve = new ASN1ObjectIdentifier("1.3.132.0");
+ /** sect163k1 OID: 1.3.132.0.1 */
static final ASN1ObjectIdentifier sect163k1 = ellipticCurve.branch("1");
+ /** sect163r1 OID: 1.3.132.0.2 */
static final ASN1ObjectIdentifier sect163r1 = ellipticCurve.branch("2");
+ /** sect239k1 OID: 1.3.132.0.3 */
static final ASN1ObjectIdentifier sect239k1 = ellipticCurve.branch("3");
+ /** sect113r1 OID: 1.3.132.0.4 */
static final ASN1ObjectIdentifier sect113r1 = ellipticCurve.branch("4");
+ /** sect113r2 OID: 1.3.132.0.5 */
static final ASN1ObjectIdentifier sect113r2 = ellipticCurve.branch("5");
+ /** secp112r1 OID: 1.3.132.0.6 */
static final ASN1ObjectIdentifier secp112r1 = ellipticCurve.branch("6");
+ /** secp112r2 OID: 1.3.132.0.7 */
static final ASN1ObjectIdentifier secp112r2 = ellipticCurve.branch("7");
+ /** secp160r1 OID: 1.3.132.0.8 */
static final ASN1ObjectIdentifier secp160r1 = ellipticCurve.branch("8");
+ /** secp160k1 OID: 1.3.132.0.9 */
static final ASN1ObjectIdentifier secp160k1 = ellipticCurve.branch("9");
+ /** secp256k1 OID: 1.3.132.0.10 */
static final ASN1ObjectIdentifier secp256k1 = ellipticCurve.branch("10");
+ /** sect163r2 OID: 1.3.132.0.15 */
static final ASN1ObjectIdentifier sect163r2 = ellipticCurve.branch("15");
+ /** sect283k1 OID: 1.3.132.0.16 */
static final ASN1ObjectIdentifier sect283k1 = ellipticCurve.branch("16");
+ /** sect283r1 OID: 1.3.132.0.17 */
static final ASN1ObjectIdentifier sect283r1 = ellipticCurve.branch("17");
+ /** sect131r1 OID: 1.3.132.0.22 */
static final ASN1ObjectIdentifier sect131r1 = ellipticCurve.branch("22");
+ /** sect131r2 OID: 1.3.132.0.23 */
static final ASN1ObjectIdentifier sect131r2 = ellipticCurve.branch("23");
+ /** sect193r1 OID: 1.3.132.0.24 */
static final ASN1ObjectIdentifier sect193r1 = ellipticCurve.branch("24");
+ /** sect193r2 OID: 1.3.132.0.25 */
static final ASN1ObjectIdentifier sect193r2 = ellipticCurve.branch("25");
+ /** sect233k1 OID: 1.3.132.0.26 */
static final ASN1ObjectIdentifier sect233k1 = ellipticCurve.branch("26");
+ /** sect233r1 OID: 1.3.132.0.27 */
static final ASN1ObjectIdentifier sect233r1 = ellipticCurve.branch("27");
+ /** secp128r1 OID: 1.3.132.0.28 */
static final ASN1ObjectIdentifier secp128r1 = ellipticCurve.branch("28");
+ /** secp128r2 OID: 1.3.132.0.29 */
static final ASN1ObjectIdentifier secp128r2 = ellipticCurve.branch("29");
+ /** secp160r2 OID: 1.3.132.0.30 */
static final ASN1ObjectIdentifier secp160r2 = ellipticCurve.branch("30");
+ /** secp192k1 OID: 1.3.132.0.31 */
static final ASN1ObjectIdentifier secp192k1 = ellipticCurve.branch("31");
+ /** secp224k1 OID: 1.3.132.0.32 */
static final ASN1ObjectIdentifier secp224k1 = ellipticCurve.branch("32");
+ /** secp224r1 OID: 1.3.132.0.33 */
static final ASN1ObjectIdentifier secp224r1 = ellipticCurve.branch("33");
+ /** secp384r1 OID: 1.3.132.0.34 */
static final ASN1ObjectIdentifier secp384r1 = ellipticCurve.branch("34");
+ /** secp521r1 OID: 1.3.132.0.35 */
static final ASN1ObjectIdentifier secp521r1 = ellipticCurve.branch("35");
+ /** sect409k1 OID: 1.3.132.0.36 */
static final ASN1ObjectIdentifier sect409k1 = ellipticCurve.branch("36");
+ /** sect409r1 OID: 1.3.132.0.37 */
static final ASN1ObjectIdentifier sect409r1 = ellipticCurve.branch("37");
+ /** sect571k1 OID: 1.3.132.0.38 */
static final ASN1ObjectIdentifier sect571k1 = ellipticCurve.branch("38");
+ /** sect571r1 OID: 1.3.132.0.39 */
static final ASN1ObjectIdentifier sect571r1 = ellipticCurve.branch("39");
+ /** secp192r1 OID: 1.3.132.0.prime192v1 */
static final ASN1ObjectIdentifier secp192r1 = X9ObjectIdentifiers.prime192v1;
+ /** secp256r1 OID: 1.3.132.0.prime256v1 */
static final ASN1ObjectIdentifier secp256r1 = X9ObjectIdentifiers.prime256v1;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
index df9a0ff..895f5e8 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
@@ -2,41 +2,74 @@ package org.bouncycastle.asn1.teletrust;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * TeleTrusT:
+ * { iso(1) identifier-organization(3) teleTrust(36) algorithm(3)
+ *
+ */
public interface TeleTrusTObjectIdentifiers
{
+ /** 1.3.36.3 */
static final ASN1ObjectIdentifier teleTrusTAlgorithm = new ASN1ObjectIdentifier("1.3.36.3");
+ /** 1.3.36.3.2.1 */
static final ASN1ObjectIdentifier ripemd160 = teleTrusTAlgorithm.branch("2.1");
+ /** 1.3.36.3.2.2 */
static final ASN1ObjectIdentifier ripemd128 = teleTrusTAlgorithm.branch("2.2");
+ /** 1.3.36.3.2.3 */
static final ASN1ObjectIdentifier ripemd256 = teleTrusTAlgorithm.branch("2.3");
+ /** 1.3.36.3.3.1 */
static final ASN1ObjectIdentifier teleTrusTRSAsignatureAlgorithm = teleTrusTAlgorithm.branch("3.1");
- static final ASN1ObjectIdentifier rsaSignatureWithripemd160 = teleTrusTRSAsignatureAlgorithm.branch("2");
- static final ASN1ObjectIdentifier rsaSignatureWithripemd128 = teleTrusTRSAsignatureAlgorithm.branch("3");
- static final ASN1ObjectIdentifier rsaSignatureWithripemd256 = teleTrusTRSAsignatureAlgorithm.branch("4");
+ /** 1.3.36.3.3.1.2 */
+ static final ASN1ObjectIdentifier rsaSignatureWithripemd160 = teleTrusTRSAsignatureAlgorithm.branch("2");
+ /** 1.3.36.3.3.1.3 */
+ static final ASN1ObjectIdentifier rsaSignatureWithripemd128 = teleTrusTRSAsignatureAlgorithm.branch("3");
+ /** 1.3.36.3.3.1.4 */
+ static final ASN1ObjectIdentifier rsaSignatureWithripemd256 = teleTrusTRSAsignatureAlgorithm.branch("4");
- static final ASN1ObjectIdentifier ecSign = teleTrusTAlgorithm.branch("3.2");
+ /** 1.3.36.3.3.2 */
+ static final ASN1ObjectIdentifier ecSign = teleTrusTAlgorithm.branch("3.2");
- static final ASN1ObjectIdentifier ecSignWithSha1 = ecSign.branch("1");
+ /** 1.3.36.3.3.2,1 */
+ static final ASN1ObjectIdentifier ecSignWithSha1 = ecSign.branch("1");
+ /** 1.3.36.3.3.2.2 */
static final ASN1ObjectIdentifier ecSignWithRipemd160 = ecSign.branch("2");
+ /** 1.3.36.3.3.2.8 */
static final ASN1ObjectIdentifier ecc_brainpool = teleTrusTAlgorithm.branch("3.2.8");
+ /** 1.3.36.3.3.2.8.1 */
static final ASN1ObjectIdentifier ellipticCurve = ecc_brainpool.branch("1");
+ /** 1.3.36.3.3.2.8.1 */
static final ASN1ObjectIdentifier versionOne = ellipticCurve.branch("1");
+ /** 1.3.36.3.3.2.8.1.1 */
static final ASN1ObjectIdentifier brainpoolP160r1 = versionOne.branch("1");
+ /** 1.3.36.3.3.2.8.1.2 */
static final ASN1ObjectIdentifier brainpoolP160t1 = versionOne.branch("2");
+ /** 1.3.36.3.3.2.8.1.3 */
static final ASN1ObjectIdentifier brainpoolP192r1 = versionOne.branch("3");
+ /** 1.3.36.3.3.2.8.1.4 */
static final ASN1ObjectIdentifier brainpoolP192t1 = versionOne.branch("4");
+ /** 1.3.36.3.3.2.8.1.5 */
static final ASN1ObjectIdentifier brainpoolP224r1 = versionOne.branch("5");
+ /** 1.3.36.3.3.2.8.1.6 */
static final ASN1ObjectIdentifier brainpoolP224t1 = versionOne.branch("6");
+ /** 1.3.36.3.3.2.8.1.7 */
static final ASN1ObjectIdentifier brainpoolP256r1 = versionOne.branch("7");
+ /** 1.3.36.3.3.2.8.1.8 */
static final ASN1ObjectIdentifier brainpoolP256t1 = versionOne.branch("8");
+ /** 1.3.36.3.3.2.8.1.9 */
static final ASN1ObjectIdentifier brainpoolP320r1 = versionOne.branch("9");
+ /** 1.3.36.3.3.2.8.1.10 */
static final ASN1ObjectIdentifier brainpoolP320t1 = versionOne.branch("10");
+ /** 1.3.36.3.3.2.8.1.11 */
static final ASN1ObjectIdentifier brainpoolP384r1 = versionOne.branch("11");
+ /** 1.3.36.3.3.2.8.1.12 */
static final ASN1ObjectIdentifier brainpoolP384t1 = versionOne.branch("12");
+ /** 1.3.36.3.3.2.8.1.13 */
static final ASN1ObjectIdentifier brainpoolP512r1 = versionOne.branch("13");
+ /** 1.3.36.3.3.2.8.1.14 */
static final ASN1ObjectIdentifier brainpoolP512t1 = versionOne.branch("14");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java
index 714a32c..6842182 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java
@@ -1,6 +1,7 @@
package org.bouncycastle.asn1.x500.style;
import java.io.IOException;
+import java.util.Enumeration;
import java.util.Hashtable;
import org.bouncycastle.asn1.ASN1Encodable;
@@ -19,8 +20,6 @@ import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
public class BCStyle
implements X500NameStyle
{
- public static final X500NameStyle INSTANCE = new BCStyle();
-
/**
* country code - StringType(SIZE(2))
*/
@@ -273,9 +272,18 @@ public class BCStyle
DefaultLookUp.put("name", NAME);
}
+ /**
+ * Singleton instance.
+ */
+ public static final X500NameStyle INSTANCE = new BCStyle();
+
+ protected final Hashtable defaultLookUp;
+ protected final Hashtable defaultSymbols;
+
protected BCStyle()
{
-
+ defaultSymbols = copyHashTable(DefaultSymbols);
+ defaultLookUp = copyHashTable(DefaultLookUp);
}
public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
@@ -322,12 +330,12 @@ public class BCStyle
public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
{
- return IETFUtils.findAttrNamesForOID(oid, DefaultLookUp);
+ return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
}
public ASN1ObjectIdentifier attrNameToOID(String attrName)
{
- return IETFUtils.decodeAttrName(attrName, DefaultLookUp);
+ return IETFUtils.decodeAttrName(attrName, defaultLookUp);
}
public boolean areEqual(X500Name name1, X500Name name2)
@@ -451,9 +459,23 @@ public class BCStyle
buf.append(',');
}
- IETFUtils.appendRDN(buf, rdns[i], DefaultSymbols);
+ 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/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java
index c73107e..b4f1794 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java
@@ -405,7 +405,7 @@ public class IETFUtils
int start = 0;
if (vBuf.length() > 0)
{
- while (vBuf.charAt(start) == ' ')
+ while (vBuf.length() > start && vBuf.charAt(start) == ' ')
{
vBuf.insert(start, "\\");
start += 2;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java
index 8486989..8c92257 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java
@@ -1,6 +1,7 @@
package org.bouncycastle.asn1.x500.style;
import java.io.IOException;
+import java.util.Enumeration;
import java.util.Hashtable;
import org.bouncycastle.asn1.ASN1Encodable;
@@ -16,8 +17,6 @@ import org.bouncycastle.asn1.x500.X500NameStyle;
public class RFC4519Style
implements X500NameStyle
{
- public static final X500NameStyle INSTANCE = new RFC4519Style();
-
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");
@@ -166,9 +165,18 @@ public class RFC4519Style
// TODO: need to add correct matching for equality comparisons.
}
+ /**
+ * Singleton instance.
+ */
+ public static final X500NameStyle INSTANCE = new RFC4519Style();
+
+ protected final Hashtable defaultLookUp;
+ protected final Hashtable defaultSymbols;
+
protected RFC4519Style()
{
-
+ defaultSymbols = copyHashTable(DefaultSymbols);
+ defaultLookUp = copyHashTable(DefaultLookUp);
}
public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
@@ -211,12 +219,12 @@ public class RFC4519Style
public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
{
- return IETFUtils.findAttrNamesForOID(oid, DefaultLookUp);
+ return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
}
public ASN1ObjectIdentifier attrNameToOID(String attrName)
{
- return IETFUtils.decodeAttrName(attrName, DefaultLookUp);
+ return IETFUtils.decodeAttrName(attrName, defaultLookUp);
}
public boolean areEqual(X500Name name1, X500Name name2)
@@ -350,9 +358,23 @@ public class RFC4519Style
buf.append(',');
}
- IETFUtils.appendRDN(buf, rdns[i], DefaultSymbols);
+ 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/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java
index 92aa0f7..73fe7b4 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java
@@ -41,7 +41,10 @@ public class AttributeCertificate
this.signatureAlgorithm = signatureAlgorithm;
this.signatureValue = signatureValue;
}
-
+
+ /**
+ * @deprecated use getInstance() method.
+ */
public AttributeCertificate(
ASN1Sequence seq)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java
index 7b9d450..ae539f4 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java
@@ -13,7 +13,7 @@ import org.bouncycastle.asn1.DERSequence;
public class AttributeCertificateInfo
extends ASN1Object
{
- private ASN1Integer version;
+ private ASN1Integer version;
private Holder holder;
private AttCertIssuer issuer;
private AlgorithmIdentifier signature;
@@ -48,22 +48,33 @@ public class AttributeCertificateInfo
private AttributeCertificateInfo(
ASN1Sequence seq)
{
- if (seq.size() < 7 || seq.size() > 9)
+ if (seq.size() < 6 || seq.size() > 9)
{
throw new IllegalArgumentException("Bad sequence size: " + seq.size());
}
- this.version = ASN1Integer.getInstance(seq.getObjectAt(0));
- this.holder = Holder.getInstance(seq.getObjectAt(1));
- this.issuer = AttCertIssuer.getInstance(seq.getObjectAt(2));
- this.signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(3));
- this.serialNumber = ASN1Integer.getInstance(seq.getObjectAt(4));
- this.attrCertValidityPeriod = AttCertValidityPeriod.getInstance(seq.getObjectAt(5));
- this.attributes = ASN1Sequence.getInstance(seq.getObjectAt(6));
+ int start;
+ if (seq.getObjectAt(0) instanceof ASN1Integer) // in version 1 certs version is DEFAULT v1(0)
+ {
+ this.version = ASN1Integer.getInstance(seq.getObjectAt(0));
+ start = 1;
+ }
+ else
+ {
+ this.version = new ASN1Integer(0);
+ start = 0;
+ }
+
+ this.holder = Holder.getInstance(seq.getObjectAt(start));
+ this.issuer = AttCertIssuer.getInstance(seq.getObjectAt(start + 1));
+ this.signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(start + 2));
+ this.serialNumber = ASN1Integer.getInstance(seq.getObjectAt(start + 3));
+ this.attrCertValidityPeriod = AttCertValidityPeriod.getInstance(seq.getObjectAt(start + 4));
+ this.attributes = ASN1Sequence.getInstance(seq.getObjectAt(start + 5));
- for (int i = 7; i < seq.size(); i++)
+ for (int i = start + 6; i < seq.size(); i++)
{
- ASN1Encodable obj = (ASN1Encodable)seq.getObjectAt(i);
+ ASN1Encodable obj = seq.getObjectAt(i);
if (obj instanceof DERBitString)
{
@@ -143,7 +154,10 @@ public class AttributeCertificateInfo
{
ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(version);
+ if (version.getValue().intValue() != 0)
+ {
+ v.add(version);
+ }
v.add(holder);
v.add(issuer);
v.add(signature);
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java
index 91a37ad..61d7d4a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java
@@ -31,6 +31,8 @@ public class CertificateList
TBSCertList tbsCertList;
AlgorithmIdentifier sigAlgId;
DERBitString sig;
+ boolean isHashCodeSet = false;
+ int hashCodeValue;
public static CertificateList getInstance(
ASN1TaggedObject obj,
@@ -54,6 +56,10 @@ public class CertificateList
return null;
}
+ /**
+ * @deprecated use getInstance() method.
+ * @param seq
+ */
public CertificateList(
ASN1Sequence seq)
{
@@ -124,4 +130,15 @@ public class CertificateList
return new DERSequence(v);
}
+
+ public int hashCode()
+ {
+ if (!isHashCodeSet)
+ {
+ hashCodeValue = super.hashCode();
+ isHashCodeSet = true;
+ }
+
+ return hashCodeValue;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java
index dcc1b1f..84d21ca 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java
@@ -25,6 +25,13 @@ public class ExtendedKeyUsage
Hashtable usageTable = new Hashtable();
ASN1Sequence seq;
+ /**
+ * Return an ExtendedKeyUsage from the passed in tagged object.
+ *
+ * @param obj the tagged object containing the ExtendedKeyUsage
+ * @param explicit true if the tagged object should be interpreted as explicitly tagged, false if implicit.
+ * @return the ExtendedKeyUsage contained.
+ */
public static ExtendedKeyUsage getInstance(
ASN1TaggedObject obj,
boolean explicit)
@@ -32,6 +39,12 @@ public class ExtendedKeyUsage
return getInstance(ASN1Sequence.getInstance(obj, explicit));
}
+ /**
+ * Return an ExtendedKeyUsage from the passed in object.
+ *
+ * @param obj an ExtendedKeyUsage, some form or encoding of one, or null.
+ * @return an ExtendedKeyUsage object, or null if null is passed in.
+ */
public static ExtendedKeyUsage getInstance(
Object obj)
{
@@ -47,11 +60,22 @@ public class ExtendedKeyUsage
return null;
}
+ /**
+ * Retrieve an ExtendedKeyUsage for a passed in Extensions object, if present.
+ *
+ * @param extensions the extensions object to be examined.
+ * @return the ExtendedKeyUsage, null if the extension is not present.
+ */
public static ExtendedKeyUsage fromExtensions(Extensions extensions)
{
return ExtendedKeyUsage.getInstance(extensions.getExtensionParsedValue(Extension.extendedKeyUsage));
}
+ /**
+ * Base constructor, from a single KeyPurposeId.
+ *
+ * @param usage the keyPurposeId to be included.
+ */
public ExtendedKeyUsage(
KeyPurposeId usage)
{
@@ -78,6 +102,11 @@ public class ExtendedKeyUsage
}
}
+ /**
+ * Base constructor, from multiple KeyPurposeIds.
+ *
+ * @param usages an array of KeyPurposeIds.
+ */
public ExtendedKeyUsage(
KeyPurposeId[] usages)
{
@@ -103,7 +132,7 @@ public class ExtendedKeyUsage
while (e.hasMoreElements())
{
- ASN1Primitive o = (ASN1Primitive)e.nextElement();
+ KeyPurposeId o = KeyPurposeId.getInstance(e.nextElement());
v.add(o);
this.usageTable.put(o, o);
@@ -112,6 +141,12 @@ public class ExtendedKeyUsage
this.seq = new DERSequence(v);
}
+ /**
+ * Return true if this ExtendedKeyUsage object contains the passed in keyPurposeId.
+ *
+ * @param keyPurposeId the KeyPurposeId of interest.
+ * @return true if the keyPurposeId is present, false otherwise.
+ */
public boolean hasKeyPurposeId(
KeyPurposeId keyPurposeId)
{
@@ -120,7 +155,7 @@ public class ExtendedKeyUsage
/**
* Returns all extended key usages.
- * The returned vector contains DERObjectIdentifiers.
+ *
* @return An array with all key purposes.
*/
public KeyPurposeId[] getUsages()
@@ -135,11 +170,21 @@ public class ExtendedKeyUsage
return temp;
}
+ /**
+ * Return the number of KeyPurposeIds present in this ExtendedKeyUsage.
+ *
+ * @return the number of KeyPurposeIds
+ */
public int size()
{
return usageTable.size();
}
-
+
+ /**
+ * Return the ASN.1 primitive form of this object.
+ *
+ * @return an ASN1Sequence.
+ */
public ASN1Primitive toASN1Primitive()
{
return seq;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Holder.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Holder.java
index 6ae6e35..e854681 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Holder.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Holder.java
@@ -31,9 +31,9 @@ import org.bouncycastle.asn1.DERTaggedObject;
*
* <pre>
* subject CHOICE {
- * baseCertificateID [0] IssuerSerial,
+ * baseCertificateID [0] EXPLICIT IssuerSerial,
* -- associated with a Public Key Certificate
- * subjectName [1] GeneralNames },
+ * subjectName [1] EXPLICIT GeneralNames },
* -- associated with a name
* </pre>
*/
@@ -79,10 +79,10 @@ public class Holder
switch (tagObj.getTagNo())
{
case 0:
- baseCertificateID = IssuerSerial.getInstance(tagObj, false);
+ baseCertificateID = IssuerSerial.getInstance(tagObj, true);
break;
case 1:
- entityName = GeneralNames.getInstance(tagObj, false);
+ entityName = GeneralNames.getInstance(tagObj, true);
break;
default:
throw new IllegalArgumentException("unknown tag in Holder");
@@ -234,11 +234,11 @@ public class Holder
{
if (entityName != null)
{
- return new DERTaggedObject(false, 1, entityName);
+ return new DERTaggedObject(true, 1, entityName);
}
else
{
- return new DERTaggedObject(false, 0, baseCertificateID);
+ return new DERTaggedObject(true, 0, baseCertificateID);
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java
index 8d3036b..fefc939 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java
@@ -10,6 +10,7 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.x500.X500Name;
public class IssuerSerial
extends ASN1Object
@@ -59,6 +60,13 @@ public class IssuerSerial
}
public IssuerSerial(
+ X500Name issuer,
+ BigInteger serial)
+ {
+ this(new GeneralNames(new GeneralName(issuer)), new ASN1Integer(serial));
+ }
+
+ public IssuerSerial(
GeneralNames issuer,
BigInteger serial)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java
index 2943c0b..d4456b7 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java
@@ -74,6 +74,17 @@ public class KeyUsage
this.bitString = bitString;
}
+ /**
+ * Return true if a given usage bit is set, false otherwise.
+ *
+ * @param usages combination of usage flags.
+ * @return true if all bits are set, false otherwise.
+ */
+ public boolean hasUsages(int usages)
+ {
+ return (bitString.intValue() & usages) == usages;
+ }
+
public byte[] getBytes()
{
return bitString.getBytes();
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java
new file mode 100644
index 0000000..aeb53f0
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java
@@ -0,0 +1,106 @@
+package org.bouncycastle.asn1.x509;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1Object;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1TaggedObject;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * PKIX RFC 5280
+ * <pre>
+ * id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 }
+ *
+ * PolicyConstraints ::= SEQUENCE {
+ * requireExplicitPolicy [0] SkipCerts OPTIONAL,
+ * inhibitPolicyMapping [1] SkipCerts OPTIONAL }
+ *
+ * SkipCerts ::= INTEGER (0..MAX)
+ * </pre>
+ */
+public class PolicyConstraints
+ extends ASN1Object
+{
+ private BigInteger requireExplicitPolicyMapping;
+ private BigInteger inhibitPolicyMapping;
+
+ public PolicyConstraints(BigInteger requireExplicitPolicyMapping, BigInteger inhibitPolicyMapping)
+ {
+ this.requireExplicitPolicyMapping = requireExplicitPolicyMapping;
+ this.inhibitPolicyMapping = inhibitPolicyMapping;
+ }
+
+ private PolicyConstraints(ASN1Sequence seq)
+ {
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject to = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
+
+ if (to.getTagNo() == 0)
+ {
+ requireExplicitPolicyMapping = ASN1Integer.getInstance(to, false).getValue();
+ }
+ else if (to.getTagNo() == 1)
+ {
+ inhibitPolicyMapping = ASN1Integer.getInstance(to, false).getValue();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Unknown tag encountered.");
+ }
+ }
+ }
+
+ public static PolicyConstraints getInstance(
+ Object obj)
+ {
+ if (obj instanceof PolicyConstraints)
+ {
+ return (PolicyConstraints)obj;
+ }
+
+ if (obj != null)
+ {
+ return new PolicyConstraints(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static PolicyConstraints fromExtensions(Extensions extensions)
+ {
+ return PolicyConstraints.getInstance(extensions.getExtensionParsedValue(Extension.policyConstraints));
+ }
+
+ public BigInteger getRequireExplicitPolicyMapping()
+ {
+ return requireExplicitPolicyMapping;
+ }
+
+ public BigInteger getInhibitPolicyMapping()
+ {
+ return inhibitPolicyMapping;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (requireExplicitPolicyMapping != null)
+ {
+ v.add(new DERTaggedObject(0, new ASN1Integer(requireExplicitPolicyMapping)));
+ }
+
+ if (inhibitPolicyMapping != null)
+ {
+ v.add(new DERTaggedObject(1, new ASN1Integer(inhibitPolicyMapping)));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java
index f020bcb..f29284d 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java
@@ -10,6 +10,7 @@ import org.bouncycastle.asn1.DERBoolean;
/**
* an object for the elements in the X.509 V3 extension block.
+ * @deprecated use Extension
*/
public class X509Extension
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Name.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Name.java
index 9aed4e1..0c372f7 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Name.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Name.java
@@ -1242,49 +1242,47 @@ public class X509Name
buf.append('=');
- int index = buf.length();
- int start = index;
-
+ int start = buf.length();
buf.append(value);
-
- int end = buf.length();
+ int end = buf.length();
if (value.length() >= 2 && value.charAt(0) == '\\' && value.charAt(1) == '#')
{
- index += 2;
- }
-
- while (index != end)
- {
- if ((buf.charAt(index) == ',')
- || (buf.charAt(index) == '"')
- || (buf.charAt(index) == '\\')
- || (buf.charAt(index) == '+')
- || (buf.charAt(index) == '=')
- || (buf.charAt(index) == '<')
- || (buf.charAt(index) == '>')
- || (buf.charAt(index) == ';'))
- {
- buf.insert(index, "\\");
- index++;
- end++;
- }
-
- index++;
+ start += 2;
}
- while (buf.charAt(start) == ' ')
+ while (start < end && buf.charAt(start) == ' ')
{
buf.insert(start, "\\");
start += 2;
+ ++end;
}
- int endBuf = buf.length() - 1;
+ while (--end > start && buf.charAt(end) == ' ')
+ {
+ buf.insert(end, '\\');
+ }
- while (endBuf >= 0 && buf.charAt(endBuf) == ' ')
+ while (start <= end)
{
- buf.insert(endBuf, '\\');
- endBuf--;
+ switch (buf.charAt(start))
+ {
+ case ',':
+ case '"':
+ case '\\':
+ case '+':
+ case '=':
+ case '<':
+ case '>':
+ case ';':
+ buf.insert(start, "\\");
+ start += 2;
+ ++end;
+ break;
+ default:
+ ++start;
+ break;
+ }
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java
index ed4dd32..e1c7a54 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java
@@ -4,64 +4,78 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
public interface X509ObjectIdentifiers
{
- //
- // base id
- //
- static final String id = "2.5.4";
-
- static final ASN1ObjectIdentifier commonName = new ASN1ObjectIdentifier(id + ".3");
- static final ASN1ObjectIdentifier countryName = new ASN1ObjectIdentifier(id + ".6");
- static final ASN1ObjectIdentifier localityName = new ASN1ObjectIdentifier(id + ".7");
- static final ASN1ObjectIdentifier stateOrProvinceName = new ASN1ObjectIdentifier(id + ".8");
- static final ASN1ObjectIdentifier organization = new ASN1ObjectIdentifier(id + ".10");
- static final ASN1ObjectIdentifier organizationalUnitName = new ASN1ObjectIdentifier(id + ".11");
+
+ /** Subject RDN components: commonName = 2.5.4.3 */
+ static final ASN1ObjectIdentifier commonName = new ASN1ObjectIdentifier("2.5.4.3");
+ /** Subject RDN components: countryName = 2.5.4.6 */
+ static final ASN1ObjectIdentifier countryName = new ASN1ObjectIdentifier("2.5.4.6");
+ /** Subject RDN components: localityName = 2.5.4.7 */
+ static final ASN1ObjectIdentifier localityName = new ASN1ObjectIdentifier("2.5.4.7");
+ /** Subject RDN components: stateOrProvinceName = 2.5.4.8 */
+ static final ASN1ObjectIdentifier stateOrProvinceName = new ASN1ObjectIdentifier("2.5.4.8");
+ /** Subject RDN components: organization = 2.5.4.10 */
+ static final ASN1ObjectIdentifier organization = new ASN1ObjectIdentifier("2.5.4.10");
+ /** Subject RDN components: organizationalUnitName = 2.5.4.11 */
+ static final ASN1ObjectIdentifier organizationalUnitName = new ASN1ObjectIdentifier("2.5.4.11");
+ /** Subject RDN components: telephone_number = 2.5.4.20 */
static final ASN1ObjectIdentifier id_at_telephoneNumber = new ASN1ObjectIdentifier("2.5.4.20");
- static final ASN1ObjectIdentifier id_at_name = new ASN1ObjectIdentifier(id + ".41");
+ /** Subject RDN components: name = 2.5.4.41 */
+ static final ASN1ObjectIdentifier id_at_name = new ASN1ObjectIdentifier("2.5.4.41");
- // id-SHA1 OBJECT IDENTIFIER ::=
- // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } //
+ /**
+ * id-SHA1 OBJECT IDENTIFIER ::=
+ * {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 }
+ * <p>
+ * OID: 1.3.14.3.2.27
+ */
static final ASN1ObjectIdentifier id_SHA1 = new ASN1ObjectIdentifier("1.3.14.3.2.26");
- //
- // ripemd160 OBJECT IDENTIFIER ::=
- // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) hashAlgorithm(2) RIPEMD-160(1)}
- //
+ /**
+ * ripemd160 OBJECT IDENTIFIER ::=
+ * {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) hashAlgorithm(2) RIPEMD-160(1)}
+ * <p>
+ * OID: 1.3.36.3.2.1
+ */
static final ASN1ObjectIdentifier ripemd160 = new ASN1ObjectIdentifier("1.3.36.3.2.1");
- //
- // ripemd160WithRSAEncryption OBJECT IDENTIFIER ::=
- // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) signatureAlgorithm(3) rsaSignature(1) rsaSignatureWithripemd160(2) }
- //
+ /**
+ * ripemd160WithRSAEncryption OBJECT IDENTIFIER ::=
+ * {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) signatureAlgorithm(3) rsaSignature(1) rsaSignatureWithripemd160(2) }
+ * <p>
+ * OID: 1.3.36.3.3.1.2
+ */
static final ASN1ObjectIdentifier ripemd160WithRSAEncryption = new ASN1ObjectIdentifier("1.3.36.3.3.1.2");
+ /** OID: 2.5.8.1.1 */
static final ASN1ObjectIdentifier id_ea_rsa = new ASN1ObjectIdentifier("2.5.8.1.1");
- // id-pkix
- static final ASN1ObjectIdentifier id_pkix = new ASN1ObjectIdentifier("1.3.6.1.5.5.7");
+ /** id-pkix OID: 1.3.6.1.5.5.7
+ */
+ static final ASN1ObjectIdentifier id_pkix = new ASN1ObjectIdentifier("1.3.6.1.5.5.7");
- //
- // private internet extensions
- //
- static final ASN1ObjectIdentifier id_pe = new ASN1ObjectIdentifier(id_pkix + ".1");
+ /**
+ * private internet extensions; OID = 1.3.6.1.5.5.7.1
+ */
+ static final ASN1ObjectIdentifier id_pe = id_pkix.branch("1");
- //
- // ISO ARC for standard certificate and CRL extensions
- //
+ /**
+ * ISO ARC for standard certificate and CRL extensions
+ * <p>
+ * OID: 2.5.29
+ */
static final ASN1ObjectIdentifier id_ce = new ASN1ObjectIdentifier("2.5.29");
- //
- // authority information access
- //
- static final ASN1ObjectIdentifier id_ad = new ASN1ObjectIdentifier(id_pkix + ".48");
- static final ASN1ObjectIdentifier id_ad_caIssuers = new ASN1ObjectIdentifier(id_ad + ".2");
- static final ASN1ObjectIdentifier id_ad_ocsp = new ASN1ObjectIdentifier(id_ad + ".1");
+ /** id-pkix OID: 1.3.6.1.5.5.7.48 */
+ static final ASN1ObjectIdentifier id_ad = id_pkix.branch("48");
+ /** id-ad-caIssuers OID: 1.3.6.1.5.5.7.48.2 */
+ static final ASN1ObjectIdentifier id_ad_caIssuers = id_ad.branch("2");
+ /** id-ad-ocsp OID: 1.3.6.1.5.5.7.48.1 */
+ static final ASN1ObjectIdentifier id_ad_ocsp = id_ad.branch("1");
- //
- // OID for ocsp and crl uri in AuthorityInformationAccess extension
- //
+ /** OID for ocsp uri in AuthorityInformationAccess extension */
static final ASN1ObjectIdentifier ocspAccessMethod = id_ad_ocsp;
- static final ASN1ObjectIdentifier crlAccessMethod = id_ad_caIssuers;
+ /** OID for crl uri in AuthorityInformationAccess extension */
+ static final ASN1ObjectIdentifier crlAccessMethod = id_ad_caIssuers;
}
-
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
new file mode 100644
index 0000000..fef664f
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
@@ -0,0 +1,107 @@
+package org.bouncycastle.asn1.x9;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.nist.NISTNamedCurves;
+import org.bouncycastle.asn1.sec.SECNamedCurves;
+// BEGIN android-removed
+// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
+// END android-removed
+
+/**
+ * A general class that reads all X9.62 style EC curve tables.
+ */
+public class ECNamedCurveTable
+{
+ /**
+ * return a X9ECParameters object representing the passed in named
+ * curve. The routine returns null if the curve is not present.
+ *
+ * @param name the name of the curve requested
+ * @return an X9ECParameters object or null if the curve is not available.
+ */
+ public static X9ECParameters getByName(
+ String name)
+ {
+ X9ECParameters ecP = X962NamedCurves.getByName(name);
+
+ if (ecP == null)
+ {
+ ecP = SECNamedCurves.getByName(name);
+ }
+
+ // BEGIN android-removed
+ // if (ecP == null)
+ // {
+ // ecP = TeleTrusTNamedCurves.getByName(name);
+ // }
+ // END android-removed
+
+ if (ecP == null)
+ {
+ ecP = NISTNamedCurves.getByName(name);
+ }
+
+ return ecP;
+ }
+
+ /**
+ * return a X9ECParameters object representing the passed in named
+ * curve.
+ *
+ * @param oid the object id of the curve requested
+ * @return an X9ECParameters object or null if the curve is not available.
+ */
+ public static X9ECParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ X9ECParameters ecP = X962NamedCurves.getByOID(oid);
+
+ if (ecP == null)
+ {
+ ecP = SECNamedCurves.getByOID(oid);
+ }
+
+ // BEGIN android-removed
+ // if (ecP == null)
+ // {
+ // ecP = TeleTrusTNamedCurves.getByOID(oid);
+ // }
+ // END android-removed
+
+ // NOTE: All the NIST curves are currently from SEC, so no point in redundant OID lookup
+
+ return ecP;
+ }
+
+ /**
+ * return an enumeration of the names of the available curves.
+ *
+ * @return an enumeration of the names of the available curves.
+ */
+ public static Enumeration getNames()
+ {
+ Vector v = new Vector();
+
+ addEnumeration(v, X962NamedCurves.getNames());
+ addEnumeration(v, SECNamedCurves.getNames());
+ addEnumeration(v, NISTNamedCurves.getNames());
+ // BEGIN android-removed
+ // addEnumeration(v, TeleTrusTNamedCurves.getNames());
+ // END android-removed
+
+ return v.elements();
+ }
+
+ private static void addEnumeration(
+ Vector v,
+ Enumeration e)
+ {
+ while (e.hasMoreElements())
+ {
+ v.addElement(e.nextElement());
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java
index e059089..60f9008 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java
@@ -39,11 +39,21 @@ public class X9ECParameters
}
X9Curve x9c = new X9Curve(
- new X9FieldID((ASN1Sequence)seq.getObjectAt(1)),
- (ASN1Sequence)seq.getObjectAt(2));
+ X9FieldID.getInstance(seq.getObjectAt(1)),
+ ASN1Sequence.getInstance(seq.getObjectAt(2)));
this.curve = x9c.getCurve();
- this.g = new X9ECPoint(curve, (ASN1OctetString)seq.getObjectAt(3)).getPoint();
+ Object p = seq.getObjectAt(3);
+
+ if (p instanceof X9ECPoint)
+ {
+ this.g = ((X9ECPoint)p).getPoint();
+ }
+ else
+ {
+ this.g = new X9ECPoint(curve, (ASN1OctetString)p).getPoint();
+ }
+
this.n = ((ASN1Integer)seq.getObjectAt(4)).getValue();
this.seed = x9c.getSeed();
@@ -93,7 +103,7 @@ public class X9ECParameters
byte[] seed)
{
this.curve = curve;
- this.g = g;
+ this.g = g.normalize();
this.n = n;
this.h = h;
this.seed = seed;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java
index a4acb6e..cbb9116 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java
@@ -18,7 +18,7 @@ public class X9ECPoint
public X9ECPoint(
ECPoint p)
{
- this.p = p;
+ this.p = p.normalize();
}
public X9ECPoint(
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java
index 30598e2..a210352 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java
@@ -71,11 +71,26 @@ public class X9FieldID
this.parameters = new DERSequence(fieldIdParams);
}
- public X9FieldID(
+ private X9FieldID(
ASN1Sequence seq)
{
- this.id = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- this.parameters = (ASN1Primitive)seq.getObjectAt(1);
+ this.id = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ this.parameters = seq.getObjectAt(1).toASN1Primitive();
+ }
+
+ public static X9FieldID getInstance(Object obj)
+ {
+ if (obj instanceof X9FieldID)
+ {
+ return (X9FieldID)obj;
+ }
+
+ if (obj != null)
+ {
+ return new X9FieldID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
}
public ASN1ObjectIdentifier getIdentifier()
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
index f005cfa..eabf90e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
@@ -2,109 +2,172 @@ package org.bouncycastle.asn1.x9;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ *
+ * X9.62
+ * <pre>
+ * ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ * us(840) ansi-x962(10045) }
+ * </pre>
+ */
public interface X9ObjectIdentifiers
{
- //
- // X9.62
- //
- // ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- // us(840) ansi-x962(10045) }
- //
+ /** Base OID: 1.2.840.10045 */
static final ASN1ObjectIdentifier ansi_X9_62 = new ASN1ObjectIdentifier("1.2.840.10045");
+
+ /** OID: 1.2.840.10045.1 */
static final ASN1ObjectIdentifier id_fieldType = ansi_X9_62.branch("1");
+ /** OID: 1.2.840.10045.1.1 */
static final ASN1ObjectIdentifier prime_field = id_fieldType.branch("1");
+ /** OID: 1.2.840.10045.1.2 */
static final ASN1ObjectIdentifier characteristic_two_field = id_fieldType.branch("2");
+ /** OID: 1.2.840.10045.1.2.3.1 */
static final ASN1ObjectIdentifier gnBasis = characteristic_two_field.branch("3.1");
+ /** OID: 1.2.840.10045.1.2.3.2 */
static final ASN1ObjectIdentifier tpBasis = characteristic_two_field.branch("3.2");
+ /** OID: 1.2.840.10045.1.2.3.3 */
static final ASN1ObjectIdentifier ppBasis = characteristic_two_field.branch("3.3");
+ /** OID: 1.2.840.10045.4 */
static final ASN1ObjectIdentifier id_ecSigType = ansi_X9_62.branch("4");
- static final ASN1ObjectIdentifier ecdsa_with_SHA1 = new ASN1ObjectIdentifier(id_ecSigType + ".1");
+ /** OID: 1.2.840.10045.4.1 */
+ static final ASN1ObjectIdentifier ecdsa_with_SHA1 = id_ecSigType.branch("1");
+ /** OID: 1.2.840.10045.2 */
static final ASN1ObjectIdentifier id_publicKeyType = ansi_X9_62.branch("2");
+ /** OID: 1.2.840.10045.2.1 */
static final ASN1ObjectIdentifier id_ecPublicKey = id_publicKeyType.branch("1");
+ /** OID: 1.2.840.10045.4.3 */
static final ASN1ObjectIdentifier ecdsa_with_SHA2 = id_ecSigType.branch("3");
+ /** OID: 1.2.840.10045.4.3.1 */
static final ASN1ObjectIdentifier ecdsa_with_SHA224 = ecdsa_with_SHA2.branch("1");
+ /** OID: 1.2.840.10045.4.3.2 */
static final ASN1ObjectIdentifier ecdsa_with_SHA256 = ecdsa_with_SHA2.branch("2");
+ /** OID: 1.2.840.10045.4.3.3 */
static final ASN1ObjectIdentifier ecdsa_with_SHA384 = ecdsa_with_SHA2.branch("3");
+ /** OID: 1.2.840.10045.4.3.4 */
static final ASN1ObjectIdentifier ecdsa_with_SHA512 = ecdsa_with_SHA2.branch("4");
- //
- // named curves
- //
+ /**
+ * Named curves base
+ * <p>
+ * OID: 1.2.840.10045.1
+ */
static final ASN1ObjectIdentifier ellipticCurve = ansi_X9_62.branch("3");
- //
- // Two Curves
- //
+ /**
+ * Two Curves
+ * <p>
+ * OID: 1.2.840.10045.1.0
+ */
static final ASN1ObjectIdentifier cTwoCurve = ellipticCurve.branch("0");
+ /** Two Curve c2pnb163v1, OID: 1.2.840.10045.1.0.1 */
static final ASN1ObjectIdentifier c2pnb163v1 = cTwoCurve.branch("1");
+ /** Two Curve c2pnb163v2, OID: 1.2.840.10045.1.0.2 */
static final ASN1ObjectIdentifier c2pnb163v2 = cTwoCurve.branch("2");
+ /** Two Curve c2pnb163v3, OID: 1.2.840.10045.1.0.3 */
static final ASN1ObjectIdentifier c2pnb163v3 = cTwoCurve.branch("3");
+ /** Two Curve c2pnb176w1, OID: 1.2.840.10045.1.0.4 */
static final ASN1ObjectIdentifier c2pnb176w1 = cTwoCurve.branch("4");
+ /** Two Curve c2tnb191v1, OID: 1.2.840.10045.1.0.5 */
static final ASN1ObjectIdentifier c2tnb191v1 = cTwoCurve.branch("5");
+ /** Two Curve c2tnb191v2, OID: 1.2.840.10045.1.0.6 */
static final ASN1ObjectIdentifier c2tnb191v2 = cTwoCurve.branch("6");
+ /** Two Curve c2tnb191v3, OID: 1.2.840.10045.1.0.7 */
static final ASN1ObjectIdentifier c2tnb191v3 = cTwoCurve.branch("7");
+ /** Two Curve c2onb191v4, OID: 1.2.840.10045.1.0.8 */
static final ASN1ObjectIdentifier c2onb191v4 = cTwoCurve.branch("8");
+ /** Two Curve c2onb191v5, OID: 1.2.840.10045.1.0.9 */
static final ASN1ObjectIdentifier c2onb191v5 = cTwoCurve.branch("9");
+ /** Two Curve c2pnb208w1, OID: 1.2.840.10045.1.0.10 */
static final ASN1ObjectIdentifier c2pnb208w1 = cTwoCurve.branch("10");
+ /** Two Curve c2tnb239v1, OID: 1.2.840.10045.1.0.11 */
static final ASN1ObjectIdentifier c2tnb239v1 = cTwoCurve.branch("11");
+ /** Two Curve c2tnb239v2, OID: 1.2.840.10045.1.0.12 */
static final ASN1ObjectIdentifier c2tnb239v2 = cTwoCurve.branch("12");
+ /** Two Curve c2tnb239v3, OID: 1.2.840.10045.1.0.13 */
static final ASN1ObjectIdentifier c2tnb239v3 = cTwoCurve.branch("13");
+ /** Two Curve c2onb239v4, OID: 1.2.840.10045.1.0.14 */
static final ASN1ObjectIdentifier c2onb239v4 = cTwoCurve.branch("14");
+ /** Two Curve c2onb239v5, OID: 1.2.840.10045.1.0.15 */
static final ASN1ObjectIdentifier c2onb239v5 = cTwoCurve.branch("15");
+ /** Two Curve c2pnb272w1, OID: 1.2.840.10045.1.0.16 */
static final ASN1ObjectIdentifier c2pnb272w1 = cTwoCurve.branch("16");
+ /** Two Curve c2pnb304w1, OID: 1.2.840.10045.1.0.17 */
static final ASN1ObjectIdentifier c2pnb304w1 = cTwoCurve.branch("17");
+ /** Two Curve c2tnb359v1, OID: 1.2.840.10045.1.0.18 */
static final ASN1ObjectIdentifier c2tnb359v1 = cTwoCurve.branch("18");
+ /** Two Curve c2pnb368w1, OID: 1.2.840.10045.1.0.19 */
static final ASN1ObjectIdentifier c2pnb368w1 = cTwoCurve.branch("19");
+ /** Two Curve c2tnb431r1, OID: 1.2.840.10045.1.0.20 */
static final ASN1ObjectIdentifier c2tnb431r1 = cTwoCurve.branch("20");
- //
- // Prime
- //
+ /**
+ * Prime Curves
+ * <p>
+ * OID: 1.2.840.10045.1.1
+ */
static final ASN1ObjectIdentifier primeCurve = ellipticCurve.branch("1");
+ /** Prime Curve prime192v1, OID: 1.2.840.10045.1.1.1 */
static final ASN1ObjectIdentifier prime192v1 = primeCurve.branch("1");
+ /** Prime Curve prime192v2, OID: 1.2.840.10045.1.1.2 */
static final ASN1ObjectIdentifier prime192v2 = primeCurve.branch("2");
+ /** Prime Curve prime192v3, OID: 1.2.840.10045.1.1.3 */
static final ASN1ObjectIdentifier prime192v3 = primeCurve.branch("3");
+ /** Prime Curve prime239v1, OID: 1.2.840.10045.1.1.4 */
static final ASN1ObjectIdentifier prime239v1 = primeCurve.branch("4");
+ /** Prime Curve prime239v2, OID: 1.2.840.10045.1.1.5 */
static final ASN1ObjectIdentifier prime239v2 = primeCurve.branch("5");
+ /** Prime Curve prime239v3, OID: 1.2.840.10045.1.1.6 */
static final ASN1ObjectIdentifier prime239v3 = primeCurve.branch("6");
+ /** Prime Curve prime256v1, OID: 1.2.840.10045.1.1.7 */
static final ASN1ObjectIdentifier prime256v1 = primeCurve.branch("7");
- //
- // DSA
- //
- // dsapublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- // us(840) ansi-x957(10040) number-type(4) 1 }
+ /**
+ * DSA
+ * <pre>
+ * dsapublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ * us(840) ansi-x957(10040) number-type(4) 1 }
+ * </pre>
+ * Base OID: 1.2.840.10040.4.1
+ */
static final ASN1ObjectIdentifier id_dsa = new ASN1ObjectIdentifier("1.2.840.10040.4.1");
/**
- * id-dsa-with-sha1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) x9-57
- * (10040) x9cm(4) 3 }
+ * <pre>
+ * id-dsa-with-sha1 OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 }
+ * </pre>
+ * OID: 1.2.840.10040.4.3
*/
- public static final ASN1ObjectIdentifier id_dsa_with_sha1 = new ASN1ObjectIdentifier("1.2.840.10040.4.3");
+ static final ASN1ObjectIdentifier id_dsa_with_sha1 = new ASN1ObjectIdentifier("1.2.840.10040.4.3");
/**
- * X9.63
+ * X9.63 - Signature Specification
+ * <p>
+ * Base OID: 1.3.133.16.840.63.0
*/
- public static final ASN1ObjectIdentifier x9_63_scheme = new ASN1ObjectIdentifier("1.3.133.16.840.63.0");
- public static final ASN1ObjectIdentifier dhSinglePass_stdDH_sha1kdf_scheme = x9_63_scheme.branch("2");
- public static final ASN1ObjectIdentifier dhSinglePass_cofactorDH_sha1kdf_scheme = x9_63_scheme.branch("3");
- public static final ASN1ObjectIdentifier mqvSinglePass_sha1kdf_scheme = x9_63_scheme.branch("16");
+ static final ASN1ObjectIdentifier x9_63_scheme = new ASN1ObjectIdentifier("1.3.133.16.840.63.0");
+ /** OID: 1.3.133.16.840.63.0.2 */
+ static final ASN1ObjectIdentifier dhSinglePass_stdDH_sha1kdf_scheme = x9_63_scheme.branch("2");
+ /** OID: 1.3.133.16.840.63.0.3 */
+ static final ASN1ObjectIdentifier dhSinglePass_cofactorDH_sha1kdf_scheme = x9_63_scheme.branch("3");
+ /** OID: 1.3.133.16.840.63.0.16 */
+ static final ASN1ObjectIdentifier mqvSinglePass_sha1kdf_scheme = x9_63_scheme.branch("16");
/**
* X9.42
@@ -112,21 +175,33 @@ public interface X9ObjectIdentifiers
static final ASN1ObjectIdentifier ansi_X9_42 = new ASN1ObjectIdentifier("1.2.840.10046");
- //
- // Diffie-Hellman
- //
- // dhpublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- // us(840) ansi-x942(10046) number-type(2) 1 }
- //
- public static final ASN1ObjectIdentifier dhpublicnumber = ansi_X9_42.branch("2.1");
-
- public static final ASN1ObjectIdentifier x9_42_schemes = ansi_X9_42.branch("3");
- public static final ASN1ObjectIdentifier dhStatic = x9_42_schemes.branch("1");
- public static final ASN1ObjectIdentifier dhEphem = x9_42_schemes.branch("2");
- public static final ASN1ObjectIdentifier dhOneFlow = x9_42_schemes.branch("3");
- public static final ASN1ObjectIdentifier dhHybrid1 = x9_42_schemes.branch("4");
- public static final ASN1ObjectIdentifier dhHybrid2 = x9_42_schemes.branch("5");
- public static final ASN1ObjectIdentifier dhHybridOneFlow = x9_42_schemes.branch("6");
- public static final ASN1ObjectIdentifier mqv2 = x9_42_schemes.branch("7");
- public static final ASN1ObjectIdentifier mqv1 = x9_42_schemes.branch("8");
+ /**
+ * Diffie-Hellman
+ * <pre>
+ * dhpublicnumber OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) ansi-x942(10046) number-type(2) 1
+ * }
+ * </pre>
+ * OID: 1.2.840.10046.2.1
+ */
+ static final ASN1ObjectIdentifier dhpublicnumber = ansi_X9_42.branch("2.1");
+
+ /** X9.42 schemas base OID: 1.2.840.10046.3 */
+ static final ASN1ObjectIdentifier x9_42_schemes = ansi_X9_42.branch("3");
+ /** X9.42 dhStatic OID: 1.2.840.10046.3.1 */
+ static final ASN1ObjectIdentifier dhStatic = x9_42_schemes.branch("1");
+ /** X9.42 dhEphem OID: 1.2.840.10046.3.2 */
+ static final ASN1ObjectIdentifier dhEphem = x9_42_schemes.branch("2");
+ /** X9.42 dhOneFlow OID: 1.2.840.10046.3.3 */
+ static final ASN1ObjectIdentifier dhOneFlow = x9_42_schemes.branch("3");
+ /** X9.42 dhHybrid1 OID: 1.2.840.10046.3.4 */
+ static final ASN1ObjectIdentifier dhHybrid1 = x9_42_schemes.branch("4");
+ /** X9.42 dhHybrid2 OID: 1.2.840.10046.3.5 */
+ static final ASN1ObjectIdentifier dhHybrid2 = x9_42_schemes.branch("5");
+ /** X9.42 dhHybridOneFlow OID: 1.2.840.10046.3.6 */
+ static final ASN1ObjectIdentifier dhHybridOneFlow = x9_42_schemes.branch("6");
+ /** X9.42 MQV2 OID: 1.2.840.10046.3.7 */
+ static final ASN1ObjectIdentifier mqv2 = x9_42_schemes.branch("7");
+ /** X9.42 MQV1 OID: 1.2.840.10046.3.8 */
+ static final ASN1ObjectIdentifier mqv1 = x9_42_schemes.branch("8");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
index bdb694d..dd056ac 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
@@ -54,7 +54,7 @@ public class BufferedBlockCipher
}
else
{
- partialBlockOkay = (idx > 0 && (name.startsWith("CFB", idx) || name.startsWith("OFB", idx) || name.startsWith("OpenPGP", idx) || name.startsWith("SIC", idx) || name.startsWith("GCTR", idx)));
+ partialBlockOkay = (idx > 0 && (name.startsWith("CFB", idx) || name.startsWith("GCFB", idx) ||name.startsWith("OFB", idx) || name.startsWith("OpenPGP", idx) || name.startsWith("SIC", idx) || name.startsWith("GCTR", idx)));
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/DerivationFunction.java b/bcprov/src/main/java/org/bouncycastle/crypto/DerivationFunction.java
index ef6e29e..0e2b4b0 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/DerivationFunction.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/DerivationFunction.java
@@ -7,11 +7,6 @@ public interface DerivationFunction
{
public void init(DerivationParameters param);
- /**
- * return the message digest used as the basis for the function
- */
- public Digest getDigest();
-
public int generateBytes(byte[] out, int outOff, int len)
throws DataLengthException, IllegalArgumentException;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
index 59944e0..a491b9d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
@@ -42,10 +42,13 @@ public class ECDHBasicAgreement
CipherParameters pubKey)
{
ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
- ECPoint P = pub.getQ().multiply(key.getD());
+ ECPoint P = pub.getQ().multiply(key.getD()).normalize();
- // if (p.isInfinity()) throw new RuntimeException("d*Q == infinity");
+ if (P.isInfinity())
+ {
+ throw new IllegalStateException("Infinity is not a valid agreement value for ECDH");
+ }
- return P.getX().toBigInteger();
+ return P.getAffineXCoord().toBigInteger();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
index 540bd25..cfd86fb 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
@@ -85,7 +85,7 @@ public class RFC3394WrapEngine
byte[] buf = new byte[8 + iv.length];
System.arraycopy(iv, 0, block, 0, iv.length);
- System.arraycopy(in, 0, block, iv.length, inLen);
+ System.arraycopy(in, inOff, block, iv.length, inLen);
engine.init(true, param);
@@ -137,8 +137,8 @@ public class RFC3394WrapEngine
byte[] a = new byte[iv.length];
byte[] buf = new byte[8 + iv.length];
- System.arraycopy(in, 0, a, 0, iv.length);
- System.arraycopy(in, iv.length, block, 0, inLen - iv.length);
+ System.arraycopy(in, inOff, a, 0, iv.length);
+ System.arraycopy(in, inOff + iv.length, block, 0, inLen - iv.length);
engine.init(false, param);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java
index e7fb943..c9765bf 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java
@@ -1,5 +1,8 @@
package org.bouncycastle.crypto.engines;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
@@ -8,16 +11,13 @@ import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.util.BigIntegers;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
/**
* this does your basic RSA algorithm with blinding
*/
public class RSABlindedEngine
implements AsymmetricBlockCipher
{
- private static BigInteger ONE = BigInteger.valueOf(1);
+ private static final BigInteger ONE = BigInteger.valueOf(1);
private RSACoreEngine core = new RSACoreEngine();
private RSAKeyParameters key;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
index 50baa4d..d70ee8f 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
@@ -232,10 +232,10 @@ public class DSAParametersGenerator
int seedlen = N;
byte[] seed = new byte[seedlen / 8];
-// 3. n = ceiling(L ⁄ outlen) – 1.
+// 3. n = ceiling(L / outlen) - 1.
int n = (L - 1) / outlen;
-// 4. b = L – 1 – (n ∗ outlen).
+// 4. b = L - 1 - (n * outlen).
int b = (L - 1) % outlen;
byte[] output = new byte[d.getDigestSize()];
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
index d77bd74..d5f5fc8 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
@@ -26,6 +26,11 @@ public class ECKeyPairGenerator
this.random = ecP.getRandom();
this.params = ecP.getDomainParameters();
+
+ if (this.random == null)
+ {
+ this.random = new SecureRandom();
+ }
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
index 316de64..082a1c8 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
@@ -62,7 +62,7 @@ public class PKCS5S2ParametersGenerator
hMac.doFinal(state, 0);
System.arraycopy(state, 0, out, outOff, state.length);
-
+
for (int count = 1; count < c; count++)
{
hMac.update(state, 0, state.length);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherInputStream.java b/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherInputStream.java
deleted file mode 100644
index bb09a76..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherInputStream.java
+++ /dev/null
@@ -1,244 +0,0 @@
-package org.bouncycastle.crypto.io;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.StreamCipher;
-
-/**
- * A CipherInputStream is composed of an InputStream and a BufferedBlockCipher so
- * that read() methods return data that are read in from the
- * underlying InputStream but have been additionally processed by the
- * Cipher. The Cipher must be fully initialized before being used by
- * a CipherInputStream.
- * <p>
- * For example, if the Cipher is initialized for decryption, the
- * CipherInputStream will attempt to read in data and decrypt them,
- * before returning the decrypted data.
- */
-public class CipherInputStream
- extends FilterInputStream
-{
- private BufferedBlockCipher bufferedBlockCipher;
- private StreamCipher streamCipher;
-
- private byte[] buf;
- private byte[] inBuf;
-
- private int bufOff;
- private int maxBuf;
- private boolean finalized;
-
- private static final int INPUT_BUF_SIZE = 2048;
-
- /**
- * Constructs a CipherInputStream from an InputStream and a
- * BufferedBlockCipher.
- */
- public CipherInputStream(
- InputStream is,
- BufferedBlockCipher cipher)
- {
- super(is);
-
- this.bufferedBlockCipher = cipher;
-
- buf = new byte[cipher.getOutputSize(INPUT_BUF_SIZE)];
- inBuf = new byte[INPUT_BUF_SIZE];
- }
-
- public CipherInputStream(
- InputStream is,
- StreamCipher cipher)
- {
- super(is);
-
- this.streamCipher = cipher;
-
- buf = new byte[INPUT_BUF_SIZE];
- inBuf = new byte[INPUT_BUF_SIZE];
- }
-
- /**
- * grab the next chunk of input from the underlying input stream
- */
- private int nextChunk()
- throws IOException
- {
- int available = super.available();
-
- // must always try to read 1 byte!
- // some buggy InputStreams return < 0!
- if (available <= 0)
- {
- available = 1;
- }
-
- if (available > inBuf.length)
- {
- available = super.read(inBuf, 0, inBuf.length);
- }
- else
- {
- available = super.read(inBuf, 0, available);
- }
-
- if (available < 0)
- {
- if (finalized)
- {
- return -1;
- }
-
- try
- {
- if (bufferedBlockCipher != null)
- {
- maxBuf = bufferedBlockCipher.doFinal(buf, 0);
- }
- else
- {
- maxBuf = 0; // a stream cipher
- }
- }
- catch (Exception e)
- {
- throw new IOException("error processing stream: " + e.toString());
- }
-
- bufOff = 0;
-
- finalized = true;
-
- if (bufOff == maxBuf)
- {
- return -1;
- }
- }
- else
- {
- bufOff = 0;
-
- try
- {
- if (bufferedBlockCipher != null)
- {
- maxBuf = bufferedBlockCipher.processBytes(inBuf, 0, available, buf, 0);
- }
- else
- {
- streamCipher.processBytes(inBuf, 0, available, buf, 0);
- maxBuf = available;
- }
- }
- catch (Exception e)
- {
- throw new IOException("error processing stream: " + e.toString());
- }
-
- if (maxBuf == 0) // not enough bytes read for first block...
- {
- return nextChunk();
- }
- }
-
- return maxBuf;
- }
-
- public int read()
- throws IOException
- {
- if (bufOff == maxBuf)
- {
- if (nextChunk() < 0)
- {
- return -1;
- }
- }
-
- return buf[bufOff++] & 0xff;
- }
-
- public int read(
- byte[] b)
- throws IOException
- {
- return read(b, 0, b.length);
- }
-
- public int read(
- byte[] b,
- int off,
- int len)
- throws IOException
- {
- if (bufOff == maxBuf)
- {
- if (nextChunk() < 0)
- {
- return -1;
- }
- }
-
- int available = maxBuf - bufOff;
-
- if (len > available)
- {
- System.arraycopy(buf, bufOff, b, off, available);
- bufOff = maxBuf;
-
- return available;
- }
- else
- {
- System.arraycopy(buf, bufOff, b, off, len);
- bufOff += len;
-
- return len;
- }
- }
-
- public long skip(
- long n)
- throws IOException
- {
- if (n <= 0)
- {
- return 0;
- }
-
- int available = maxBuf - bufOff;
-
- if (n > available)
- {
- bufOff = maxBuf;
-
- return available;
- }
- else
- {
- bufOff += (int)n;
-
- return (int)n;
- }
- }
-
- public int available()
- throws IOException
- {
- return maxBuf - bufOff;
- }
-
- public void close()
- throws IOException
- {
- super.close();
- }
-
- public boolean markSupported()
- {
- return false;
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherOutputStream.java b/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherOutputStream.java
deleted file mode 100644
index 17a7b6d..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherOutputStream.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package org.bouncycastle.crypto.io;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.StreamCipher;
-
-public class CipherOutputStream
- extends FilterOutputStream
-{
- private BufferedBlockCipher bufferedBlockCipher;
- private StreamCipher streamCipher;
-
- private byte[] oneByte = new byte[1];
- private byte[] buf;
-
- /**
- * Constructs a CipherOutputStream from an OutputStream and a
- * BufferedBlockCipher.
- */
- public CipherOutputStream(
- OutputStream os,
- BufferedBlockCipher cipher)
- {
- super(os);
- this.bufferedBlockCipher = cipher;
- this.buf = new byte[cipher.getBlockSize()];
- }
-
- /**
- * Constructs a CipherOutputStream from an OutputStream and a
- * BufferedBlockCipher.
- */
- public CipherOutputStream(
- OutputStream os,
- StreamCipher cipher)
- {
- super(os);
- this.streamCipher = cipher;
- }
-
- /**
- * Writes the specified byte to this output stream.
- *
- * @param b the <code>byte</code>.
- * @exception java.io.IOException if an I/O error occurs.
- */
- public void write(
- int b)
- throws IOException
- {
- oneByte[0] = (byte)b;
-
- if (bufferedBlockCipher != null)
- {
- int len = bufferedBlockCipher.processBytes(oneByte, 0, 1, buf, 0);
-
- if (len != 0)
- {
- out.write(buf, 0, len);
- }
- }
- else
- {
- out.write(streamCipher.returnByte((byte)b));
- }
- }
-
- /**
- * Writes <code>b.length</code> bytes from the specified byte array
- * to this output stream.
- * <p>
- * The <code>write</code> method of
- * <code>CipherOutputStream</code> calls the <code>write</code>
- * method of three arguments with the three arguments
- * <code>b</code>, <code>0</code>, and <code>b.length</code>.
- *
- * @param b the data.
- * @exception java.io.IOException if an I/O error occurs.
- * @see #write(byte[], int, int)
- */
- public void write(
- byte[] b)
- throws IOException
- {
- write(b, 0, b.length);
- }
-
- /**
- * Writes <code>len</code> bytes from the specified byte array
- * starting at offset <code>off</code> to this output stream.
- *
- * @param b the data.
- * @param off the start offset in the data.
- * @param len the number of bytes to write.
- * @exception java.io.IOException if an I/O error occurs.
- */
- public void write(
- byte[] b,
- int off,
- int len)
- throws IOException
- {
- if (bufferedBlockCipher != null)
- {
- byte[] buf = new byte[bufferedBlockCipher.getOutputSize(len)];
-
- int outLen = bufferedBlockCipher.processBytes(b, off, len, buf, 0);
-
- if (outLen != 0)
- {
- out.write(buf, 0, outLen);
- }
- }
- else
- {
- byte[] buf = new byte[len];
-
- streamCipher.processBytes(b, off, len, buf, 0);
-
- out.write(buf, 0, len);
- }
- }
-
- /**
- * Flushes this output stream by forcing any buffered output bytes
- * that have already been processed by the encapsulated cipher object
- * to be written out.
- *
- * <p>
- * Any bytes buffered by the encapsulated cipher
- * and waiting to be processed by it will not be written out. For example,
- * if the encapsulated cipher is a block cipher, and the total number of
- * bytes written using one of the <code>write</code> methods is less than
- * the cipher's block size, no bytes will be written out.
- *
- * @exception java.io.IOException if an I/O error occurs.
- */
- public void flush()
- throws IOException
- {
- super.flush();
- }
-
- /**
- * Closes this output stream and releases any system resources
- * associated with this stream.
- * <p>
- * This method invokes the <code>doFinal</code> method of the encapsulated
- * cipher object, which causes any bytes buffered by the encapsulated
- * cipher to be processed. The result is written out by calling the
- * <code>flush</code> method of this output stream.
- * <p>
- * This method resets the encapsulated cipher object to its initial state
- * and calls the <code>close</code> method of the underlying output
- * stream.
- *
- * @exception java.io.IOException if an I/O error occurs.
- */
- public void close()
- throws IOException
- {
- try
- {
- if (bufferedBlockCipher != null)
- {
- byte[] buf = new byte[bufferedBlockCipher.getOutputSize(0)];
-
- int outLen = bufferedBlockCipher.doFinal(buf, 0);
-
- if (outLen != 0)
- {
- out.write(buf, 0, outLen);
- }
- }
- }
- catch (Exception e)
- {
- throw new IOException("Error closing stream: " + e.toString());
- }
-
- flush();
-
- super.close();
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
index 9a6e2e0..fef51fd 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
@@ -29,8 +29,8 @@ public class CCMBlockCipher
private int macSize;
private CipherParameters keyParam;
private byte[] macBlock;
- private ByteArrayOutputStream associatedText = new ByteArrayOutputStream();
- private ByteArrayOutputStream data = new ByteArrayOutputStream();
+ private ExposedByteArrayOutputStream associatedText = new ExposedByteArrayOutputStream();
+ private ExposedByteArrayOutputStream data = new ExposedByteArrayOutputStream();
/**
* Basic constructor.
@@ -65,6 +65,7 @@ public class CCMBlockCipher
{
this.forEncryption = forEncryption;
+ CipherParameters cipherParameters;
if (params instanceof AEADParameters)
{
AEADParameters param = (AEADParameters)params;
@@ -72,7 +73,7 @@ public class CCMBlockCipher
nonce = param.getNonce();
initialAssociatedText = param.getAssociatedText();
macSize = param.getMacSize() / 8;
- keyParam = param.getKey();
+ cipherParameters = param.getKey();
}
else if (params instanceof ParametersWithIV)
{
@@ -81,17 +82,25 @@ public class CCMBlockCipher
nonce = param.getIV();
initialAssociatedText = null;
macSize = macBlock.length / 2;
- keyParam = param.getParameters();
+ cipherParameters = param.getParameters();
}
else
{
throw new IllegalArgumentException("invalid parameters passed to CCM");
}
+ // NOTE: Very basic support for key re-use, but no performance gain from it
+ if (cipherParameters != null)
+ {
+ keyParam = cipherParameters;
+ }
+
if (nonce == null || nonce.length < 7 || nonce.length > 13)
{
throw new IllegalArgumentException("nonce must have length from 7 to 13 octets");
}
+
+ reset();
}
public String getAlgorithmName()
@@ -129,14 +138,11 @@ public class CCMBlockCipher
public int doFinal(byte[] out, int outOff)
throws IllegalStateException, InvalidCipherTextException
{
- byte[] text = data.toByteArray();
- byte[] enc = processPacket(text, 0, text.length);
-
- System.arraycopy(enc, 0, out, outOff, enc.length);
+ int len = processPacket(data.getBuffer(), 0, data.size(), out, outOff);
reset();
- return enc.length;
+ return len;
}
public void reset()
@@ -178,9 +184,55 @@ public class CCMBlockCipher
return totalData < macSize ? 0 : totalData - macSize;
}
+ /**
+ * Process a packet of data for either CCM decryption or encryption.
+ *
+ * @param in data for processing.
+ * @param inOff offset at which data starts in the input array.
+ * @param inLen length of the data in the input array.
+ * @return a byte array containing the processed input..
+ * @throws IllegalStateException if the cipher is not appropriately set up.
+ * @throws InvalidCipherTextException if the input data is truncated or the mac check fails.
+ */
public byte[] processPacket(byte[] in, int inOff, int inLen)
throws IllegalStateException, InvalidCipherTextException
{
+ byte[] output;
+
+ if (forEncryption)
+ {
+ output = new byte[inLen + macSize];
+ }
+ else
+ {
+ if (inLen < macSize)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
+ output = new byte[inLen - macSize];
+ }
+
+ processPacket(in, inOff, inLen, output, 0);
+
+ return output;
+ }
+
+ /**
+ * Process a packet of data for either CCM decryption or encryption.
+ *
+ * @param in data for processing.
+ * @param inOff offset at which data starts in the input array.
+ * @param inLen length of the data in the input array.
+ * @param output output array.
+ * @param outOff offset into output array to start putting processed bytes.
+ * @return the number of bytes added to output.
+ * @throws IllegalStateException if the cipher is not appropriately set up.
+ * @throws InvalidCipherTextException if the input data is truncated or the mac check fails.
+ * @throws DataLengthException if output buffer too short.
+ */
+ public int processPacket(byte[] in, int inOff, int inLen, byte[] output, int outOff)
+ throws IllegalStateException, InvalidCipherTextException, DataLengthException
+ {
// TODO: handle null keyParam (e.g. via RepeatedKeySpec)
// Need to keep the CTR and CBC Mac parts around and reset
if (keyParam == null)
@@ -206,42 +258,52 @@ public class CCMBlockCipher
BlockCipher ctrCipher = new SICBlockCipher(cipher);
ctrCipher.init(forEncryption, new ParametersWithIV(keyParam, iv));
- int index = inOff;
- int outOff = 0;
- byte[] output;
+ int outputLen;
+ int inIndex = inOff;
+ int outIndex = outOff;
if (forEncryption)
{
- output = new byte[inLen + macSize];
+ outputLen = inLen + macSize;
+ if (output.length < (outputLen + outOff))
+ {
+ throw new DataLengthException("Output buffer too short.");
+ }
calculateMac(in, inOff, inLen, macBlock);
ctrCipher.processBlock(macBlock, 0, macBlock, 0); // S0
- while (index < inLen - blockSize) // S1...
+ while (inIndex < (inOff + inLen - blockSize)) // S1...
{
- ctrCipher.processBlock(in, index, output, outOff);
- outOff += blockSize;
- index += blockSize;
+ ctrCipher.processBlock(in, inIndex, output, outIndex);
+ outIndex += blockSize;
+ inIndex += blockSize;
}
byte[] block = new byte[blockSize];
- System.arraycopy(in, index, block, 0, inLen - index);
+ System.arraycopy(in, inIndex, block, 0, inLen + inOff - inIndex);
ctrCipher.processBlock(block, 0, block, 0);
- System.arraycopy(block, 0, output, outOff, inLen - index);
+ System.arraycopy(block, 0, output, outIndex, inLen + inOff - inIndex);
- outOff += inLen - index;
-
- System.arraycopy(macBlock, 0, output, outOff, output.length - outOff);
+ System.arraycopy(macBlock, 0, output, outOff + inLen, macSize);
}
else
{
- output = new byte[inLen - macSize];
+ if (inLen < macSize)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
+ outputLen = inLen - macSize;
+ if (output.length < (outputLen + outOff))
+ {
+ throw new DataLengthException("Output buffer too short.");
+ }
- System.arraycopy(in, inOff + inLen - macSize, macBlock, 0, macSize);
+ System.arraycopy(in, inOff + outputLen, macBlock, 0, macSize);
ctrCipher.processBlock(macBlock, 0, macBlock, 0);
@@ -250,24 +312,24 @@ public class CCMBlockCipher
macBlock[i] = 0;
}
- while (outOff < output.length - blockSize)
+ while (inIndex < (inOff + outputLen - blockSize))
{
- ctrCipher.processBlock(in, index, output, outOff);
- outOff += blockSize;
- index += blockSize;
+ ctrCipher.processBlock(in, inIndex, output, outIndex);
+ outIndex += blockSize;
+ inIndex += blockSize;
}
byte[] block = new byte[blockSize];
- System.arraycopy(in, index, block, 0, output.length - outOff);
+ System.arraycopy(in, inIndex, block, 0, outputLen - (inIndex - inOff));
ctrCipher.processBlock(block, 0, block, 0);
- System.arraycopy(block, 0, output, outOff, output.length - outOff);
+ System.arraycopy(block, 0, output, outIndex, outputLen - (inIndex - inOff));
byte[] calculatedMacBlock = new byte[blockSize];
- calculateMac(output, 0, output.length, calculatedMacBlock);
+ calculateMac(output, outOff, outputLen, calculatedMacBlock);
if (!Arrays.constantTimeAreEqual(macBlock, calculatedMacBlock))
{
@@ -275,7 +337,7 @@ public class CCMBlockCipher
}
}
- return output;
+ return outputLen;
}
private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
@@ -344,8 +406,7 @@ public class CCMBlockCipher
}
if (associatedText.size() > 0)
{
- byte[] tmp = associatedText.toByteArray();
- cMac.update(tmp, 0, tmp.length);
+ cMac.update(associatedText.getBuffer(), 0, associatedText.size());
}
extra = (extra + textLength) % 16;
@@ -375,4 +436,17 @@ public class CCMBlockCipher
{
return getAssociatedTextLength() > 0;
}
+
+ private class ExposedByteArrayOutputStream
+ extends ByteArrayOutputStream
+ {
+ public ExposedByteArrayOutputStream()
+ {
+ }
+
+ public byte[] getBuffer()
+ {
+ return this.buf;
+ }
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
index d0fb9bb..a885169 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
@@ -4,6 +4,7 @@ import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.util.Arrays;
/**
* implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
@@ -246,6 +247,16 @@ public class CFBBlockCipher
}
/**
+ * Return the current state of the initialisation vector.
+ *
+ * @return current IV
+ */
+ public byte[] getCurrentIV()
+ {
+ return Arrays.clone(cfbV);
+ }
+
+ /**
* reset the chaining vector back to the IV and reset the underlying
* cipher.
*/
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
index b8e5b61..5388b40 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
@@ -22,8 +22,9 @@ public class CTSBlockCipher
public CTSBlockCipher(
BlockCipher cipher)
{
- if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher))
+ if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher) || (cipher instanceof SICBlockCipher))
{
+ // TODO: This is broken - need to introduce marker interface to differentiate block cipher primitive from mode?
throw new IllegalArgumentException("CTSBlockCipher can only accept ECB, or CBC ciphers");
}
@@ -72,7 +73,7 @@ public class CTSBlockCipher
}
/**
- * process a single byte, producing an output block if neccessary.
+ * process a single byte, producing an output block if necessary.
*
* @param in the input byte.
* @param out the space for any output that might be produced.
@@ -200,60 +201,81 @@ public class CTSBlockCipher
if (forEncryption)
{
- cipher.processBlock(buf, 0, block, 0);
-
if (bufOff < blockSize)
{
throw new DataLengthException("need at least one block of input for CTS");
}
- for (int i = bufOff; i != buf.length; i++)
- {
- buf[i] = block[i - blockSize];
- }
-
- for (int i = blockSize; i != bufOff; i++)
- {
- buf[i] ^= block[i - blockSize];
- }
+ cipher.processBlock(buf, 0, block, 0);
- if (cipher instanceof CBCBlockCipher)
+ if (bufOff > blockSize)
{
- BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
-
- c.processBlock(buf, blockSize, out, outOff);
+ for (int i = bufOff; i != buf.length; i++)
+ {
+ buf[i] = block[i - blockSize];
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ buf[i] ^= block[i - blockSize];
+ }
+
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, blockSize, out, outOff);
+ }
+ else
+ {
+ cipher.processBlock(buf, blockSize, out, outOff);
+ }
+
+ System.arraycopy(block, 0, out, outOff + blockSize, len);
}
else
{
- cipher.processBlock(buf, blockSize, out, outOff);
+ System.arraycopy(block, 0, out, outOff, blockSize);
}
-
- System.arraycopy(block, 0, out, outOff + blockSize, len);
}
else
{
+ if (bufOff < blockSize)
+ {
+ throw new DataLengthException("need at least one block of input for CTS");
+ }
+
byte[] lastBlock = new byte[blockSize];
- if (cipher instanceof CBCBlockCipher)
+ if (bufOff > blockSize)
{
- BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
-
- c.processBlock(buf, 0, block, 0);
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, 0, block, 0);
+ }
+ else
+ {
+ cipher.processBlock(buf, 0, block, 0);
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]);
+ }
+
+ System.arraycopy(buf, blockSize, block, 0, len);
+
+ cipher.processBlock(block, 0, out, outOff);
+ System.arraycopy(lastBlock, 0, out, outOff + blockSize, len);
}
else
{
cipher.processBlock(buf, 0, block, 0);
- }
- for (int i = blockSize; i != bufOff; i++)
- {
- lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]);
+ System.arraycopy(block, 0, out, outOff, blockSize);
}
-
- System.arraycopy(buf, blockSize, block, 0, len);
-
- cipher.processBlock(block, 0, out, outOff);
- System.arraycopy(lastBlock, 0, out, outOff + blockSize, len);
}
int offset = bufOff;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
index 4875301..3031a44 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
@@ -5,6 +5,32 @@ import org.bouncycastle.util.Arrays;
abstract class GCMUtil
{
+ private static final int E1 = 0xe1000000;
+ private static final byte E1B = (byte)0xe1;
+ private static final long E1L = (E1 & 0xFFFFFFFFL) << 24;
+
+ private static int[] generateLookup()
+ {
+ int[] lookup = new int[256];
+
+ for (int c = 0; c < 256; ++c)
+ {
+ int v = 0;
+ for (int i = 7; i >= 0; --i)
+ {
+ if ((c & (1 << i)) != 0)
+ {
+ v ^= (E1 >>> (7 - i));
+ }
+ }
+ lookup[c] = v;
+ }
+
+ return lookup;
+ }
+
+ private static final int[] LOOKUP = generateLookup();
+
static byte[] oneAsBytes()
{
byte[] tmp = new byte[16];
@@ -15,78 +41,155 @@ abstract class GCMUtil
static int[] oneAsInts()
{
int[] tmp = new int[4];
- tmp[0] = 0x80000000;
+ tmp[0] = 1 << 31;
+ return tmp;
+ }
+
+ static long[] oneAsLongs()
+ {
+ long[] tmp = new long[2];
+ tmp[0] = 1L << 63;
return tmp;
}
- static byte[] asBytes(int[] ns)
+ static byte[] asBytes(int[] x)
+ {
+ byte[] z = new byte[16];
+ Pack.intToBigEndian(x, z, 0);
+ return z;
+ }
+
+ static void asBytes(int[] x, byte[] z)
+ {
+ Pack.intToBigEndian(x, z, 0);
+ }
+
+ static byte[] asBytes(long[] x)
+ {
+ byte[] z = new byte[16];
+ Pack.longToBigEndian(x, z, 0);
+ return z;
+ }
+
+ static void asBytes(long[] x, byte[] z)
+ {
+ Pack.longToBigEndian(x, z, 0);
+ }
+
+ static int[] asInts(byte[] x)
+ {
+ int[] z = new int[4];
+ Pack.bigEndianToInt(x, 0, z);
+ return z;
+ }
+
+ static void asInts(byte[] x, int[] z)
{
- byte[] output = new byte[16];
- Pack.intToBigEndian(ns, output, 0);
- return output;
+ Pack.bigEndianToInt(x, 0, z);
}
- static int[] asInts(byte[] bs)
+ static long[] asLongs(byte[] x)
{
- int[] output = new int[4];
- Pack.bigEndianToInt(bs, 0, output);
- return output;
+ long[] z = new long[2];
+ Pack.bigEndianToLong(x, 0, z);
+ return z;
}
- static void asInts(byte[] bs, int[] output)
+ static void asLongs(byte[] x, long[] z)
{
- Pack.bigEndianToInt(bs, 0, output);
+ Pack.bigEndianToLong(x, 0, z);
}
- static void multiply(byte[] block, byte[] val)
+ static void multiply(byte[] x, byte[] y)
{
- byte[] tmp = Arrays.clone(block);
- byte[] c = new byte[16];
+ byte[] r0 = Arrays.clone(x);
+ byte[] r1 = new byte[16];
for (int i = 0; i < 16; ++i)
{
- byte bits = val[i];
+ byte bits = y[i];
for (int j = 7; j >= 0; --j)
{
if ((bits & (1 << j)) != 0)
{
- xor(c, tmp);
+ xor(r1, r0);
}
- boolean lsb = (tmp[15] & 1) != 0;
- shiftRight(tmp);
- if (lsb)
+ if (shiftRight(r0) != 0)
{
- // R = new byte[]{ 0xe1, ... };
-// GCMUtil.xor(v, R);
- tmp[0] ^= (byte)0xe1;
+ r0[0] ^= E1B;
}
}
}
- System.arraycopy(c, 0, block, 0, 16);
+ System.arraycopy(r1, 0, x, 0, 16);
+ }
+
+ static void multiply(int[] x, int[] y)
+ {
+ int[] r0 = Arrays.clone(x);
+ int[] r1 = new int[4];
+
+ for (int i = 0; i < 4; ++i)
+ {
+ int bits = y[i];
+ for (int j = 31; j >= 0; --j)
+ {
+ if ((bits & (1 << j)) != 0)
+ {
+ xor(r1, r0);
+ }
+
+ if (shiftRight(r0) != 0)
+ {
+ r0[0] ^= E1;
+ }
+ }
+ }
+
+ System.arraycopy(r1, 0, x, 0, 4);
+ }
+
+ static void multiply(long[] x, long[] y)
+ {
+ long[] r0 = new long[]{ x[0], x[1] };
+ long[] r1 = new long[2];
+
+ for (int i = 0; i < 2; ++i)
+ {
+ long bits = y[i];
+ for (int j = 63; j >= 0; --j)
+ {
+ if ((bits & (1L << j)) != 0)
+ {
+ xor(r1, r0);
+ }
+
+ if (shiftRight(r0) != 0)
+ {
+ r0[0] ^= E1L;
+ }
+ }
+ }
+
+ x[0] = r1[0];
+ x[1] = r1[1];
}
// P is the value with only bit i=1 set
static void multiplyP(int[] x)
{
- boolean lsb = (x[3] & 1) != 0;
- shiftRight(x);
- if (lsb)
+ if (shiftRight(x) != 0)
{
- // R = new int[]{ 0xe1000000, 0, 0, 0 };
-// xor(v, R);
- x[0] ^= 0xe1000000;
+ x[0] ^= E1;
}
}
- static void multiplyP(int[] x, int[] output)
+ static void multiplyP(int[] x, int[] y)
{
- boolean lsb = (x[3] & 1) != 0;
- shiftRight(x, output);
- if (lsb)
+ if (shiftRight(x, y) != 0)
{
- output[0] ^= 0xe1000000;
+ y[0] ^= E1;
}
}
@@ -98,163 +201,257 @@ abstract class GCMUtil
// multiplyP(x);
// }
- int lsw = x[3];
- shiftRightN(x, 8);
- for (int i = 7; i >= 0; --i)
- {
- if ((lsw & (1 << i)) != 0)
- {
- x[0] ^= (0xe1000000 >>> (7 - i));
- }
- }
+ int c = shiftRightN(x, 8);
+ x[0] ^= LOOKUP[c >>> 24];
}
- static void multiplyP8(int[] x, int[] output)
+ static void multiplyP8(int[] x, int[] y)
{
- int lsw = x[3];
- shiftRightN(x, 8, output);
- for (int i = 7; i >= 0; --i)
- {
- if ((lsw & (1 << i)) != 0)
- {
- output[0] ^= (0xe1000000 >>> (7 - i));
- }
- }
+ int c = shiftRightN(x, 8, y);
+ y[0] ^= LOOKUP[c >>> 24];
}
- static void shiftRight(byte[] block)
+ static byte shiftRight(byte[] x)
{
- int i = 0;
- int bit = 0;
- for (;;)
+// int c = 0;
+// for (int i = 0; i < 16; ++i)
+// {
+// int b = x[i] & 0xff;
+// x[i] = (byte)((b >>> 1) | c);
+// c = (b & 1) << 7;
+// }
+// return (byte)c;
+
+ int i = 0, c = 0;
+ do
{
- int b = block[i] & 0xff;
- block[i] = (byte) ((b >>> 1) | bit);
- if (++i == 16)
- {
- break;
- }
- bit = (b & 1) << 7;
+ int b = x[i] & 0xff;
+ x[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ x[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ x[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ x[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
}
+ while (i < 16);
+ return (byte)c;
}
- static void shiftRight(byte[] block, byte[] output)
+ static byte shiftRight(byte[] x, byte[] z)
{
- int i = 0;
- int bit = 0;
- for (;;)
+// int c = 0;
+// for (int i = 0; i < 16; ++i)
+// {
+// int b = x[i] & 0xff;
+// z[i] = (byte) ((b >>> 1) | c);
+// c = (b & 1) << 7;
+// }
+// return (byte) c;
+
+ int i = 0, c = 0;
+ do
{
- int b = block[i] & 0xff;
- output[i] = (byte) ((b >>> 1) | bit);
- if (++i == 16)
- {
- break;
- }
- bit = (b & 1) << 7;
+ int b = x[i] & 0xff;
+ z[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ z[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ z[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ z[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
}
+ while (i < 16);
+ return (byte)c;
}
- static void shiftRight(int[] block)
+ static int shiftRight(int[] x)
{
- int i = 0;
- int bit = 0;
- for (;;)
- {
- int b = block[i];
- block[i] = (b >>> 1) | bit;
- if (++i == 4)
- {
- break;
- }
- bit = b << 31;
- }
+// int c = 0;
+// for (int i = 0; i < 4; ++i)
+// {
+// int b = x[i];
+// x[i] = (b >>> 1) | c;
+// c = b << 31;
+// }
+// return c;
+
+ int b = x[0];
+ x[0] = b >>> 1;
+ int c = b << 31;
+ b = x[1];
+ x[1] = (b >>> 1) | c;
+ c = b << 31;
+ b = x[2];
+ x[2] = (b >>> 1) | c;
+ c = b << 31;
+ b = x[3];
+ x[3] = (b >>> 1) | c;
+ return b << 31;
}
- static void shiftRight(int[] block, int[] output)
+ static int shiftRight(int[] x, int[] z)
{
- int i = 0;
- int bit = 0;
- for (;;)
- {
- int b = block[i];
- output[i] = (b >>> 1) | bit;
- if (++i == 4)
- {
- break;
- }
- bit = b << 31;
- }
+// int c = 0;
+// for (int i = 0; i < 4; ++i)
+// {
+// int b = x[i];
+// z[i] = (b >>> 1) | c;
+// c = b << 31;
+// }
+// return c;
+
+ int b = x[0];
+ z[0] = b >>> 1;
+ int c = b << 31;
+ b = x[1];
+ z[1] = (b >>> 1) | c;
+ c = b << 31;
+ b = x[2];
+ z[2] = (b >>> 1) | c;
+ c = b << 31;
+ b = x[3];
+ z[3] = (b >>> 1) | c;
+ return b << 31;
}
- static void shiftRightN(int[] block, int n)
+ static long shiftRight(long[] x)
{
- int i = 0;
- int bits = 0;
- for (;;)
- {
- int b = block[i];
- block[i] = (b >>> n) | bits;
- if (++i == 4)
- {
- break;
- }
- bits = b << (32 - n);
- }
+ long b = x[0];
+ x[0] = b >>> 1;
+ long c = b << 63;
+ b = x[1];
+ x[1] = (b >>> 1) | c;
+ return b << 63;
+ }
+
+ static long shiftRight(long[] x, long[] z)
+ {
+ long b = x[0];
+ z[0] = b >>> 1;
+ long c = b << 63;
+ b = x[1];
+ z[1] = (b >>> 1) | c;
+ return b << 63;
+ }
+
+ static int shiftRightN(int[] x, int n)
+ {
+// int c = 0, nInv = 32 - n;
+// for (int i = 0; i < 4; ++i)
+// {
+// int b = x[i];
+// x[i] = (b >>> n) | c;
+// c = b << nInv;
+// }
+// return c;
+
+ int b = x[0], nInv = 32 - n;
+ x[0] = b >>> n;
+ int c = b << nInv;
+ b = x[1];
+ x[1] = (b >>> n) | c;
+ c = b << nInv;
+ b = x[2];
+ x[2] = (b >>> n) | c;
+ c = b << nInv;
+ b = x[3];
+ x[3] = (b >>> n) | c;
+ return b << nInv;
}
- static void shiftRightN(int[] block, int n, int[] output)
+ static int shiftRightN(int[] x, int n, int[] z)
+ {
+// int c = 0, nInv = 32 - n;
+// for (int i = 0; i < 4; ++i)
+// {
+// int b = x[i];
+// z[i] = (b >>> n) | c;
+// c = b << nInv;
+// }
+// return c;
+
+ int b = x[0], nInv = 32 - n;
+ z[0] = b >>> n;
+ int c = b << nInv;
+ b = x[1];
+ z[1] = (b >>> n) | c;
+ c = b << nInv;
+ b = x[2];
+ z[2] = (b >>> n) | c;
+ c = b << nInv;
+ b = x[3];
+ z[3] = (b >>> n) | c;
+ return b << nInv;
+ }
+
+ static void xor(byte[] x, byte[] y)
{
int i = 0;
- int bits = 0;
- for (;;)
+ do
{
- int b = block[i];
- output[i] = (b >>> n) | bits;
- if (++i == 4)
- {
- break;
- }
- bits = b << (32 - n);
+ x[i] ^= y[i]; ++i;
+ x[i] ^= y[i]; ++i;
+ x[i] ^= y[i]; ++i;
+ x[i] ^= y[i]; ++i;
}
+ while (i < 16);
}
- static void xor(byte[] block, byte[] val)
+ static void xor(byte[] x, byte[] y, int yOff, int yLen)
{
- for (int i = 15; i >= 0; --i)
+ while (yLen-- > 0)
{
- block[i] ^= val[i];
+ x[yLen] ^= y[yOff + yLen];
}
}
- static void xor(byte[] block, byte[] val, int off, int len)
+ static void xor(byte[] x, byte[] y, byte[] z)
{
- while (len-- > 0)
+ int i = 0;
+ do
{
- block[len] ^= val[off + len];
+ z[i] = (byte)(x[i] ^ y[i]); ++i;
+ z[i] = (byte)(x[i] ^ y[i]); ++i;
+ z[i] = (byte)(x[i] ^ y[i]); ++i;
+ z[i] = (byte)(x[i] ^ y[i]); ++i;
}
+ while (i < 16);
}
- static void xor(byte[] block, byte[] val, byte[] output)
+ static void xor(int[] x, int[] y)
{
- for (int i = 15; i >= 0; --i)
- {
- output[i] = (byte)(block[i] ^ val[i]);
- }
+ x[0] ^= y[0];
+ x[1] ^= y[1];
+ x[2] ^= y[2];
+ x[3] ^= y[3];
}
- static void xor(int[] block, int[] val)
+ static void xor(int[] x, int[] y, int[] z)
{
- for (int i = 3; i >= 0; --i)
- {
- block[i] ^= val[i];
- }
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
+ z[2] = x[2] ^ y[2];
+ z[3] = x[3] ^ y[3];
}
- static void xor(int[] block, int[] val, int[] output)
+ static void xor(long[] x, long[] y)
{
- for (int i = 3; i >= 0; --i)
- {
- output[i] = block[i] ^ val[i];
- }
+ x[0] ^= y[0];
+ x[1] ^= y[1];
+ }
+
+ static void xor(long[] x, long[] y, long[] z)
+ {
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
index a051208..6eff4e3 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
@@ -12,31 +12,32 @@ public class Tables1kGCMExponentiator implements GCMExponentiator
public void init(byte[] x)
{
- if (lookupPowX2 != null && Arrays.areEqual(x, (byte[])lookupPowX2.elementAt(0)))
+ int[] y = GCMUtil.asInts(x);
+ if (lookupPowX2 != null && Arrays.areEqual(y, (int[])lookupPowX2.elementAt(0)))
{
return;
}
lookupPowX2 = new Vector(8);
- lookupPowX2.addElement(Arrays.clone(x));
+ lookupPowX2.addElement(y);
}
public void exponentiateX(long pow, byte[] output)
{
- byte[] y = GCMUtil.oneAsBytes();
+ int[] y = GCMUtil.oneAsInts();
int bit = 0;
while (pow > 0)
{
if ((pow & 1L) != 0)
{
ensureAvailable(bit);
- GCMUtil.multiply(y, (byte[])lookupPowX2.elementAt(bit));
+ GCMUtil.multiply(y, (int[])lookupPowX2.elementAt(bit));
}
++bit;
pow >>>= 1;
}
- System.arraycopy(y, 0, output, 0, 16);
+ GCMUtil.asBytes(y, output);
}
private void ensureAvailable(int bit)
@@ -44,7 +45,7 @@ public class Tables1kGCMExponentiator implements GCMExponentiator
int count = lookupPowX2.size();
if (count <= bit)
{
- byte[] tmp = (byte[])lookupPowX2.elementAt(count - 1);
+ int[] tmp = (int[])lookupPowX2.elementAt(count - 1);
do
{
tmp = Arrays.clone(tmp);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java
index 05a1327..9cc6e72 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java
@@ -41,7 +41,7 @@ public class ECDomainParameters
byte[] seed)
{
this.curve = curve;
- this.G = G;
+ this.G = G.normalize();
this.n = n;
this.h = h;
this.seed = seed;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java
index 5fbea19..b6b3fb6 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java
@@ -12,7 +12,7 @@ public class ECPublicKeyParameters
ECDomainParameters params)
{
super(false, params);
- this.Q = Q;
+ this.Q = Q.normalize();
}
public ECPoint getQ()
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSAKCalculator.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSAKCalculator.java
new file mode 100644
index 0000000..fced06e
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSAKCalculator.java
@@ -0,0 +1,41 @@
+package org.bouncycastle.crypto.signers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * Interface define calculators of K values for DSA/ECDSA.
+ */
+public interface DSAKCalculator
+{
+ /**
+ * Return true if this calculator is deterministic, false otherwise.
+ *
+ * @return true if deterministic, otherwise false.
+ */
+ boolean isDeterministic();
+
+ /**
+ * Non-deterministic initialiser.
+ *
+ * @param n the order of the DSA group.
+ * @param random a source of randomness.
+ */
+ void init(BigInteger n, SecureRandom random);
+
+ /**
+ * Deterministic initialiser.
+ *
+ * @param n the order of the DSA group.
+ * @param d the DSA private value.
+ * @param message the message being signed.
+ */
+ void init(BigInteger n, BigInteger d, byte[] message);
+
+ /**
+ * Return the next valid value of K.
+ *
+ * @return a K value.
+ */
+ BigInteger nextK();
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
index a96cef0..292c408 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
@@ -1,5 +1,8 @@
package org.bouncycastle.crypto.signers;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DSA;
import org.bouncycastle.crypto.params.DSAKeyParameters;
@@ -8,9 +11,6 @@ import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
/**
* The Digital Signature Algorithm - as described in "Handbook of Applied
* Cryptography", pages 452 - 453.
@@ -18,9 +18,28 @@ import java.security.SecureRandom;
public class DSASigner
implements DSA
{
- DSAKeyParameters key;
+ private final DSAKCalculator kCalculator;
- SecureRandom random;
+ private DSAKeyParameters key;
+ private SecureRandom random;
+
+ /**
+ * Default configuration, random K values.
+ */
+ public DSASigner()
+ {
+ this.kCalculator = new RandomDSAKCalculator();
+ }
+
+ /**
+ * Configuration with an alternate, possibly deterministic calculator of K.
+ *
+ * @param kCalculator a K value calculator.
+ */
+ public DSASigner(DSAKCalculator kCalculator)
+ {
+ this.kCalculator = kCalculator;
+ }
public void init(
boolean forSigning,
@@ -59,14 +78,17 @@ public class DSASigner
{
DSAParameters params = key.getParameters();
BigInteger m = calculateE(params.getQ(), message);
- BigInteger k;
- int qBitLength = params.getQ().bitLength();
- do
+ if (kCalculator.isDeterministic())
{
- k = new BigInteger(qBitLength, random);
+ kCalculator.init(params.getQ(), ((DSAPrivateKeyParameters)key).getX(), message);
}
- while (k.compareTo(params.getQ()) >= 0);
+ else
+ {
+ kCalculator.init(params.getQ(), random);
+ }
+
+ BigInteger k = kCalculator.nextK();
BigInteger r = params.getG().modPow(k, params.getP()).mod(params.getQ());
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
index a80c574..2a1f98e 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
@@ -19,9 +19,28 @@ import org.bouncycastle.math.ec.ECPoint;
public class ECDSASigner
implements ECConstants, DSA
{
- ECKeyParameters key;
+ private final DSAKCalculator kCalculator;
- SecureRandom random;
+ private ECKeyParameters key;
+ private SecureRandom random;
+
+ /**
+ * Default configuration, random K values.
+ */
+ public ECDSASigner()
+ {
+ this.kCalculator = new RandomDSAKCalculator();
+ }
+
+ /**
+ * Configuration with an alternate, possibly deterministic calculator of K.
+ *
+ * @param kCalculator a K value calculator.
+ */
+ public ECDSASigner(DSAKCalculator kCalculator)
+ {
+ this.kCalculator = kCalculator;
+ }
public void init(
boolean forSigning,
@@ -64,24 +83,28 @@ public class ECDSASigner
BigInteger r = null;
BigInteger s = null;
+ if (kCalculator.isDeterministic())
+ {
+ kCalculator.init(n, ((ECPrivateKeyParameters)key).getD(), message);
+ }
+ else
+ {
+ kCalculator.init(n, random);
+ }
+
// 5.3.2
do // generate s
{
BigInteger k = null;
- int nBitLength = n.bitLength();
do // generate r
{
- do
- {
- k = new BigInteger(nBitLength, random);
- }
- while (k.equals(ZERO) || k.compareTo(n) >= 0);
+ k = kCalculator.nextK();
- ECPoint p = key.getParameters().getG().multiply(k);
+ ECPoint p = key.getParameters().getG().multiply(k).normalize();
// 5.3.3
- BigInteger x = p.getX().toBigInteger();
+ BigInteger x = p.getAffineXCoord().toBigInteger();
r = x.mod(n);
}
@@ -135,7 +158,7 @@ public class ECDSASigner
ECPoint G = key.getParameters().getG();
ECPoint Q = ((ECPublicKeyParameters)key).getQ();
- ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2);
+ ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2).normalize();
// components must be bogus.
if (point.isInfinity())
@@ -143,7 +166,7 @@ public class ECDSASigner
return false;
}
- BigInteger v = point.getX().toBigInteger().mod(n);
+ BigInteger v = point.getAffineXCoord().toBigInteger().mod(n);
return v.equals(r);
}
@@ -153,17 +176,11 @@ public class ECDSASigner
int log2n = n.bitLength();
int messageBitLength = message.length * 8;
- if (log2n >= messageBitLength)
+ BigInteger e = new BigInteger(1, message);
+ if (log2n < messageBitLength)
{
- return new BigInteger(1, message);
- }
- else
- {
- BigInteger trunc = new BigInteger(1, message);
-
- trunc = trunc.shiftRight(messageBitLength - log2n);
-
- return trunc;
+ e = e.shiftRight(messageBitLength - log2n);
}
+ return e;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
index 7fba55a..18dd84e 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
@@ -61,9 +61,15 @@ public class RSADigestSigner
public RSADigestSigner(
Digest digest)
{
- this.digest = digest;
+ this(digest, (ASN1ObjectIdentifier)oidMap.get(digest.getAlgorithmName()));
+ }
- algId = new AlgorithmIdentifier((ASN1ObjectIdentifier)oidMap.get(digest.getAlgorithmName()), DERNull.INSTANCE);
+ public RSADigestSigner(
+ Digest digest,
+ ASN1ObjectIdentifier digestOid)
+ {
+ this.digest = digest;
+ this.algId = new AlgorithmIdentifier(digestOid, DERNull.INSTANCE);
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
new file mode 100644
index 0000000..bbd8cda
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
@@ -0,0 +1,43 @@
+package org.bouncycastle.crypto.signers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+class RandomDSAKCalculator
+ implements DSAKCalculator
+{
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+
+ private BigInteger q;
+ private SecureRandom random;
+
+ public boolean isDeterministic()
+ {
+ return false;
+ }
+
+ public void init(BigInteger n, SecureRandom random)
+ {
+ this.q = n;
+ this.random = random;
+ }
+
+ public void init(BigInteger n, BigInteger d, byte[] message)
+ {
+ throw new IllegalStateException("Operation not supported");
+ }
+
+ public BigInteger nextK()
+ {
+ int qBitLength = q.bitLength();
+
+ BigInteger k;
+ do
+ {
+ k = new BigInteger(qBitLength, random);
+ }
+ while (k.equals(ZERO) || k.compareTo(q) >= 0);
+
+ return k;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java b/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
index 394f2c2..d997db7 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
@@ -10,7 +10,6 @@ import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.nist.NISTNamedCurves;
// BEGIN android-removed
// import org.bouncycastle.asn1.oiw.ElGamalParameter;
// END android-removed
@@ -20,13 +19,9 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.sec.ECPrivateKey;
-import org.bouncycastle.asn1.sec.SECNamedCurves;
-// BEGIN android-removed
-// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
-// END android-removed
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
-import org.bouncycastle.asn1.x9.X962NamedCurves;
+import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
@@ -138,24 +133,7 @@ public class PrivateKeyFactory
if (params.isNamedCurve())
{
ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
- x9 = X962NamedCurves.getByOID(oid);
-
- if (x9 == null)
- {
- x9 = SECNamedCurves.getByOID(oid);
-
- if (x9 == null)
- {
- x9 = NISTNamedCurves.getByOID(oid);
-
- // BEGIN android-removed
- // if (x9 == null)
- // {
- // x9 = TeleTrusTNamedCurves.getByOID(oid);
- // }
- // END android-removed
- }
- }
+ x9 = ECNamedCurveTable.getByOID(oid);
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java b/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
index 6a5c88e..7ade197 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
@@ -12,7 +12,6 @@ import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.nist.NISTNamedCurves;
// BEGIN android-removed
// import org.bouncycastle.asn1.oiw.ElGamalParameter;
// END android-removed
@@ -20,10 +19,6 @@ import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.DHParameter;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.RSAPublicKey;
-import org.bouncycastle.asn1.sec.SECNamedCurves;
-// BEGIN android-removed
-// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
-// END android-removed
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
@@ -31,7 +26,7 @@ import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.asn1.x9.DHDomainParameters;
import org.bouncycastle.asn1.x9.DHPublicKey;
import org.bouncycastle.asn1.x9.DHValidationParms;
-import org.bouncycastle.asn1.x9.X962NamedCurves;
+import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ECPoint;
@@ -168,31 +163,13 @@ public class PublicKeyFactory
}
else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey))
{
- X962Parameters params = new X962Parameters(
- (ASN1Primitive)algId.getParameters());
+ X962Parameters params = X962Parameters.getInstance(algId.getParameters());
X9ECParameters x9;
if (params.isNamedCurve())
{
ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
- x9 = X962NamedCurves.getByOID(oid);
-
- if (x9 == null)
- {
- x9 = SECNamedCurves.getByOID(oid);
-
- if (x9 == null)
- {
- x9 = NISTNamedCurves.getByOID(oid);
-
- // BEGIN android-removed
- // if (x9 == null)
- // {
- // x9 = TeleTrusTNamedCurves.getByOID(oid);
- // }
- // END android-removed
- }
- }
+ x9 = ECNamedCurveTable.getByOID(oid);
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceUtils.java
new file mode 100644
index 0000000..d7677f3
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceUtils.java
@@ -0,0 +1,53 @@
+package org.bouncycastle.jcajce;
+
+import java.io.IOException;
+import java.security.AlgorithmParameters;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1Primitive;
+
+public class JcaJceUtils
+{
+ private JcaJceUtils()
+ {
+
+ }
+
+ /**
+ * Extract an ASN.1 encodable from an AlgorithmParameters object.
+ *
+ * @param params the object to get the encoding used to create the return value.
+ * @return an ASN.1 object representing the primitives making up the params parameter.
+ * @throws IOException if an encoding cannot be extracted.
+ */
+ public static ASN1Encodable extractParameters(AlgorithmParameters params)
+ throws IOException
+ {
+ // we try ASN.1 explicitly first just in case and then role back to the default.
+ ASN1Encodable asn1Params;
+ try
+ {
+ asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1"));
+ }
+ catch (Exception ex)
+ {
+ asn1Params = ASN1Primitive.fromByteArray(params.getEncoded());
+ }
+
+ return asn1Params;
+ }
+
+ public static void loadParameters(AlgorithmParameters params, ASN1Encodable sParams)
+ throws IOException
+ {
+ // we try ASN.1 explicitly first just in case and then role back to the default.
+ try
+ {
+ params.init(sParams.toASN1Primitive().getEncoded(), "ASN.1");
+ }
+ catch (Exception ex)
+ {
+ params.init(sParams.toASN1Primitive().getEncoded());
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/io/MacOutputStream.java b/bcprov/src/main/java/org/bouncycastle/jcajce/io/MacOutputStream.java
deleted file mode 100644
index 235bfe5..0000000
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/io/MacOutputStream.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.jcajce.io;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import javax.crypto.Mac;
-
-public class MacOutputStream
- extends OutputStream
-{
- protected Mac mac;
-
- public MacOutputStream(
- Mac mac)
- {
- this.mac = mac;
- }
-
- public void write(int b)
- throws IOException
- {
- mac.update((byte)b);
- }
-
- public void write(
- byte[] b,
- int off,
- int len)
- throws IOException
- {
- mac.update(b, off, len);
- }
-
- public byte[] getMac()
- {
- return mac.doFinal();
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java
index 1c7b679..ceb9292 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java
@@ -34,18 +34,26 @@ public class DSA
provider.addAlgorithm("Alg.Alias.Signature.RAWDSA", "NONEWITHDSA");
- addSignatureAlgorithm(provider, "SHA224", "DSA", PREFIX + "DSASigner$dsa224", NISTObjectIdentifiers.dsa_with_sha224);
- addSignatureAlgorithm(provider, "SHA256", "DSA", PREFIX + "DSASigner$dsa256", NISTObjectIdentifiers.dsa_with_sha256);
// BEGIN android-removed
- // addSignatureAlgorithm(provider, "SHA384", "DSA", PREFIX + "DSASigner$dsa384", NISTObjectIdentifiers.dsa_with_sha384);
- // addSignatureAlgorithm(provider, "SHA512", "DSA", PREFIX + "DSASigner$dsa512", NISTObjectIdentifiers.dsa_with_sha512);
+ // provider.addAlgorithm("Signature.DETDSA", PREFIX + "DSASigner$detDSA");
+ // provider.addAlgorithm("Signature.SHA1WITHDETDSA", PREFIX + "DSASigner$detDSA");
+ // provider.addAlgorithm("Signature.SHA224WITHDETDSA", PREFIX + "DSASigner$detDSA224");
+ // provider.addAlgorithm("Signature.SHA256WITHDETDSA", PREFIX + "DSASigner$detDSA256");
+ // provider.addAlgorithm("Signature.SHA384WITHDETDSA", PREFIX + "DSASigner$detDSA384");
+ // provider.addAlgorithm("Signature.SHA512WITHDETDSA", PREFIX + "DSASigner$detDSA512");
// END android-removed
+ addSignatureAlgorithm(provider, "SHA224", "DSA", PREFIX + "DSASigner$dsa224", NISTObjectIdentifiers.dsa_with_sha224);
+ addSignatureAlgorithm(provider, "SHA256", "DSA", PREFIX + "DSASigner$dsa256", NISTObjectIdentifiers.dsa_with_sha256);
+ addSignatureAlgorithm(provider, "SHA384", "DSA", PREFIX + "DSASigner$dsa384", NISTObjectIdentifiers.dsa_with_sha384);
+ addSignatureAlgorithm(provider, "SHA512", "DSA", PREFIX + "DSASigner$dsa512", NISTObjectIdentifiers.dsa_with_sha512);
+
// BEGIN android-added
provider.addAlgorithm("Alg.Alias.Signature.DSA", "SHA1withDSA");
// END android-added
// BEGIN android-changed
provider.addAlgorithm("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA");
+ provider.addAlgorithm("Alg.Alias.Signature.SHA1withDSA", "SHA1withDSA");
provider.addAlgorithm("Alg.Alias.Signature.SHA1WITHDSA", "SHA1withDSA");
provider.addAlgorithm("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.1", "SHA1withDSA");
provider.addAlgorithm("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.3", "SHA1withDSA");
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java
index 780a8ca..43e5861 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java
@@ -79,6 +79,13 @@ public class EC
provider.addAlgorithm("Alg.Alias.Signature.1.2.840.10045.4.1", "ECDSA");
// BEGIN android-removed
// provider.addAlgorithm("Alg.Alias.Signature." + TeleTrusTObjectIdentifiers.ecSignWithSha1, "ECDSA");
+ //
+ // provider.addAlgorithm("Signature.DETECDSA", PREFIX + "SignatureSpi$ecDetDSA");
+ // provider.addAlgorithm("Signature.SHA1WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA");
+ // provider.addAlgorithm("Signature.SHA224WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA224");
+ // provider.addAlgorithm("Signature.SHA256WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA256");
+ // provider.addAlgorithm("Signature.SHA384WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA384");
+ // provider.addAlgorithm("Signature.SHA512WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA512");
// END android-removed
addSignatureAlgorithm(provider, "SHA224", "ECDSA", PREFIX + "SignatureSpi$ecDSA224", X9ObjectIdentifiers.ecdsa_with_SHA224);
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java
index c9462a6..f2b5314 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java
@@ -50,17 +50,34 @@ public class KeyAgreementSpi
private byte[] bigIntToBytes(
BigInteger r)
{
+ //
+ // RFC 2631 (2.1.2) specifies that the secret should be padded with leading zeros if necessary
+ // must be the same length as p
+ //
+ int expectedLength = (p.bitLength() + 7) / 8;
+
byte[] tmp = r.toByteArray();
-
- if (tmp[0] == 0)
+
+ if (tmp.length == expectedLength)
+ {
+ return tmp;
+ }
+
+ if (tmp[0] == 0 && tmp.length == expectedLength + 1)
{
- byte[] ntmp = new byte[tmp.length - 1];
+ byte[] rv = new byte[tmp.length - 1];
- System.arraycopy(tmp, 1, ntmp, 0, ntmp.length);
- return ntmp;
+ System.arraycopy(tmp, 1, rv, 0, rv.length);
+ return rv;
}
-
- return tmp;
+
+ // tmp must be shorter than expectedLength
+ // pad to the left with zeros.
+ byte[] rv = new byte[expectedLength];
+
+ System.arraycopy(tmp, 0, rv, rv.length - tmp.length, tmp.length);
+
+ return rv;
}
protected Key engineDoPhase(
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java
index a8c9d45..bdda6a2 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java
@@ -34,6 +34,9 @@ import org.bouncycastle.crypto.digests.AndroidDigestFactory;
// import org.bouncycastle.crypto.digests.SHA512Digest;
// END android-removed
import org.bouncycastle.crypto.params.ParametersWithRandom;
+// BEGIN android-removed
+// import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
+// END android-removed
public class DSASigner
extends SignatureSpi
@@ -227,6 +230,17 @@ public class DSASigner
}
}
+ // BEGIN android-removed
+ // static public class detDSA
+ // extends DSASigner
+ // {
+ // public detDSA()
+ // {
+ // super(new SHA1Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA1Digest())));
+ // }
+ // }
+ // END android-removed
+
static public class dsa224
extends DSASigner
{
@@ -237,7 +251,18 @@ public class DSASigner
// END android-changed
}
}
-
+
+ // BEGIN android-removed
+ // static public class detDSA224
+ // extends DSASigner
+ // {
+ // public detDSA224()
+ // {
+ // super(new SHA224Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA224Digest())));
+ // }
+ // }
+ // END android-removed
+
static public class dsa256
extends DSASigner
{
@@ -248,8 +273,17 @@ public class DSASigner
// END android-changed
}
}
-
+
// BEGIN android-removed
+ // static public class detDSA256
+ // extends DSASigner
+ // {
+ // public detDSA256()
+ // {
+ // super(new SHA256Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA256Digest())));
+ // }
+ // }
+ //
// static public class dsa384
// extends DSASigner
// {
@@ -259,6 +293,15 @@ public class DSASigner
// }
// }
//
+ // static public class detDSA384
+ // extends DSASigner
+ // {
+ // public detDSA384()
+ // {
+ // super(new SHA384Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA384Digest())));
+ // }
+ // }
+ //
// static public class dsa512
// extends DSASigner
// {
@@ -267,6 +310,15 @@ public class DSASigner
// super(new SHA512Digest(), new org.bouncycastle.crypto.signers.DSASigner());
// }
// }
+ //
+ // static public class detDSA512
+ // extends DSASigner
+ // {
+ // public detDSA512()
+ // {
+ // super(new SHA512Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA512Digest())));
+ // }
+ // }
// END android-removed
static public class noneDSA
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java
index 3d64c83..45d5b08 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java
@@ -13,16 +13,11 @@ import java.util.Enumeration;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-// BEGIN android-removed
-// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
-// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
-// END android-removed
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
@@ -140,8 +135,8 @@ public class BCECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
@@ -173,22 +168,16 @@ public class BCECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
else
{
EllipticCurve ellipticCurve = EC5Util.convertCurve(spec.getCurve(), spec.getSeed());
-
- this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
- spec.getN(),
- spec.getH().intValue());
+
+ this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec);
}
publicKey = getPublicKeyDetails(pubKey);
@@ -225,36 +214,16 @@ public class BCECPrivateKey
{
ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);
-
- // BEGIN android-removed
- // if (ecP == null) // GOST Curve
- // {
- // ECDomainParameters gParam = ECGOST3410NamedCurves.getByOID(oid);
- // EllipticCurve ellipticCurve = EC5Util.convertCurve(gParam.getCurve(), gParam.getSeed());
- //
- // ecSpec = new ECNamedCurveSpec(
- // ECGOST3410NamedCurves.getName(oid),
- // ellipticCurve,
- // new ECPoint(
- // gParam.getG().getX().toBigInteger(),
- // gParam.getG().getY().toBigInteger()),
- // gParam.getN(),
- // gParam.getH());
- // }
- // else
- // END android-removed
- {
- EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
-
- ecSpec = new ECNamedCurveSpec(
- ECUtil.getCurveName(oid),
- ellipticCurve,
- new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
- ecP.getN(),
- ecP.getH());
- }
+ EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
+
+ ecSpec = new ECNamedCurveSpec(
+ ECUtil.getCurveName(oid),
+ ellipticCurve,
+ new ECPoint(
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
+ ecP.getN(),
+ ecP.getH());
}
else if (params.isImplicitlyCA())
{
@@ -268,16 +237,16 @@ public class BCECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH().intValue());
}
ASN1Encodable privKey = info.parsePrivateKey();
- if (privKey instanceof DERInteger)
+ if (privKey instanceof ASN1Integer)
{
- DERInteger derD = DERInteger.getInstance(privKey);
+ ASN1Integer derD = ASN1Integer.getInstance(privKey);
this.d = derD.getValue();
}
@@ -317,11 +286,12 @@ public class BCECPrivateKey
if (ecSpec instanceof ECNamedCurveSpec)
{
- DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName());
+ ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName());
if (curveOid == null) // guess it's the OID
{
- curveOid = new DERObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName());
+ curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName());
}
+
params = new X962Parameters(curveOid);
}
else if (ecSpec == null)
@@ -356,17 +326,7 @@ public class BCECPrivateKey
try
{
- // BEGIN android-removed
- // if (algorithm.equals("ECGOST3410"))
- // {
- // info = new PrivateKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params.toASN1Primitive()), keyStructure.toASN1Primitive());
- // }
- // else
- // END android-removed
- {
-
- info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.toASN1Primitive()), keyStructure.toASN1Primitive());
- }
+ info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), keyStructure);
return info.getEncoded(ASN1Encoding.DER);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java
index 2b61727..0eaae1d 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java
@@ -90,7 +90,7 @@ public class BCECPublicKey
{
org.bouncycastle.jce.spec.ECParameterSpec s = configuration.getEcImplicitlyCa();
- q = s.getCurve().createPoint(q.getX().toBigInteger(), q.getY().toBigInteger(), false);
+ q = s.getCurve().createPoint(q.getXCoord().toBigInteger(), q.getYCoord().toBigInteger(), false);
}
this.ecSpec = null;
}
@@ -188,8 +188,8 @@ public class BCECPublicKey
return new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
@@ -212,8 +212,8 @@ public class BCECPublicKey
ECUtil.getCurveName(oid),
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH());
}
@@ -232,8 +232,8 @@ public class BCECPublicKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH().intValue());
}
@@ -310,8 +310,19 @@ public class BCECPublicKey
}
ECCurve curve = this.engineGetQ().getCurve();
- ASN1OctetString p = (ASN1OctetString)
- new X9ECPoint(curve.createPoint(this.getQ().getX().toBigInteger(), this.getQ().getY().toBigInteger(), withCompression)).toASN1Primitive();
+ ASN1OctetString p;
+
+ // stored curve is null if ImplicitlyCa
+ if (ecSpec == null)
+ {
+ p = (ASN1OctetString)
+ new X9ECPoint(curve.createPoint(this.getQ().getXCoord().toBigInteger(), this.getQ().getYCoord().toBigInteger(), withCompression)).toASN1Primitive();
+ }
+ else
+ {
+ p = (ASN1OctetString)
+ new X9ECPoint(curve.createPoint(this.getQ().getAffineXCoord().toBigInteger(), this.getQ().getAffineYCoord().toBigInteger(), withCompression)).toASN1Primitive();
+ }
info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets());
@@ -351,7 +362,7 @@ public class BCECPublicKey
public ECPoint getW()
{
- return new ECPoint(q.getX().toBigInteger(), q.getY().toBigInteger());
+ return new ECPoint(q.getAffineXCoord().toBigInteger(), q.getAffineYCoord().toBigInteger());
}
public org.bouncycastle.math.ec.ECPoint getQ()
@@ -360,11 +371,11 @@ public class BCECPublicKey
{
if (q instanceof org.bouncycastle.math.ec.ECPoint.Fp)
{
- return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getX(), q.getY());
+ return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getAffineXCoord(), q.getAffineYCoord());
}
else
{
- return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getX(), q.getY());
+ return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getAffineXCoord(), q.getAffineYCoord());
}
}
@@ -392,8 +403,8 @@ public class BCECPublicKey
String nl = System.getProperty("line.separator");
buf.append("EC Public Key").append(nl);
- buf.append(" X: ").append(this.q.getX().toBigInteger().toString(16)).append(nl);
- buf.append(" Y: ").append(this.q.getY().toBigInteger().toString(16)).append(nl);
+ buf.append(" X: ").append(this.q.getAffineXCoord().toBigInteger().toString(16)).append(nl);
+ buf.append(" Y: ").append(this.q.getAffineYCoord().toBigInteger().toString(16)).append(nl);
return buf.toString();
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java
index 35a804c..ea36dfd 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java
@@ -15,7 +15,7 @@ import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;
-import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x9.X9IntegerConverter;
@@ -84,7 +84,7 @@ public class KeyAgreementSpi
private byte[] bigIntToBytes(
BigInteger r)
{
- return converter.integerToBytes(r, converter.getByteLength(parameters.getG().getX()));
+ return converter.integerToBytes(r, converter.getByteLength(parameters.getG().getAffineXCoord()));
}
protected KeyAgreementSpi(
@@ -197,10 +197,10 @@ public class KeyAgreementSpi
// {
// throw new NoSuchAlgorithmException("unknown algorithm encountered: " + algorithm);
// }
- //
+ //
// int keySize = ((Integer)algorithms.get(algorithm)).intValue();
//
- // DHKDFParameters params = new DHKDFParameters(new DERObjectIdentifier(algorithm), keySize, secret);
+ // DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(algorithm), keySize, secret);
//
// byte[] keyBytes = new byte[keySize / 8];
// kdf.init(params);
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java
index c0c825c..42bb895 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java
@@ -10,12 +10,7 @@ import java.security.spec.ECGenParameterSpec;
import java.util.Hashtable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.nist.NISTNamedCurves;
-import org.bouncycastle.asn1.sec.SECNamedCurves;
-// BEGIN android-removed
-// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
-// END android-removed
-import org.bouncycastle.asn1.x9.X962NamedCurves;
+import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
@@ -161,51 +156,23 @@ public abstract class KeyPairGeneratorSpi
curveName = ((ECNamedCurveGenParameterSpec)params).getName();
}
- X9ECParameters ecP = X962NamedCurves.getByName(curveName);
+ X9ECParameters ecP = ECNamedCurveTable.getByName(curveName);
if (ecP == null)
{
- ecP = SECNamedCurves.getByName(curveName);
- if (ecP == null)
+ // See if it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug)
+ try
{
- ecP = NISTNamedCurves.getByName(curveName);
- }
- // BEGIN android-removed
- // if (ecP == null)
- // {
- // ecP = TeleTrusTNamedCurves.getByName(curveName);
- // }
- // END android-removed
- if (ecP == null)
- {
- // See if it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug)
- try
- {
- ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(curveName);
- ecP = X962NamedCurves.getByOID(oid);
- if (ecP == null)
- {
- ecP = SECNamedCurves.getByOID(oid);
- }
- if (ecP == null)
- {
- ecP = NISTNamedCurves.getByOID(oid);
- }
- // BEGIN android-removed
- // if (ecP == null)
- // {
- // ecP = TeleTrusTNamedCurves.getByOID(oid);
- // }
- // END android-removed
- if (ecP == null)
- {
- throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName);
- }
- }
- catch (IllegalArgumentException ex)
+ ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(curveName);
+ ecP = ECNamedCurveTable.getByOID(oid);
+ if (ecP == null)
{
- throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
+ throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName);
}
}
+ catch (IllegalArgumentException ex)
+ {
+ throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
+ }
}
this.ecParams = new ECNamedCurveSpec(
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java
index 09cba7c..3757229 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java
@@ -31,6 +31,7 @@ import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.ECDSASigner;
// BEGIN android-removed
// import org.bouncycastle.crypto.signers.ECNRSigner;
+// import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
// END android-removed
import org.bouncycastle.jcajce.provider.asymmetric.util.DSABase;
import org.bouncycastle.jcajce.provider.asymmetric.util.DSAEncoder;
@@ -82,6 +83,17 @@ public class SignatureSpi
}
}
+ // BEGIN android-removed
+ // static public class ecDetDSA
+ // extends SignatureSpi
+ // {
+ // public ecDetDSA()
+ // {
+ // super(new SHA1Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA1Digest())), new StdDSAEncoder());
+ // }
+ // }
+ // END android-removed
+
static public class ecDSAnone
extends SignatureSpi
{
@@ -102,6 +114,17 @@ public class SignatureSpi
}
}
+ // BEGIN android-removed
+ // static public class ecDetDSA224
+ // extends SignatureSpi
+ // {
+ // public ecDetDSA224()
+ // {
+ // super(new SHA224Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA224Digest())), new StdDSAEncoder());
+ // }
+ // }
+ // END android-removed
+
static public class ecDSA256
extends SignatureSpi
{
@@ -113,6 +136,17 @@ public class SignatureSpi
}
}
+ // BEGIN android-removed
+ // static public class ecDetDSA256
+ // extends SignatureSpi
+ // {
+ // public ecDetDSA256()
+ // {
+ // super(new SHA256Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest())), new StdDSAEncoder());
+ // }
+ // }
+ // END android-removed
+
static public class ecDSA384
extends SignatureSpi
{
@@ -124,6 +158,17 @@ public class SignatureSpi
}
}
+ // BEGIN android-removed
+ // static public class ecDetDSA384
+ // extends SignatureSpi
+ // {
+ // public ecDetDSA384()
+ // {
+ // super(new SHA384Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA384Digest())), new StdDSAEncoder());
+ // }
+ // }
+ // END android-removed
+
static public class ecDSA512
extends SignatureSpi
{
@@ -136,6 +181,15 @@ public class SignatureSpi
}
// BEGIN android-removed
+ // static public class ecDetDSA512
+ // extends SignatureSpi
+ // {
+ // public ecDetDSA512()
+ // {
+ // super(new SHA512Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA512Digest())), new StdDSAEncoder());
+ // }
+ // }
+ //
// static public class ecDSARipeMD160
// extends SignatureSpi
// {
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java
index ce0e603..a2114fa 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java
@@ -1,6 +1,9 @@
package org.bouncycastle.jcajce.provider.asymmetric.rsa;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OptionalDataException;
import java.math.BigInteger;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;
@@ -15,14 +18,18 @@ import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
public class BCRSAPublicKey
implements RSAPublicKey
{
+ private static final AlgorithmIdentifier DEFAULT_ALGORITHM_IDENTIFIER = new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE);
+
static final long serialVersionUID = 2675817738516720772L;
-
+
private BigInteger modulus;
private BigInteger publicExponent;
+ private transient AlgorithmIdentifier algorithmIdentifier;
BCRSAPublicKey(
RSAKeyParameters key)
{
+ this.algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER;
this.modulus = key.getModulus();
this.publicExponent = key.getExponent();
}
@@ -30,6 +37,7 @@ public class BCRSAPublicKey
BCRSAPublicKey(
RSAPublicKeySpec spec)
{
+ this.algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER;
this.modulus = spec.getModulus();
this.publicExponent = spec.getPublicExponent();
}
@@ -37,6 +45,7 @@ public class BCRSAPublicKey
BCRSAPublicKey(
RSAPublicKey key)
{
+ this.algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER;
this.modulus = key.getModulus();
this.publicExponent = key.getPublicExponent();
}
@@ -44,10 +53,16 @@ public class BCRSAPublicKey
BCRSAPublicKey(
SubjectPublicKeyInfo info)
{
+ populateFromPublicKeyInfo(info);
+ }
+
+ private void populateFromPublicKeyInfo(SubjectPublicKeyInfo info)
+ {
try
{
org.bouncycastle.asn1.pkcs.RSAPublicKey pubKey = org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(info.parsePublicKey());
+ this.algorithmIdentifier = info.getAlgorithm();
this.modulus = pubKey.getModulus();
this.publicExponent = pubKey.getPublicExponent();
}
@@ -89,7 +104,7 @@ public class BCRSAPublicKey
public byte[] getEncoded()
{
- return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), new org.bouncycastle.asn1.pkcs.RSAPublicKey(getModulus(), getPublicExponent()));
+ return KeyUtil.getEncodedSubjectPublicKeyInfo(algorithmIdentifier, new org.bouncycastle.asn1.pkcs.RSAPublicKey(getModulus(), getPublicExponent()));
}
public int hashCode()
@@ -126,4 +141,32 @@ public class BCRSAPublicKey
return buf.toString();
}
+
+ private void readObject(
+ ObjectInputStream in)
+ throws IOException, ClassNotFoundException
+ {
+ in.defaultReadObject();
+
+ try
+ {
+ algorithmIdentifier = AlgorithmIdentifier.getInstance(in.readObject());
+ }
+ catch (OptionalDataException e)
+ {
+ algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER;
+ }
+ }
+
+ private void writeObject(
+ ObjectOutputStream out)
+ throws IOException
+ {
+ out.defaultWriteObject();
+
+ if (!algorithmIdentifier.equals(DEFAULT_ALGORITHM_IDENTIFIER))
+ {
+ out.writeObject(algorithmIdentifier.getEncoded());
+ }
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java
index d4065ac..5eea1b9 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java
@@ -74,8 +74,8 @@ public class EC5Util
((ECNamedCurveParameterSpec)spec).getName(),
ellipticCurve,
new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
+ spec.getG().getAffineXCoord().toBigInteger(),
+ spec.getG().getAffineYCoord().toBigInteger()),
spec.getN(),
spec.getH());
}
@@ -84,8 +84,8 @@ public class EC5Util
return new ECParameterSpec(
ellipticCurve,
new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
+ spec.getG().getAffineXCoord().toBigInteger(),
+ spec.getG().getAffineYCoord().toBigInteger()),
spec.getN(),
spec.getH().intValue());
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java
index 1888328..32e595c 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java
@@ -31,7 +31,7 @@ import org.bouncycastle.asn1.x509.X509Extension;
* ReasonCode Hode Instruction Code Invalidity Date Certificate Issuer
* (critical)
*/
-class X509CRLEntryObject extends X509CRLEntry
+public class X509CRLEntryObject extends X509CRLEntry
{
private TBSCertList.CRLEntry c;
@@ -39,7 +39,7 @@ class X509CRLEntryObject extends X509CRLEntry
private int hashValue;
private boolean isHashValueSet;
- public X509CRLEntryObject(TBSCertList.CRLEntry c)
+ protected X509CRLEntryObject(TBSCertList.CRLEntry c)
{
this.c = c;
this.certificateIssuer = null;
@@ -62,7 +62,7 @@ class X509CRLEntryObject extends X509CRLEntry
* @param previousCertificateIssuer
* Certificate issuer of the previous CRLEntry.
*/
- public X509CRLEntryObject(
+ protected X509CRLEntryObject(
TBSCertList.CRLEntry c,
boolean isIndirect,
X500Name previousCertificateIssuer)
@@ -211,6 +211,23 @@ class X509CRLEntryObject extends X509CRLEntry
return hashValue;
}
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (o instanceof X509CRLEntryObject)
+ {
+ X509CRLEntryObject other = (X509CRLEntryObject)o;
+
+ return this.c.equals(other.c);
+ }
+
+ return super.equals(this);
+ }
+
public byte[] getEncoded()
throws CRLException
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java
index 2fc0826..c7d0402 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java
@@ -54,13 +54,15 @@ import org.bouncycastle.util.encoders.Hex;
* Delta CRL Indicator (critical)
* Issuing Distribution Point (critical)
*/
-class X509CRLObject
+public class X509CRLObject
extends X509CRL
{
private CertificateList c;
private String sigAlgName;
private byte[] sigAlgParams;
private boolean isIndirect;
+ private boolean isHashCodeSet = false;
+ private int hashCodeValue;
static boolean isIndirectCRL(X509CRL crl)
throws CRLException
@@ -78,7 +80,7 @@ class X509CRLObject
}
}
- public X509CRLObject(
+ protected X509CRLObject(
CertificateList c)
throws CRLException
{
@@ -522,19 +524,21 @@ class X509CRLObject
throw new RuntimeException("X.509 CRL used with non X.509 Cert");
}
- TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
+ Enumeration certs = c.getRevokedCertificateEnumeration();
X500Name caName = c.getIssuer();
- if (certs != null)
+ if (certs.hasMoreElements())
{
BigInteger serial = ((X509Certificate)cert).getSerialNumber();
- for (int i = 0; i < certs.length; i++)
+ while (certs.hasMoreElements())
{
- if (isIndirect && certs[i].hasExtensions())
+ TBSCertList.CRLEntry entry = TBSCertList.CRLEntry.getInstance(certs.nextElement());
+
+ if (isIndirect && entry.hasExtensions())
{
- Extension currentCaName = certs[i].getExtensions().getExtension(Extension.certificateIssuer);
+ Extension currentCaName = entry.getExtensions().getExtension(Extension.certificateIssuer);
if (currentCaName != null)
{
@@ -542,7 +546,7 @@ class X509CRLObject
}
}
- if (certs[i].getUserCertificate().getValue().equals(serial))
+ if (entry.getUserCertificate().getValue().equals(serial))
{
X500Name issuer;
@@ -574,5 +578,50 @@ class X509CRLObject
return false;
}
+
+ public boolean equals(Object other)
+ {
+ if (this == other)
+ {
+ return true;
+ }
+
+ if (!(other instanceof X509CRL))
+ {
+ return false;
+ }
+
+ if (other instanceof X509CRLObject)
+ {
+ X509CRLObject crlObject = (X509CRLObject)other;
+
+ if (isHashCodeSet)
+ {
+ boolean otherIsHashCodeSet = crlObject.isHashCodeSet;
+ if (otherIsHashCodeSet)
+ {
+ if (crlObject.hashCodeValue != hashCodeValue)
+ {
+ return false;
+ }
+ }
+ }
+
+ return this.c.equals(crlObject.c);
+ }
+
+ return super.equals(other);
+ }
+
+ public int hashCode()
+ {
+ if (!isHashCodeSet)
+ {
+ isHashCodeSet = true;
+ hashCodeValue = super.hashCode();
+ }
+
+ return hashCodeValue;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java
index df5d41a..c7502c7 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java
@@ -193,7 +193,6 @@ public class SHA1
provider.addAlgorithm("SecretKeyFactory.PBEWITHHMACSHA1", PREFIX + "$PBEWithMacKeyFactory");
provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1", PREFIX + "$PBKDF2WithHmacSHA1UTF8");
- provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.id_PBKDF2, "PBKDF2WithHmacSHA1");
provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WithHmacSHA1AndUTF8", "PBKDF2WithHmacSHA1");
provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1And8BIT", PREFIX + "$PBKDF2WithHmacSHA18BIT");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
index 0d4f0ad..24dac19 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
@@ -6,6 +6,8 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStore.LoadStoreParameter;
@@ -24,13 +26,18 @@ import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Hashtable;
+import java.util.Map;
import java.util.Vector;
import javax.crypto.Cipher;
import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
@@ -54,6 +61,12 @@ import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DEROutputStream;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERSet;
+// BEGIN android-removed
+// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// import org.bouncycastle.asn1.cryptopro.GOST28147Parameters;
+// END android-removed
+import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.AuthenticatedSafe;
import org.bouncycastle.asn1.pkcs.CertBag;
import org.bouncycastle.asn1.pkcs.ContentInfo;
@@ -75,12 +88,16 @@ import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.jcajce.provider.config.PKCS12StoreParameter;
import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
-import org.bouncycastle.jcajce.provider.util.SecretKeyUtil;
+// BEGIN android-removed
+// import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
+// END android-removed
+import org.bouncycastle.jcajce.spec.PBKDF2KeySpec;
import org.bouncycastle.jce.interfaces.BCKeyStore;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.provider.JDKPKCS12StoreParameter;
import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Integers;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.encoders.Hex;
@@ -92,6 +109,7 @@ public class PKCS12KeyStoreSpi
private static final int MIN_ITERATIONS = 1024;
private static final Provider bcProvider = new BouncyCastleProvider();
+ private static final DefaultSecretKeyProvider keySizeProvider = new DefaultSecretKeyProvider();
private IgnoresCaseHashtable keys = new IgnoresCaseHashtable();
private Hashtable localIds = new Hashtable();
@@ -593,16 +611,8 @@ public class PKCS12KeyStoreSpi
}
else if (algorithm.equals(PKCSObjectIdentifiers.id_PBES2))
{
- PBES2Parameters alg = PBES2Parameters.getInstance(algId.getParameters());
- PBKDF2Params func = PBKDF2Params.getInstance(alg.getKeyDerivationFunc().getParameters());
- SecretKeyFactory keyFact = SecretKeyFactory.getInstance(alg.getKeyDerivationFunc().getAlgorithm().getId(), bcProvider);
-
- SecretKey k = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), func.getIterationCount().intValue(), SecretKeyUtil.getKeySize(alg.getEncryptionScheme().getAlgorithm())));
-
- Cipher cipher = Cipher.getInstance(alg.getEncryptionScheme().getAlgorithm().getId(), bcProvider);
-
- cipher.init(Cipher.UNWRAP_MODE, k, new IvParameterSpec(ASN1OctetString.getInstance(alg.getEncryptionScheme().getParameters()).getOctets()));
+ Cipher cipher = createCipher(Cipher.UNWRAP_MODE, password, algId);
// we pass "" as the key algorithm type as it is unknown at this point
return (PrivateKey)cipher.unwrap(data, "", Cipher.PRIVATE_KEY);
@@ -656,31 +666,92 @@ public class PKCS12KeyStoreSpi
byte[] data)
throws IOException
{
- String algorithm = algId.getAlgorithm().getId();
- PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters());
- PBEKeySpec pbeSpec = new PBEKeySpec(password);
+ ASN1ObjectIdentifier algorithm = algId.getAlgorithm();
- try
+ if (algorithm.on(PKCSObjectIdentifiers.pkcs_12PbeIds))
{
- SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm, bcProvider);
- PBEParameterSpec defParams = new PBEParameterSpec(
- pbeParams.getIV(),
- pbeParams.getIterations().intValue());
- BCPBEKey key = (BCPBEKey)keyFact.generateSecret(pbeSpec);
+ PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters());
+ PBEKeySpec pbeSpec = new PBEKeySpec(password);
- key.setTryWrongPKCS12Zero(wrongPKCS12Zero);
+ try
+ {
+ SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm.getId(), bcProvider);
+ PBEParameterSpec defParams = new PBEParameterSpec(
+ pbeParams.getIV(),
+ pbeParams.getIterations().intValue());
+ BCPBEKey key = (BCPBEKey)keyFact.generateSecret(pbeSpec);
- Cipher cipher = Cipher.getInstance(algorithm, bcProvider);
- int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
- cipher.init(mode, key, defParams);
- return cipher.doFinal(data);
+ key.setTryWrongPKCS12Zero(wrongPKCS12Zero);
+
+ Cipher cipher = Cipher.getInstance(algorithm.getId(), bcProvider);
+ int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
+ cipher.init(mode, key, defParams);
+ return cipher.doFinal(data);
+ }
+ catch (Exception e)
+ {
+ throw new IOException("exception decrypting data - " + e.toString());
+ }
}
- catch (Exception e)
+ else if (algorithm.equals(PKCSObjectIdentifiers.id_PBES2))
{
- throw new IOException("exception decrypting data - " + e.toString());
+ try
+ {
+ Cipher cipher = createCipher(Cipher.DECRYPT_MODE, password, algId);
+
+ return cipher.doFinal(data);
+ }
+ catch (Exception e)
+ {
+ throw new IOException("exception decrypting data - " + e.toString());
+ }
+ }
+ else
+ {
+ throw new IOException("unknown PBE algorithm: " + algorithm);
}
}
+ private Cipher createCipher(int mode, char[] password, AlgorithmIdentifier algId)
+ throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ PBES2Parameters alg = PBES2Parameters.getInstance(algId.getParameters());
+ PBKDF2Params func = PBKDF2Params.getInstance(alg.getKeyDerivationFunc().getParameters());
+ AlgorithmIdentifier encScheme = AlgorithmIdentifier.getInstance(alg.getEncryptionScheme());
+
+ SecretKeyFactory keyFact = SecretKeyFactory.getInstance(alg.getKeyDerivationFunc().getAlgorithm().getId(), bcProvider);
+ SecretKey key;
+
+ if (func.isDefaultPrf())
+ {
+ key = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme)));
+ }
+ else
+ {
+ key = keyFact.generateSecret(new PBKDF2KeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme), func.getPrf()));
+ }
+
+ Cipher cipher = Cipher.getInstance(alg.getEncryptionScheme().getAlgorithm().getId());
+
+ AlgorithmIdentifier encryptionAlg = AlgorithmIdentifier.getInstance(alg.getEncryptionScheme());
+
+ ASN1Encodable encParams = alg.getEncryptionScheme().getParameters();
+ if (encParams instanceof ASN1OctetString)
+ {
+ cipher.init(mode, key, new IvParameterSpec(ASN1OctetString.getInstance(encParams).getOctets()));
+ }
+ // BEGIN android-removed
+ // else
+ // {
+ // // TODO: at the moment it's just GOST, but...
+ // GOST28147Parameters gParams = GOST28147Parameters.getInstance(encParams);
+ //
+ // cipher.init(mode, key, new GOST28147ParameterSpec(gParams.getEncryptionParamSet(), gParams.getIV()));
+ // }
+ // END android-removed
+ return cipher;
+ }
+
public void engineLoad(
InputStream stream,
char[] password)
@@ -1673,4 +1744,45 @@ public class PKCS12KeyStoreSpi
return orig.elements();
}
}
+
+ private static class DefaultSecretKeyProvider
+ {
+ private final Map KEY_SIZES;
+
+ DefaultSecretKeyProvider()
+ {
+ Map keySizes = new HashMap();
+
+ keySizes.put(new ASN1ObjectIdentifier("1.2.840.113533.7.66.10"), Integers.valueOf(128));
+
+ keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), Integers.valueOf(192));
+
+ keySizes.put(NISTObjectIdentifiers.id_aes128_CBC, Integers.valueOf(128));
+ keySizes.put(NISTObjectIdentifiers.id_aes192_CBC, Integers.valueOf(192));
+ keySizes.put(NISTObjectIdentifiers.id_aes256_CBC, Integers.valueOf(256));
+
+ keySizes.put(NTTObjectIdentifiers.id_camellia128_cbc, Integers.valueOf(128));
+ keySizes.put(NTTObjectIdentifiers.id_camellia192_cbc, Integers.valueOf(192));
+ keySizes.put(NTTObjectIdentifiers.id_camellia256_cbc, Integers.valueOf(256));
+
+ // BEGIN android-removed
+ // keySizes.put(CryptoProObjectIdentifiers.gostR28147_gcfb, Integers.valueOf(256));
+ // END android-removed
+
+ KEY_SIZES = Collections.unmodifiableMap(keySizes);
+ }
+
+ public int getKeySize(AlgorithmIdentifier algorithmIdentifier)
+ {
+ // TODO: not all ciphers/oid relationships are this simple.
+ Integer keySize = (Integer)KEY_SIZES.get(algorithmIdentifier.getAlgorithm());
+
+ if (keySize != null)
+ {
+ return keySize.intValue();
+ }
+
+ return -1;
+ }
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java
index f561b8a..500bf2d 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java
@@ -1,17 +1,22 @@
package org.bouncycastle.jcajce.provider.symmetric;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
// BEGIN android-removed
// import java.security.AlgorithmParameters;
// import java.security.InvalidAlgorithmParameterException;
// END android-removed
import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
// BEGIN android-removed
-// import java.security.spec.AlgorithmParameterSpec;
-//
// import javax.crypto.spec.IvParameterSpec;
// END android-removed
import org.bouncycastle.asn1.bc.BCObjectIdentifiers;
+import org.bouncycastle.asn1.cms.GCMParameters;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
@@ -20,6 +25,7 @@ import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.engines.AESWrapEngine;
// BEGIN android-removed
// import org.bouncycastle.crypto.engines.RFC3211WrapEngine;
+// import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
// import org.bouncycastle.crypto.macs.CMac;
// import org.bouncycastle.crypto.macs.GMac;
// END android-removed
@@ -31,6 +37,7 @@ import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
// BEGIN android-removed
// import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameterGenerator;
// END android-removed
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameters;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
// BEGIN android-removed
@@ -43,9 +50,12 @@ import org.bouncycastle.jcajce.provider.symmetric.util.PBESecretKeyFactory;
// BEGIN android-removed
// import org.bouncycastle.jce.provider.BouncyCastleProvider;
// END android-removed
+import org.bouncycastle.util.Integers;
public final class AES
{
+ private static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec");
+
private AES()
{
}
@@ -92,6 +102,15 @@ public final class AES
}
}
+ static public class GCM
+ extends BaseBlockCipher
+ {
+ public GCM()
+ {
+ super(new GCMBlockCipher(new AESFastEngine()));
+ }
+ }
+
// BEGIN android-removed
// public static class AESCMAC
// extends BaseMac
@@ -110,6 +129,24 @@ public final class AES
// super(new GMac(new GCMBlockCipher(new AESFastEngine())));
// }
// }
+ //
+ // public static class Poly1305
+ // extends BaseMac
+ // {
+ // public Poly1305()
+ // {
+ // super(new org.bouncycastle.crypto.macs.Poly1305(new AESFastEngine()));
+ // }
+ // }
+ //
+ // public static class Poly1305KeyGen
+ // extends BaseKeyGenerator
+ // {
+ // public Poly1305KeyGen()
+ // {
+ // super("Poly1305-AES", 256, new Poly1305KeyGenerator());
+ // }
+ // }
// END android-removed
static public class Wrap
@@ -345,6 +382,95 @@ public final class AES
}
}
+ public static class AlgParamsGCM
+ extends BaseAlgorithmParameters
+ {
+ private GCMParameters gcmParams;
+
+ protected void engineInit(AlgorithmParameterSpec paramSpec)
+ throws InvalidParameterSpecException
+ {
+ if (gcmSpecClass != null)
+ {
+ try
+ {
+ Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]);
+ Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]);
+
+
+ gcmParams = new GCMParameters((byte[])iv.invoke(paramSpec, new Object[0]), ((Integer)tLen.invoke(paramSpec, new Object[0])).intValue());
+ }
+ catch (Exception e)
+ {
+ throw new InvalidParameterSpecException("Cannot process GCMParameterSpec.");
+ }
+ }
+ }
+
+ protected void engineInit(byte[] params)
+ throws IOException
+ {
+ gcmParams = GCMParameters.getInstance(params);
+ }
+
+ protected void engineInit(byte[] params, String format)
+ throws IOException
+ {
+ if (!isASN1FormatString(format))
+ {
+ throw new IOException("unknown format specified");
+ }
+
+ gcmParams = GCMParameters.getInstance(params);
+ }
+
+ protected byte[] engineGetEncoded()
+ throws IOException
+ {
+ return gcmParams.getEncoded();
+ }
+
+ protected byte[] engineGetEncoded(String format)
+ throws IOException
+ {
+ if (!isASN1FormatString(format))
+ {
+ throw new IOException("unknown format specified");
+ }
+
+ return gcmParams.getEncoded();
+ }
+
+ protected String engineToString()
+ {
+ return "GCM";
+ }
+
+ protected AlgorithmParameterSpec localEngineGetParameterSpec(Class paramSpec)
+ throws InvalidParameterSpecException
+ {
+ if (gcmSpecClass != null)
+ {
+ try
+ {
+ Constructor constructor = gcmSpecClass.getConstructor(new Class[] { byte[].class, Integer.class });
+
+ return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { gcmParams.getNonce(), Integers.valueOf(gcmParams.getIcvLen()) });
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new InvalidParameterSpecException("no constructor found!"); // should never happen
+ }
+ catch (Exception e)
+ {
+ throw new InvalidParameterSpecException("construction failed: " + e.getMessage()); // should never happen
+ }
+ }
+
+ throw new InvalidParameterSpecException("unknown parameter spec: " + paramSpec.getName());
+ }
+ }
+
public static class Mappings
extends SymmetricAlgorithmProvider
{
@@ -373,6 +499,11 @@ public final class AES
provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes192_CBC, "AES");
provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes256_CBC, "AES");
+ provider.addAlgorithm("AlgorithmParameters.GCM", PREFIX + "$AlgParamsGCM");
+ provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes128_GCM, "GCM");
+ provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes192_GCM, "GCM");
+ provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes256_GCM, "GCM");
+
// BEGIN android-removed
// provider.addAlgorithm("AlgorithmParameterGenerator.AES", PREFIX + "$AlgParamGen");
// provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + wrongAES128, "AES");
@@ -409,6 +540,11 @@ public final class AES
// provider.addAlgorithm("Cipher.AESRFC3211WRAP", PREFIX + "$RFC3211Wrap");
// END android-removed
+ provider.addAlgorithm("Cipher.GCM", PREFIX + "$GCM");
+ provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes128_GCM, "GCM");
+ provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes192_GCM, "GCM");
+ provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes256_GCM, "GCM");
+
provider.addAlgorithm("KeyGenerator.AES", PREFIX + "$KeyGen");
// BEGIN android-removed
// provider.addAlgorithm("KeyGenerator." + wrongAES128, PREFIX + "$KeyGen128");
@@ -513,7 +649,22 @@ public final class AES
// BEGIN android-removed
// addGMacAlgorithm(provider, "AES", PREFIX + "$AESGMAC", PREFIX + "$KeyGen128");
+ // addPoly1305Algorithm(provider, "AES", PREFIX + "$Poly1305", PREFIX + "$Poly1305KeyGen");
// END android-removed
}
}
+
+ private static Class lookup(String className)
+ {
+ try
+ {
+ Class def = AES.class.getClassLoader().loadClass(className);
+
+ return def;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java
index d96d5e6..fc34865 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java
@@ -19,5 +19,18 @@ abstract class SymmetricAlgorithmProvider
// provider.addAlgorithm("KeyGenerator." + algorithm + "-GMAC", keyGeneratorClassName);
// provider.addAlgorithm("Alg.Alias.KeyGenerator." + algorithm + "GMAC", algorithm + "-GMAC");
// }
+ //
+ // protected void addPoly1305Algorithm(ConfigurableProvider provider,
+ // String algorithm,
+ // String algorithmClassName,
+ // String keyGeneratorClassName)
+ // {
+ // provider.addAlgorithm("Mac.POLY1305-" + algorithm, algorithmClassName);
+ // provider.addAlgorithm("Alg.Alias.Mac.POLY1305" + algorithm, "POLY1305-" + algorithm);
+ //
+ // provider.addAlgorithm("KeyGenerator.POLY1305-" + algorithm, keyGeneratorClassName);
+ // provider.addAlgorithm("Alg.Alias.KeyGenerator.POLY1305" + algorithm, "POLY1305-" + algorithm);
+ // }
// END android-removed
+
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java
index dafdc39..e2b2efd 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java
@@ -6,6 +6,7 @@ package org.bouncycastle.jcajce.provider.symmetric;
// END android-removed
import org.bouncycastle.crypto.engines.TwofishEngine;
// BEGIN android-removed
+// import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
// import org.bouncycastle.crypto.macs.GMac;
// END android-removed
import org.bouncycastle.crypto.modes.CBCBlockCipher;
@@ -61,6 +62,24 @@ public final class Twofish
// super(new GMac(new GCMBlockCipher(new TwofishEngine())));
// }
// }
+ //
+ // public static class Poly1305
+ // extends BaseMac
+ // {
+ // public Poly1305()
+ // {
+ // super(new org.bouncycastle.crypto.macs.Poly1305(new TwofishEngine()));
+ // }
+ // }
+ //
+ // public static class Poly1305KeyGen
+ // extends BaseKeyGenerator
+ // {
+ // public Poly1305KeyGen()
+ // {
+ // super("Poly1305-Twofish", 256, new Poly1305KeyGenerator());
+ // }
+ // }
// END android-removed
/**
@@ -122,6 +141,7 @@ public final class Twofish
// BEGIN android-removed
// addGMacAlgorithm(provider, "Twofish", PREFIX + "$GMAC", PREFIX + "$KeyGen");
+ // addPoly1305Algorithm(provider, "Twofish", PREFIX + "$Poly1305", PREFIX + "$Poly1305KeyGen");
// END android-removed
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
index d342775..90d98b2 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
@@ -1,5 +1,7 @@
package org.bouncycastle.jcajce.provider.symmetric.util;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@@ -22,6 +24,7 @@ import javax.crypto.spec.PBEParameterSpec;
// import javax.crypto.spec.RC5ParameterSpec;
// END android-removed
+import org.bouncycastle.asn1.cms.GCMParameters;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
@@ -35,6 +38,7 @@ import org.bouncycastle.crypto.modes.CFBBlockCipher;
import org.bouncycastle.crypto.modes.CTSBlockCipher;
// BEGIN android-removed
// import org.bouncycastle.crypto.modes.EAXBlockCipher;
+// import org.bouncycastle.crypto.modes.GCFBBlockCipher;
// END android-removed
import org.bouncycastle.crypto.modes.GCMBlockCipher;
// BEGIN android-removed
@@ -54,6 +58,7 @@ import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.paddings.TBCPadding;
import org.bouncycastle.crypto.paddings.X923Padding;
import org.bouncycastle.crypto.paddings.ZeroBytePadding;
+import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.crypto.params.ParametersWithRandom;
@@ -63,18 +68,18 @@ import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.RC2Parameters;
// BEGIN android-removed
// import org.bouncycastle.crypto.params.RC5Parameters;
+// import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
+// import org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec;
// END android-removed
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-// BEGIN android-removed
-// import org.bouncycastle.jce.spec.GOST28147ParameterSpec;
-// END android-removed
-import org.bouncycastle.jce.spec.RepeatedSecretKeySpec;
import org.bouncycastle.util.Strings;
public class BaseBlockCipher
extends BaseWrapCipher
implements PBE
{
+ private static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec");
+
//
// specs we can handle.
//
@@ -87,14 +92,16 @@ public class BaseBlockCipher
IvParameterSpec.class,
PBEParameterSpec.class,
// BEGIN android-removed
- // GOST28147ParameterSpec.class
+ // GOST28147ParameterSpec.class,
// END android-removed
+ gcmSpecClass
};
private BlockCipher baseEngine;
private BlockCipherProvider engineProvider;
private GenericBlockCipher cipher;
private ParametersWithIV ivParam;
+ private AEADParameters aeadParams;
private int ivLength = 0;
@@ -105,6 +112,20 @@ public class BaseBlockCipher
private String modeName = null;
+ private static Class lookup(String className)
+ {
+ try
+ {
+ Class def = BaseBlockCipher.class.getClassLoader().loadClass(className);
+
+ return def;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
protected BaseBlockCipher(
BlockCipher engine)
{
@@ -123,6 +144,14 @@ public class BaseBlockCipher
}
protected BaseBlockCipher(
+ AEADBlockCipher engine)
+ {
+ baseEngine = engine.getUnderlyingCipher();
+ ivLength = baseEngine.getBlockSize();
+ cipher = new AEADGenericBlockCipher(engine);
+ }
+
+ protected BaseBlockCipher(
org.bouncycastle.crypto.BlockCipher engine,
int ivLength)
{
@@ -199,6 +228,18 @@ public class BaseBlockCipher
throw new RuntimeException(e.toString());
}
}
+ else if (aeadParams != null)
+ {
+ try
+ {
+ engineParams = AlgorithmParameters.getInstance("GCM", BouncyCastleProvider.PROVIDER_NAME);
+ engineParams.init(new GCMParameters(aeadParams.getNonce(), aeadParams.getMacSize()).getEncoded());
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.toString());
+ }
+ }
}
return engineParams;
@@ -257,7 +298,7 @@ public class BaseBlockCipher
// else if (modeName.startsWith("PGP"))
// {
// boolean inlineIV = modeName.equalsIgnoreCase("PGPCFBwithIV");
-
+ //
// ivLength = baseEngine.getBlockSize();
// cipher = new BufferedGenericBlockCipher(
// new PGPCFBBlockCipher(baseEngine, inlineIV));
@@ -268,17 +309,17 @@ public class BaseBlockCipher
// cipher = new BufferedGenericBlockCipher(
// new OpenPGPCFBBlockCipher(baseEngine));
// }
+ // else if (modeName.startsWith("SIC"))
+ // {
+ // ivLength = baseEngine.getBlockSize();
+ // if (ivLength < 16)
+ // {
+ // throw new IllegalArgumentException("Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)");
+ // }
+ // cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
+ // new SICBlockCipher(baseEngine)));
+ // }
// END android-removed
- else if (modeName.startsWith("SIC"))
- {
- ivLength = baseEngine.getBlockSize();
- if (ivLength < 16)
- {
- throw new IllegalArgumentException("Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)");
- }
- cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
- new SICBlockCipher(baseEngine)));
- }
else if (modeName.startsWith("CTR"))
{
ivLength = baseEngine.getBlockSize();
@@ -292,6 +333,12 @@ public class BaseBlockCipher
// cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
// new GOFBBlockCipher(baseEngine)));
// }
+ // else if (modeName.startsWith("GCFB"))
+ // {
+ // ivLength = baseEngine.getBlockSize();
+ // cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
+ // new GCFBBlockCipher(baseEngine)));
+ // }
// END android-removed
else if (modeName.startsWith("CTS"))
{
@@ -300,7 +347,7 @@ public class BaseBlockCipher
}
else if (modeName.startsWith("CCM"))
{
- ivLength = baseEngine.getBlockSize();
+ ivLength = 13; // CCM nonce 7..13 bytes
cipher = new AEADGenericBlockCipher(new CCMBlockCipher(baseEngine));
}
// BEGIN android-removed
@@ -308,7 +355,8 @@ public class BaseBlockCipher
// {
// if (engineProvider != null)
// {
- // ivLength = baseEngine.getBlockSize();
+ // // Nonce restricted to max 120 bits over 128 bit block cipher since draft-irtf-cfrg-ocb-03
+ // ivLength = 15;
// cipher = new AEADGenericBlockCipher(new OCBBlockCipher(baseEngine, engineProvider.get()));
// }
// else
@@ -401,6 +449,7 @@ public class BaseBlockCipher
this.pbeSpec = null;
this.pbeAlgorithm = null;
this.engineParams = null;
+ this.aeadParams = null;
//
// basic key check
@@ -443,6 +492,20 @@ public class BaseBlockCipher
param = new ParametersWithIV(param, iv.getIV());
}
+ // BEGIN android-removed
+ // else if (params instanceof GOST28147ParameterSpec)
+ // {
+ // // need to pick up IV and SBox.
+ // GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params;
+ //
+ // param = new ParametersWithSBox(param, gost28147Param.getSbox());
+ //
+ // if (gost28147Param.getIV() != null && ivLength != 0)
+ // {
+ // param = new ParametersWithIV(param, gost28147Param.getIV());
+ // }
+ // }
+ // END android-removed
}
else if (params instanceof PBEParameterSpec)
{
@@ -474,12 +537,14 @@ public class BaseBlockCipher
throw new InvalidAlgorithmParameterException("IV must be " + ivLength + " bytes long.");
}
- if (key instanceof RepeatedSecretKeySpec)
- {
- param = new ParametersWithIV(null, p.getIV());
- ivParam = (ParametersWithIV)param;
- }
- else
+ // BEGIN android-removed
+ // if (key instanceof RepeatedSecretKeySpec)
+ // {
+ // param = new ParametersWithIV(null, p.getIV());
+ // ivParam = (ParametersWithIV)param;
+ // }
+ // else
+ // END android-removed
{
param = new ParametersWithIV(new KeyParameter(key.getEncoded()), p.getIV());
ivParam = (ParametersWithIV)param;
@@ -554,12 +619,40 @@ public class BaseBlockCipher
// }
// }
// END android-removed
+ else if (gcmSpecClass != null && gcmSpecClass.isInstance(params))
+ {
+ if (!isAEADModeName(modeName) && !(cipher instanceof AEADGenericBlockCipher))
+ {
+ throw new InvalidAlgorithmParameterException("GCMParameterSpec can only be used with AEAD modes.");
+ }
+
+ try
+ {
+ Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]);
+ Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]);
+
+ // BEGIN android-removed
+ // if (key instanceof RepeatedSecretKeySpec)
+ // {
+ // param = aeadParams = new AEADParameters(null, ((Integer)tLen.invoke(params, new Object[0])).intValue(), (byte[])iv.invoke(params, new Object[0]));
+ // }
+ // else
+ // END android-removed
+ {
+ param = aeadParams = new AEADParameters(new KeyParameter(key.getEncoded()), ((Integer)tLen.invoke(params, new Object[0])).intValue(), (byte[])iv.invoke(params, new Object[0]));
+ }
+ }
+ catch (Exception e)
+ {
+ throw new InvalidAlgorithmParameterException("Cannot process GCMParameterSpec.");
+ }
+ }
else
{
throw new InvalidAlgorithmParameterException("unknown parameter type.");
}
- if ((ivLength != 0) && !(param instanceof ParametersWithIV))
+ if ((ivLength != 0) && !(param instanceof ParametersWithIV) && !(param instanceof AEADParameters))
{
SecureRandom ivRandom = random;
@@ -622,6 +715,11 @@ public class BaseBlockCipher
{
for (int i = 0; i != availableSpecs.length; i++)
{
+ if (availableSpecs[i] == null)
+ {
+ continue;
+ }
+
try
{
paramSpec = params.getParameterSpec(availableSpecs[i]);
@@ -660,6 +758,18 @@ public class BaseBlockCipher
}
}
+ protected void engineUpdateAAD(byte[] input, int offset, int length)
+ {
+ cipher.updateAAD(input, offset, length);
+ }
+
+ protected void engineUpdateAAD(ByteBuffer bytebuffer)
+ {
+ int offset = bytebuffer.arrayOffset() + bytebuffer.position();
+ int length = bytebuffer.limit() - bytebuffer.position();
+ engineUpdateAAD(bytebuffer.array(), offset, length);
+ }
+
protected byte[] engineUpdate(
byte[] input,
int inputOffset,
@@ -811,6 +921,8 @@ public class BaseBlockCipher
public int getUpdateOutputSize(int len);
+ public void updateAAD(byte[] input, int offset, int length);
+
public int processByte(byte in, byte[] out, int outOff)
throws DataLengthException;
@@ -872,6 +984,11 @@ public class BaseBlockCipher
return cipher.getUpdateOutputSize(len);
}
+ public void updateAAD(byte[] input, int offset, int length)
+ {
+ throw new UnsupportedOperationException("AAD is not supported in the current mode.");
+ }
+
public int processByte(byte in, byte[] out, int outOff) throws DataLengthException
{
return cipher.processByte(in, out, outOff);
@@ -929,6 +1046,11 @@ public class BaseBlockCipher
return cipher.getUpdateOutputSize(len);
}
+ public void updateAAD(byte[] input, int offset, int length)
+ {
+ cipher.processAADBytes(input, offset, length);
+ }
+
public int processByte(byte in, byte[] out, int outOff) throws DataLengthException
{
return cipher.processByte(in, out, outOff);
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java
index 442dcdd..d014972 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java
@@ -4,6 +4,9 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
import javax.crypto.MacSpi;
import javax.crypto.spec.IvParameterSpec;
@@ -13,6 +16,10 @@ import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
+// BEGIN android-removed
+// import org.bouncycastle.crypto.params.SkeinParameters;
+// import org.bouncycastle.jcajce.spec.SkeinParameterSpec;
+// END android-removed
public class BaseMac
extends MacSpi implements PBE
@@ -74,6 +81,12 @@ public class BaseMac
{
param = new ParametersWithIV(new KeyParameter(key.getEncoded()), ((IvParameterSpec)params).getIV());
}
+ // BEGIN android-removed
+ // else if (params instanceof SkeinParameterSpec)
+ // {
+ // param = new SkeinParameters.Builder(copyMap(((SkeinParameterSpec)params).getParameters())).setKey(key.getEncoded()).build();
+ // }
+ // END android-removed
else if (params == null)
{
param = new KeyParameter(key.getEncoded());
@@ -118,4 +131,18 @@ public class BaseMac
return out;
}
+
+ private static Hashtable copyMap(Map paramsMap)
+ {
+ Hashtable newTable = new Hashtable();
+
+ Iterator keys = paramsMap.keySet().iterator();
+ while (keys.hasNext())
+ {
+ Object key = keys.next();
+ newTable.put(key, paramsMap.get(key));
+ }
+
+ return newTable;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java
index 2031929..eb045bf 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java
@@ -3,6 +3,7 @@ package org.bouncycastle.jcajce.provider.symmetric.util;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
import java.security.Key;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
@@ -205,7 +206,7 @@ public class BaseStreamCipher
}
else
{
- throw new IllegalArgumentException("unknown parameter type.");
+ throw new InvalidAlgorithmParameterException("unknown parameter type.");
}
if ((ivLength != 0) && !(param instanceof ParametersWithIV))
@@ -231,18 +232,25 @@ public class BaseStreamCipher
}
}
- switch (opmode)
+ try
+ {
+ switch (opmode)
+ {
+ case Cipher.ENCRYPT_MODE:
+ case Cipher.WRAP_MODE:
+ cipher.init(true, param);
+ break;
+ case Cipher.DECRYPT_MODE:
+ case Cipher.UNWRAP_MODE:
+ cipher.init(false, param);
+ break;
+ default:
+ throw new InvalidParameterException("unknown opmode " + opmode + " passed");
+ }
+ }
+ catch (Exception e)
{
- case Cipher.ENCRYPT_MODE:
- case Cipher.WRAP_MODE:
- cipher.init(true, param);
- break;
- case Cipher.DECRYPT_MODE:
- case Cipher.UNWRAP_MODE:
- cipher.init(false, param);
- break;
- default:
- System.out.println("eeek!");
+ throw new InvalidKeyException(e.getMessage());
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
index 951beee..c39a2d3 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
@@ -87,7 +87,44 @@ public interface PBE
}
else if (type == PKCS5S2 || type == PKCS5S2_UTF8)
{
- generator = new PKCS5S2ParametersGenerator();
+ switch (hash)
+ {
+ // BEGIN android-removed
+ // case MD2:
+ // generator = new PKCS5S2ParametersGenerator(new MD2Digest());
+ // break;
+ // END android-removed
+ case MD5:
+ // BEGIN android-changed
+ generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getMD5());
+ // END android-changed
+ break;
+ case SHA1:
+ // BEGIN android-changed
+ generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA1());
+ // END android-changed
+ break;
+ // BEGIN android-removed
+ // case RIPEMD160:
+ // generator = new PKCS5S2ParametersGenerator(new RIPEMD160Digest());
+ // break;
+ // case TIGER:
+ // generator = new PKCS5S2ParametersGenerator(new TigerDigest());
+ // break;
+ // END android-removed
+ case SHA256:
+ // BEGIN android-changed
+ generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA256());
+ // END android-changed
+ break;
+ // BEGIN android-removed
+ // case GOST3411:
+ // generator = new PKCS5S2ParametersGenerator(new GOST3411Digest());
+ // break;
+ // END android-removed
+ default:
+ throw new IllegalStateException("unknown digest scheme for PBE PKCS5S2 encryption.");
+ }
}
else if (type == PKCS12)
{
@@ -288,9 +325,9 @@ public interface PBE
key = convertPassword(type, keySpec);
generator.init(key, keySpec.getSalt(), keySpec.getIterationCount());
-
+
param = generator.generateDerivedMacParameters(keySize);
-
+
for (int i = 0; i != key.length; i++)
{
key[i] = 0;
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java
new file mode 100644
index 0000000..214a5eb
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java
@@ -0,0 +1,23 @@
+package org.bouncycastle.jcajce.spec;
+
+import javax.crypto.spec.PBEKeySpec;
+
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class PBKDF2KeySpec
+ extends PBEKeySpec
+{
+ private AlgorithmIdentifier prf;
+
+ public PBKDF2KeySpec(char[] password, byte[] salt, int iterationCount, int keySize, AlgorithmIdentifier prf)
+ {
+ super(password, salt, iterationCount, keySize);
+
+ this.prf = prf;
+ }
+
+ public AlgorithmIdentifier getPrf()
+ {
+ return prf;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java b/bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java
new file mode 100644
index 0000000..941f476
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java
@@ -0,0 +1,60 @@
+package org.bouncycastle.jce;
+
+import java.util.Enumeration;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
+
+/**
+ * a table of locally supported named curves.
+ */
+public class ECNamedCurveTable
+{
+ /**
+ * return a parameter spec representing the passed in named
+ * curve. The routine returns null if the curve is not present.
+ *
+ * @param name the name of the curve requested
+ * @return a parameter spec for the curve, null if it is not available.
+ */
+ public static ECNamedCurveParameterSpec getParameterSpec(
+ String name)
+ {
+ X9ECParameters ecP = org.bouncycastle.asn1.x9.ECNamedCurveTable.getByName(name);
+ if (ecP == null)
+ {
+ try
+ {
+ ecP = org.bouncycastle.asn1.x9.ECNamedCurveTable.getByOID(new ASN1ObjectIdentifier(name));
+ }
+ catch (IllegalArgumentException e)
+ {
+ // ignore - not an oid
+ }
+ }
+
+ if (ecP == null)
+ {
+ return null;
+ }
+
+ return new ECNamedCurveParameterSpec(
+ name,
+ ecP.getCurve(),
+ ecP.getG(),
+ ecP.getN(),
+ ecP.getH(),
+ ecP.getSeed());
+ }
+
+ /**
+ * return an enumeration of the names of the available curves.
+ *
+ * @return an enumeration of the names of the available curves.
+ */
+ public static Enumeration getNames()
+ {
+ return org.bouncycastle.asn1.x9.ECNamedCurveTable.getNames();
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java b/bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java
index efa0f66..ddd38e8 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java
@@ -19,6 +19,7 @@ import org.bouncycastle.asn1.x509.X509Name;
* PrincipalUtil class.
* </p>
* @see org.bouncycastle.jce.PrincipalUtil
+ * @deprecated use the X500Name class.
*/
public class X509Principal
extends X509Name
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
index 665f85b..ab6c42f 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
@@ -44,7 +44,7 @@ import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter;
public final class BouncyCastleProvider extends Provider
implements ConfigurableProvider
{
- private static String info = "BouncyCastle Security Provider v1.49";
+ private static String info = "BouncyCastle Security Provider v1.50";
public static final String PROVIDER_NAME = "BC";
@@ -72,11 +72,13 @@ public final class BouncyCastleProvider extends Provider
private static final String[] SYMMETRIC_CIPHERS =
{
// BEGIN android-removed
- // "AES", "ARC4", "Blowfish", "Camellia", "CAST5", "CAST6", "DES", "DESede", "GOST28147", "Grainv1", "Grain128", "HC128", "HC256", "IDEA",
- // "Noekeon", "RC2", "RC5", "RC6", "Rijndael", "Salsa20", "SEED", "Serpent", "Skipjack", "TEA", "Twofish", "VMPC", "VMPCKSA3", "XTEA"
+ // "AES", "ARC4", "Blowfish", "Camellia", "CAST5", "CAST6", "ChaCha", "DES", "DESede",
+ // "GOST28147", "Grainv1", "Grain128", "HC128", "HC256", "IDEA", "Noekeon", "RC2", "RC5",
+ // "RC6", "Rijndael", "Salsa20", "SEED", "Serpent", "Shacal2", "Skipjack", "TEA", "Twofish", "Threefish",
+ // "VMPC", "VMPCKSA3", "XTEA", "XSalsa20"
// END android-removed
// BEGIN android-added
- "AES", "ARC4", "Blowfish", "DES", "DESede", "RC2", "Twofish"
+ "AES", "ARC4", "Blowfish", "DES", "DESede", "RC2", "Twofish",
// END android-added
};
@@ -114,7 +116,7 @@ public final class BouncyCastleProvider extends Provider
private static final String[] DIGESTS =
{
// BEGIN android-removed
- // "GOST3411", "MD2", "MD4", "MD5", "SHA1", "RIPEMD128", "RIPEMD160", "RIPEMD256", "RIPEMD320", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "Tiger", "Whirlpool"
+ // "GOST3411", "MD2", "MD4", "MD5", "SHA1", "RIPEMD128", "RIPEMD160", "RIPEMD256", "RIPEMD320", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "Skein", "SM3", "Tiger", "Whirlpool"
// END android-removed
// BEGIN android-added
"MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512",
@@ -122,7 +124,7 @@ public final class BouncyCastleProvider extends Provider
};
/*
- * Configurable digests
+ * Configurable keystores
*/
private static final String KEYSTORE_PACKAGE = "org.bouncycastle.jcajce.provider.keystore.";
private static final String[] KEYSTORES =
@@ -137,7 +139,7 @@ public final class BouncyCastleProvider extends Provider
*/
public BouncyCastleProvider()
{
- super(PROVIDER_NAME, 1.49, info);
+ super(PROVIDER_NAME, 1.50, info);
AccessController.doPrivileged(new PrivilegedAction()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
index a76aff7..eb663dc 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
@@ -76,7 +76,9 @@ import org.bouncycastle.x509.ExtendedPKIXParameters;
import org.bouncycastle.x509.X509AttributeCertificate;
import org.bouncycastle.x509.X509CRLStoreSelector;
import org.bouncycastle.x509.X509CertStoreSelector;
-import org.bouncycastle.x509.X509Store;
+// BEGIN android-removed
+// import org.bouncycastle.x509.X509Store;
+// END android-removed
public class CertPathValidatorUtilities
{
@@ -726,20 +728,22 @@ public class CertPathValidatorUtilities
{
Object obj = iter.next();
- if (obj instanceof X509Store)
- {
- X509Store certStore = (X509Store)obj;
- try
- {
- certs.addAll(certStore.getMatches(certSelect));
- }
- catch (StoreException e)
- {
- throw new AnnotatedException(
- "Problem while picking certificates from X.509 store.", e);
- }
- }
- else
+ // BEGIN android-removed
+ // if (obj instanceof X509Store)
+ // {
+ // X509Store certStore = (X509Store)obj;
+ // try
+ // {
+ // certs.addAll(certStore.getMatches(certSelect));
+ // }
+ // catch (StoreException e)
+ // {
+ // throw new AnnotatedException(
+ // "Problem while picking certificates from X.509 store.", e);
+ // }
+ // }
+ // else
+ // END android-removed
{
CertStore certStore = (CertStore)obj;
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java
index 7d561b3..53f4ec7 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java
@@ -127,8 +127,8 @@ public class JCEECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
@@ -158,8 +158,8 @@ public class JCEECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
@@ -170,8 +170,8 @@ public class JCEECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
+ spec.getG().getAffineXCoord().toBigInteger(),
+ spec.getG().getAffineYCoord().toBigInteger()),
spec.getN(),
spec.getH().intValue());
}
@@ -215,8 +215,8 @@ public class JCEECPrivateKey
// ECGOST3410NamedCurves.getName(oid),
// ellipticCurve,
// new ECPoint(
- // gParam.getG().getX().toBigInteger(),
- // gParam.getG().getY().toBigInteger()),
+ // gParam.getG().getAffineXCoord().toBigInteger(),
+ // gParam.getG().getAffineYCoord().toBigInteger()),
// gParam.getN(),
// gParam.getH());
// }
@@ -229,8 +229,8 @@ public class JCEECPrivateKey
ECUtil.getCurveName(oid),
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH());
}
@@ -247,8 +247,8 @@ public class JCEECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH().intValue());
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java
index cfed770..6fff8a6 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java
@@ -98,7 +98,7 @@ public class JCEECPublicKey
{
org.bouncycastle.jce.spec.ECParameterSpec s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
- q = s.getCurve().createPoint(q.getX().toBigInteger(), q.getY().toBigInteger(), false);
+ q = s.getCurve().createPoint(q.getAffineXCoord().toBigInteger(), q.getAffineYCoord().toBigInteger(), false);
}
this.ecSpec = null;
}
@@ -167,8 +167,8 @@ public class JCEECPublicKey
return new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
@@ -189,7 +189,6 @@ public class JCEECPublicKey
private void populateFromPubKeyInfo(SubjectPublicKeyInfo info)
{
- // BEGIN android-removed
// if (info.getAlgorithmId().getObjectId().equals(CryptoProObjectIdentifiers.gostR3410_2001))
// {
// DERBitString bits = info.getPublicKeyData();
@@ -232,8 +231,8 @@ public class JCEECPublicKey
// ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()),
// ellipticCurve,
// new ECPoint(
- // spec.getG().getX().toBigInteger(),
- // spec.getG().getY().toBigInteger()),
+ // spec.getG().getAffineXCoord().toBigInteger(),
+ // spec.getG().getAffineYCoord().toBigInteger()),
// spec.getN(), spec.getH());
//
// }
@@ -256,8 +255,8 @@ public class JCEECPublicKey
ECUtil.getCurveName(oid),
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH());
}
@@ -276,8 +275,8 @@ public class JCEECPublicKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH().intValue());
}
@@ -357,8 +356,8 @@ public class JCEECPublicKey
// }
// }
//
- // BigInteger bX = this.q.getX().toBigInteger();
- // BigInteger bY = this.q.getY().toBigInteger();
+ // BigInteger bX = this.q.getAffineXCoord().toBigInteger();
+ // BigInteger bY = this.q.getAffineYCoord().toBigInteger();
// byte[] encKey = new byte[64];
//
// extractBytes(encKey, 0, bX);
@@ -405,7 +404,7 @@ public class JCEECPublicKey
ECCurve curve = this.engineGetQ().getCurve();
ASN1OctetString p = (ASN1OctetString)
- new X9ECPoint(curve.createPoint(this.getQ().getX().toBigInteger(), this.getQ().getY().toBigInteger(), withCompression)).toASN1Primitive();
+ new X9ECPoint(curve.createPoint(this.getQ().getAffineXCoord().toBigInteger(), this.getQ().getAffineYCoord().toBigInteger(), withCompression)).toASN1Primitive();
info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets());
}
@@ -446,7 +445,7 @@ public class JCEECPublicKey
public ECPoint getW()
{
- return new ECPoint(q.getX().toBigInteger(), q.getY().toBigInteger());
+ return new ECPoint(q.getAffineXCoord().toBigInteger(), q.getAffineYCoord().toBigInteger());
}
public org.bouncycastle.math.ec.ECPoint getQ()
@@ -455,11 +454,11 @@ public class JCEECPublicKey
{
if (q instanceof org.bouncycastle.math.ec.ECPoint.Fp)
{
- return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getX(), q.getY());
+ return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getAffineXCoord(), q.getAffineYCoord());
}
else
{
- return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getX(), q.getY());
+ return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getAffineXCoord(), q.getAffineYCoord());
}
}
@@ -487,8 +486,8 @@ public class JCEECPublicKey
String nl = System.getProperty("line.separator");
buf.append("EC Public Key").append(nl);
- buf.append(" X: ").append(this.q.getX().toBigInteger().toString(16)).append(nl);
- buf.append(" Y: ").append(this.q.getY().toBigInteger().toString(16)).append(nl);
+ buf.append(" X: ").append(this.q.getAffineXCoord().toBigInteger().toString(16)).append(nl);
+ buf.append(" Y: ").append(this.q.getAffineYCoord().toBigInteger().toString(16)).append(nl);
return buf.toString();
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCRLUtil.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCRLUtil.java
index c94016d..ebd2f2a 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCRLUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCRLUtil.java
@@ -15,7 +15,9 @@ import java.util.Set;
import org.bouncycastle.util.StoreException;
import org.bouncycastle.x509.ExtendedPKIXParameters;
import org.bouncycastle.x509.X509CRLStoreSelector;
-import org.bouncycastle.x509.X509Store;
+// BEGIN android-removed
+// import org.bouncycastle.x509.X509Store;
+// END android-removed
public class PKIXCRLUtil
{
@@ -114,22 +116,24 @@ public class PKIXCRLUtil
{
Object obj = iter.next();
- if (obj instanceof X509Store)
- {
- X509Store store = (X509Store)obj;
-
- try
- {
- crls.addAll(store.getMatches(crlSelect));
- foundValidStore = true;
- }
- catch (StoreException e)
- {
- lastException = new AnnotatedException(
- "Exception searching in X.509 CRL store.", e);
- }
- }
- else
+ // BEGIN android-removed
+ // if (obj instanceof X509Store)
+ // {
+ // X509Store store = (X509Store)obj;
+ //
+ // try
+ // {
+ // crls.addAll(store.getMatches(crlSelect));
+ // foundValidStore = true;
+ // }
+ // catch (StoreException e)
+ // {
+ // lastException = new AnnotatedException(
+ // "Exception searching in X.509 CRL store.", e);
+ // }
+ // }
+ // else
+ // END android-removed
{
CertStore store = (CertStore)obj;
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java
index d5c3700..7e76a89 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java
@@ -211,6 +211,23 @@ public class X509CRLEntryObject extends X509CRLEntry
return hashValue;
}
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (o instanceof X509CRLEntryObject)
+ {
+ X509CRLEntryObject other = (X509CRLEntryObject)o;
+
+ return this.c.equals(other.c);
+ }
+
+ return super.equals(this);
+ }
+
public byte[] getEncoded()
throws CRLException
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java
index cd83211..b5b4f13 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java
@@ -59,6 +59,8 @@ public class X509CRLObject
private String sigAlgName;
private byte[] sigAlgParams;
private boolean isIndirect;
+ private boolean isHashCodeSet = false;
+ private int hashCodeValue;
static boolean isIndirectCRL(X509CRL crl)
throws CRLException
@@ -520,7 +522,7 @@ public class X509CRLObject
throw new RuntimeException("X.509 CRL used with non X.509 Cert");
}
- TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
+ Enumeration certs = c.getRevokedCertificateEnumeration();
X500Name caName = c.getIssuer();
@@ -528,11 +530,13 @@ public class X509CRLObject
{
BigInteger serial = ((X509Certificate)cert).getSerialNumber();
- for (int i = 0; i < certs.length; i++)
+ while (certs.hasMoreElements())
{
- if (isIndirect && certs[i].hasExtensions())
+ TBSCertList.CRLEntry entry = TBSCertList.CRLEntry.getInstance(certs.nextElement());
+
+ if (isIndirect && entry.hasExtensions())
{
- Extension currentCaName = certs[i].getExtensions().getExtension(Extension.certificateIssuer);
+ Extension currentCaName = entry.getExtensions().getExtension(Extension.certificateIssuer);
if (currentCaName != null)
{
@@ -540,7 +544,7 @@ public class X509CRLObject
}
}
- if (certs[i].getUserCertificate().getValue().equals(serial))
+ if (entry.getUserCertificate().getValue().equals(serial))
{
X500Name issuer;
@@ -572,5 +576,50 @@ public class X509CRLObject
return false;
}
+
+ public boolean equals(Object other)
+ {
+ if (this == other)
+ {
+ return true;
+ }
+
+ if (!(other instanceof X509CRL))
+ {
+ return false;
+ }
+
+ if (other instanceof X509CRLObject)
+ {
+ X509CRLObject crlObject = (X509CRLObject)other;
+
+ if (isHashCodeSet)
+ {
+ boolean otherIsHashCodeSet = crlObject.isHashCodeSet;
+ if (otherIsHashCodeSet)
+ {
+ if (crlObject.hashCodeValue != hashCodeValue)
+ {
+ return false;
+ }
+ }
+ }
+
+ return this.c.equals(crlObject.c);
+ }
+
+ return super.equals(other);
+ }
+
+ public int hashCode()
+ {
+ if (!isHashCodeSet)
+ {
+ isHashCodeSet = true;
+ hashCodeValue = super.hashCode();
+ }
+
+ return hashCodeValue;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java
index 84ebf70..b3d239e 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java
@@ -49,7 +49,8 @@ public class ECNamedCurveSpec
private static ECPoint convertPoint(
org.bouncycastle.math.ec.ECPoint g)
{
- return new ECPoint(g.getX().toBigInteger(), g.getY().toBigInteger());
+ g = g.normalize();
+ return new ECPoint(g.getAffineXCoord().toBigInteger(), g.getAffineYCoord().toBigInteger());
}
public ECNamedCurveSpec(
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECParameterSpec.java b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECParameterSpec.java
index e774a11..df91412 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECParameterSpec.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECParameterSpec.java
@@ -24,7 +24,7 @@ public class ECParameterSpec
BigInteger n)
{
this.curve = curve;
- this.G = G;
+ this.G = G.normalize();
this.n = n;
this.h = BigInteger.valueOf(1);
this.seed = null;
@@ -37,7 +37,7 @@ public class ECParameterSpec
BigInteger h)
{
this.curve = curve;
- this.G = G;
+ this.G = G.normalize();
this.n = n;
this.h = h;
this.seed = null;
@@ -51,7 +51,7 @@ public class ECParameterSpec
byte[] seed)
{
this.curve = curve;
- this.G = G;
+ this.G = G.normalize();
this.n = n;
this.h = h;
this.seed = seed;
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECPublicKeySpec.java b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECPublicKeySpec.java
index debab00..0e21a5b 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECPublicKeySpec.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECPublicKeySpec.java
@@ -22,7 +22,14 @@ public class ECPublicKeySpec
{
super(spec);
- this.q = q;
+ if (q.getCurve() != null)
+ {
+ this.q = q.normalize();
+ }
+ else
+ {
+ this.q = q;
+ }
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java b/bcprov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java
deleted file mode 100644
index 2a7ceb5..0000000
--- a/bcprov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.bouncycastle.jce.spec;
-
-
-import javax.crypto.SecretKey;
-
-/**
- * A simple object to indicate that a symmetric cipher should reuse the
- * last key provided.
- */
-public class RepeatedSecretKeySpec
- implements SecretKey
-{
- private String algorithm;
-
- public RepeatedSecretKeySpec(String algorithm)
- {
- this.algorithm = algorithm;
- }
-
- public String getAlgorithm()
- {
- return algorithm;
- }
-
- public String getFormat()
- {
- return null;
- }
-
- public byte[] getEncoded()
- {
- return null;
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
new file mode 100644
index 0000000..69ab797
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
@@ -0,0 +1,20 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+public abstract class AbstractECMultiplier implements ECMultiplier
+{
+ public ECPoint multiply(ECPoint p, BigInteger k)
+ {
+ int sign = k.signum();
+ if (sign == 0 || p.isInfinity())
+ {
+ return p.getCurve().getInfinity();
+ }
+
+ ECPoint positive = multiplyPositive(p, k.abs());
+ return sign > 0 ? positive : positive.negate();
+ }
+
+ protected abstract ECPoint multiplyPositive(ECPoint p, BigInteger k);
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
index 78a7a8f..d640b5f 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
@@ -7,16 +7,13 @@ public class ECAlgorithms
public static ECPoint sumOfTwoMultiplies(ECPoint P, BigInteger a,
ECPoint Q, BigInteger b)
{
- ECCurve c = P.getCurve();
- if (!c.equals(Q.getCurve()))
- {
- throw new IllegalArgumentException("P and Q must be on same curve");
- }
+ ECCurve cp = P.getCurve();
+ Q = importPoint(cp, Q);
// Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick
- if (c instanceof ECCurve.F2m)
+ if (cp instanceof ECCurve.F2m)
{
- ECCurve.F2m f2mCurve = (ECCurve.F2m)c;
+ ECCurve.F2m f2mCurve = (ECCurve.F2m)cp;
if (f2mCurve.isKoblitz())
{
return P.multiply(a).add(Q.multiply(b));
@@ -48,43 +45,83 @@ public class ECAlgorithms
public static ECPoint shamirsTrick(ECPoint P, BigInteger k,
ECPoint Q, BigInteger l)
{
- if (!P.getCurve().equals(Q.getCurve()))
+ ECCurve cp = P.getCurve();
+ Q = importPoint(cp, Q);
+
+ return implShamirsTrick(P, k, Q, l);
+ }
+
+ public static ECPoint importPoint(ECCurve c, ECPoint p)
+ {
+ ECCurve cp = p.getCurve();
+ if (!c.equals(cp))
{
- throw new IllegalArgumentException("P and Q must be on same curve");
+ throw new IllegalArgumentException("Point must be on the same curve");
}
+ return c.importPoint(p);
+ }
- return implShamirsTrick(P, k, Q, l);
+ static void implMontgomeryTrick(ECFieldElement[] zs, int off, int len)
+ {
+ /*
+ * Uses the "Montgomery Trick" to invert many field elements, with only a single actual
+ * field inversion. See e.g. the paper:
+ * "Fast Multi-scalar Multiplication Methods on Elliptic Curves with Precomputation Strategy Using Montgomery Trick"
+ * by Katsuyuki Okeya, Kouichi Sakurai.
+ */
+
+ ECFieldElement[] c = new ECFieldElement[len];
+ c[0] = zs[off];
+
+ int i = 0;
+ while (++i < len)
+ {
+ c[i] = c[i - 1].multiply(zs[off + i]);
+ }
+
+ ECFieldElement u = c[--i].invert();
+
+ while (i > 0)
+ {
+ int j = off + i--;
+ ECFieldElement tmp = zs[j];
+ zs[j] = c[i].multiply(u);
+ u = u.multiply(tmp);
+ }
+
+ zs[off] = u;
}
- private static ECPoint implShamirsTrick(ECPoint P, BigInteger k,
+ static ECPoint implShamirsTrick(ECPoint P, BigInteger k,
ECPoint Q, BigInteger l)
{
- int m = Math.max(k.bitLength(), l.bitLength());
- ECPoint Z = P.add(Q);
- ECPoint R = P.getCurve().getInfinity();
+ ECCurve curve = P.getCurve();
+ ECPoint infinity = curve.getInfinity();
+
+ // TODO conjugate co-Z addition (ZADDC) can return both of these
+ ECPoint PaddQ = P.add(Q);
+ ECPoint PsubQ = P.subtract(Q);
+
+ ECPoint[] points = new ECPoint[]{ Q, PsubQ, P, PaddQ };
+ curve.normalizeAll(points);
- for (int i = m - 1; i >= 0; --i)
+ ECPoint[] table = new ECPoint[] {
+ points[3].negate(), points[2].negate(), points[1].negate(),
+ points[0].negate(), infinity, points[0],
+ points[1], points[2], points[3] };
+
+ byte[] jsf = WNafUtil.generateJSF(k, l);
+
+ ECPoint R = infinity;
+
+ int i = jsf.length;
+ while (--i >= 0)
{
- R = R.twice();
+ int jsfi = jsf[i];
+ int kDigit = (jsfi >> 4), lDigit = ((jsfi << 28) >> 28);
- if (k.testBit(i))
- {
- if (l.testBit(i))
- {
- R = R.add(Z);
- }
- else
- {
- R = R.add(P);
- }
- }
- else
- {
- if (l.testBit(i))
- {
- R = R.add(Q);
- }
- }
+ int index = 4 + (kDigit * 3) + lDigit;
+ R = R.twicePlus(table[index]);
}
return R;
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
index 58281af..19f0062 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
@@ -3,18 +3,199 @@ package org.bouncycastle.math.ec;
import java.math.BigInteger;
import java.util.Random;
+import org.bouncycastle.util.BigIntegers;
+
/**
* base class for an elliptic curve
*/
public abstract class ECCurve
{
- ECFieldElement a, b;
+ public static final int COORD_AFFINE = 0;
+ public static final int COORD_HOMOGENEOUS = 1;
+ public static final int COORD_JACOBIAN = 2;
+ public static final int COORD_JACOBIAN_CHUDNOVSKY = 3;
+ public static final int COORD_JACOBIAN_MODIFIED = 4;
+ public static final int COORD_LAMBDA_AFFINE = 5;
+ public static final int COORD_LAMBDA_PROJECTIVE = 6;
+ public static final int COORD_SKEWED = 7;
+
+ public static int[] getAllCoordinateSystems()
+ {
+ return new int[]{ COORD_AFFINE, COORD_HOMOGENEOUS, COORD_JACOBIAN, COORD_JACOBIAN_CHUDNOVSKY,
+ COORD_JACOBIAN_MODIFIED, COORD_LAMBDA_AFFINE, COORD_LAMBDA_PROJECTIVE, COORD_SKEWED };
+ }
+
+ public class Config
+ {
+ protected int coord;
+ protected ECMultiplier multiplier;
+
+ Config(int coord, ECMultiplier multiplier)
+ {
+ this.coord = coord;
+ this.multiplier = multiplier;
+ }
+
+ public Config setCoordinateSystem(int coord)
+ {
+ this.coord = coord;
+ return this;
+ }
+
+ public Config setMultiplier(ECMultiplier multiplier)
+ {
+ this.multiplier = multiplier;
+ return this;
+ }
+
+ public ECCurve create()
+ {
+ if (!supportsCoordinateSystem(coord))
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+
+ ECCurve c = cloneCurve();
+ if (c == ECCurve.this)
+ {
+ throw new IllegalStateException("implementation returned current curve");
+ }
+
+ c.coord = coord;
+ c.multiplier = multiplier;
+
+ return c;
+ }
+ }
+
+ protected ECFieldElement a, b;
+ protected int coord = COORD_AFFINE;
+ protected ECMultiplier multiplier = null;
public abstract int getFieldSize();
public abstract ECFieldElement fromBigInteger(BigInteger x);
- public abstract ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression);
+ public Config configure()
+ {
+ return new Config(this.coord, this.multiplier);
+ }
+
+ public ECPoint createPoint(BigInteger x, BigInteger y)
+ {
+ return createPoint(x, y, false);
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, use {@link #createPoint(BigInteger, BigInteger)}
+ * and refer {@link ECPoint#getEncoded(boolean)}
+ */
+ public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
+ {
+ return createRawPoint(fromBigInteger(x), fromBigInteger(y), withCompression);
+ }
+
+ protected abstract ECCurve cloneCurve();
+
+ protected abstract ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression);
+
+ protected ECMultiplier createDefaultMultiplier()
+ {
+ return new WNafL2RMultiplier();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ return coord == COORD_AFFINE;
+ }
+
+ public PreCompInfo getPreCompInfo(ECPoint p)
+ {
+ checkPoint(p);
+ return p.preCompInfo;
+ }
+
+ /**
+ * Sets the <code>PreCompInfo</code> for a point on this curve. Used by
+ * <code>ECMultiplier</code>s to save the precomputation for this <code>ECPoint</code> for use
+ * by subsequent multiplication.
+ *
+ * @param point
+ * The <code>ECPoint</code> to store precomputations for.
+ * @param preCompInfo
+ * The values precomputed by the <code>ECMultiplier</code>.
+ */
+ public void setPreCompInfo(ECPoint point, PreCompInfo preCompInfo)
+ {
+ checkPoint(point);
+ point.preCompInfo = preCompInfo;
+ }
+
+ public ECPoint importPoint(ECPoint p)
+ {
+ if (this == p.getCurve())
+ {
+ return p;
+ }
+ if (p.isInfinity())
+ {
+ return getInfinity();
+ }
+
+ // TODO Default behaviour could be improved if the two curves have the same coordinate system by copying any Z coordinates.
+ p = p.normalize();
+
+ return createPoint(p.getXCoord().toBigInteger(), p.getYCoord().toBigInteger(), p.withCompression);
+ }
+
+ /**
+ * Normalization ensures that any projective coordinate is 1, and therefore that the x, y
+ * coordinates reflect those of the equivalent point in an affine coordinate system. Where more
+ * than one point is to be normalized, this method will generally be more efficient than
+ * normalizing each point separately.
+ *
+ * @param points
+ * An array of points that will be updated in place with their normalized versions,
+ * where necessary
+ */
+ public void normalizeAll(ECPoint[] points)
+ {
+ checkPoints(points);
+
+ if (this.getCoordinateSystem() == ECCurve.COORD_AFFINE)
+ {
+ return;
+ }
+
+ /*
+ * Figure out which of the points actually need to be normalized
+ */
+ ECFieldElement[] zs = new ECFieldElement[points.length];
+ int[] indices = new int[points.length];
+ int count = 0;
+ for (int i = 0; i < points.length; ++i)
+ {
+ ECPoint p = points[i];
+ if (null != p && !p.isNormalized())
+ {
+ zs[count] = p.getZCoord(0);
+ indices[count++] = i;
+ }
+ }
+
+ if (count == 0)
+ {
+ return;
+ }
+
+ ECAlgorithms.implMontgomeryTrick(zs, 0, count);
+
+ for (int j = 0; j < count; ++j)
+ {
+ int index = indices[j];
+ points[index] = points[index].normalize(zs[j]);
+ }
+ }
public abstract ECPoint getInfinity();
@@ -28,9 +209,26 @@ public abstract class ECCurve
return b;
}
+ public int getCoordinateSystem()
+ {
+ return coord;
+ }
+
protected abstract ECPoint decompressPoint(int yTilde, BigInteger X1);
/**
+ * Sets the default <code>ECMultiplier</code>, unless already set.
+ */
+ public ECMultiplier getMultiplier()
+ {
+ if (this.multiplier == null)
+ {
+ this.multiplier = createDefaultMultiplier();
+ }
+ return this.multiplier;
+ }
+
+ /**
* Decode a point on this curve from its ASN.1 encoding. The different
* encodings are taken account of, including point compression for
* <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17).
@@ -62,9 +260,9 @@ public abstract class ECCurve
}
int yTilde = encoded[0] & 1;
- BigInteger X1 = fromArray(encoded, 1, expectedLength);
+ BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
- p = decompressPoint(yTilde, X1);
+ p = decompressPoint(yTilde, X);
break;
}
case 0x04: // uncompressed
@@ -76,10 +274,10 @@ public abstract class ECCurve
throw new IllegalArgumentException("Incorrect length for uncompressed/hybrid encoding");
}
- BigInteger X1 = fromArray(encoded, 1, expectedLength);
- BigInteger Y1 = fromArray(encoded, 1 + expectedLength, expectedLength);
+ BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
+ BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength);
- p = createPoint(X1, Y1, false);
+ p = createPoint(X, Y);
break;
}
default:
@@ -89,11 +287,29 @@ public abstract class ECCurve
return p;
}
- private static BigInteger fromArray(byte[] buf, int off, int length)
+ protected void checkPoint(ECPoint point)
{
- byte[] mag = new byte[length];
- System.arraycopy(buf, off, mag, 0, length);
- return new BigInteger(1, mag);
+ if (null == point || (this != point.getCurve()))
+ {
+ throw new IllegalArgumentException("'point' must be non-null and on this curve");
+ }
+ }
+
+ protected void checkPoints(ECPoint[] points)
+ {
+ if (points == null)
+ {
+ throw new IllegalArgumentException("'points' cannot be null");
+ }
+
+ for (int i = 0; i < points.length; ++i)
+ {
+ ECPoint point = points[i];
+ if (null != point && this != point.getCurve())
+ {
+ throw new IllegalArgumentException("'points' entries must be null or on this curve");
+ }
+ }
}
/**
@@ -101,15 +317,50 @@ public abstract class ECCurve
*/
public static class Fp extends ECCurve
{
- BigInteger q;
+ private static final int FP_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED;
+
+ BigInteger q, r;
ECPoint.Fp infinity;
public Fp(BigInteger q, BigInteger a, BigInteger b)
{
this.q = q;
+ this.r = ECFieldElement.Fp.calculateResidue(q);
+ this.infinity = new ECPoint.Fp(this, null, null);
+
this.a = fromBigInteger(a);
this.b = fromBigInteger(b);
+ this.coord = FP_DEFAULT_COORDS;
+ }
+
+ protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b)
+ {
+ this.q = q;
+ this.r = r;
this.infinity = new ECPoint.Fp(this, null, null);
+
+ this.a = a;
+ this.b = b;
+ this.coord = FP_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new Fp(q, r, a, b);
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_AFFINE:
+ case COORD_HOMOGENEOUS:
+ case COORD_JACOBIAN:
+ case COORD_JACOBIAN_MODIFIED:
+ return true;
+ default:
+ return false;
+ }
}
public BigInteger getQ()
@@ -124,12 +375,34 @@ public abstract class ECCurve
public ECFieldElement fromBigInteger(BigInteger x)
{
- return new ECFieldElement.Fp(this.q, x);
+ return new ECFieldElement.Fp(this.q, this.r, x);
}
- public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
{
- return new ECPoint.Fp(this, fromBigInteger(x), fromBigInteger(y), withCompression);
+ return new ECPoint.Fp(this, x, y, withCompression);
+ }
+
+ public ECPoint importPoint(ECPoint p)
+ {
+ if (this != p.getCurve() && this.getCoordinateSystem() == COORD_JACOBIAN && !p.isInfinity())
+ {
+ switch (p.getCurve().getCoordinateSystem())
+ {
+ case COORD_JACOBIAN:
+ case COORD_JACOBIAN_CHUDNOVSKY:
+ case COORD_JACOBIAN_MODIFIED:
+ return new ECPoint.Fp(this,
+ fromBigInteger(p.x.toBigInteger()),
+ fromBigInteger(p.y.toBigInteger()),
+ new ECFieldElement[]{ fromBigInteger(p.zs[0].toBigInteger()) },
+ p.withCompression);
+ default:
+ break;
+ }
+ }
+
+ return super.importPoint(p);
}
protected ECPoint decompressPoint(int yTilde, BigInteger X1)
@@ -148,9 +421,7 @@ public abstract class ECCurve
}
BigInteger betaValue = beta.toBigInteger();
- int bit0 = betaValue.testBit(0) ? 1 : 0;
-
- if (bit0 != yTilde)
+ if (betaValue.testBit(0) != (yTilde == 1))
{
// Use the other root
beta = fromBigInteger(q.subtract(betaValue));
@@ -195,6 +466,8 @@ public abstract class ECCurve
*/
public static class F2m extends ECCurve
{
+ private static final int F2M_DEFAULT_COORDS = COORD_AFFINE;
+
/**
* The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
*/
@@ -401,9 +674,53 @@ public abstract class ECCurve
}
}
+ this.infinity = new ECPoint.F2m(this, null, null);
this.a = fromBigInteger(a);
this.b = fromBigInteger(b);
+ this.coord = F2M_DEFAULT_COORDS;
+ }
+
+ protected F2m(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger n, BigInteger h)
+ {
+ this.m = m;
+ this.k1 = k1;
+ this.k2 = k2;
+ this.k3 = k3;
+ this.n = n;
+ this.h = h;
+
this.infinity = new ECPoint.F2m(this, null, null);
+ this.a = a;
+ this.b = b;
+ this.coord = F2M_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new F2m(m, k1, k2, k3, a, b, n, h);
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_AFFINE:
+ case COORD_HOMOGENEOUS:
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ protected ECMultiplier createDefaultMultiplier()
+ {
+ if (isKoblitz())
+ {
+ return new WTauNafMultiplier();
+ }
+
+ return super.createDefaultMultiplier();
}
public int getFieldSize()
@@ -418,7 +735,32 @@ public abstract class ECCurve
public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
{
- return new ECPoint.F2m(this, fromBigInteger(x), fromBigInteger(y), withCompression);
+ ECFieldElement X = fromBigInteger(x), Y = fromBigInteger(y);
+
+ switch (this.getCoordinateSystem())
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ if (!X.isZero())
+ {
+ // Y becomes Lambda (X + Y/X) here
+ Y = Y.divide(X).add(X);
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return createRawPoint(X, Y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new ECPoint.F2m(this, x, y, withCompression);
}
public ECPoint getInfinity()
@@ -432,10 +774,7 @@ public abstract class ECCurve
*/
public boolean isKoblitz()
{
- return ((n != null) && (h != null) &&
- ((a.toBigInteger().equals(ECConstants.ZERO)) ||
- (a.toBigInteger().equals(ECConstants.ONE))) &&
- (b.toBigInteger().equals(ECConstants.ONE)));
+ return n != null && h != null && a.bitLength() <= 1 && b.bitLength() == 1;
}
/**
@@ -480,7 +819,7 @@ public abstract class ECCurve
{
ECFieldElement xp = fromBigInteger(X1);
ECFieldElement yp = null;
- if (xp.toBigInteger().equals(ECConstants.ZERO))
+ if (xp.isZero())
{
yp = (ECFieldElement.F2m)b;
for (int i = 0; i < m - 1; i++)
@@ -491,17 +830,31 @@ public abstract class ECCurve
else
{
ECFieldElement beta = xp.add(a).add(b.multiply(xp.square().invert()));
- ECFieldElement z = solveQuadradicEquation(beta);
+ ECFieldElement z = solveQuadraticEquation(beta);
if (z == null)
{
throw new IllegalArgumentException("Invalid point compression");
}
- int zBit = z.toBigInteger().testBit(0) ? 1 : 0;
- if (zBit != yTilde)
+ if (z.testBitZero() != (yTilde == 1))
{
- z = z.add(fromBigInteger(ECConstants.ONE));
+ z = z.addOne();
}
+
yp = xp.multiply(z);
+
+ switch (this.getCoordinateSystem())
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ yp = yp.divide(xp).add(xp);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
}
return new ECPoint.F2m(this, xp, yp, true);
@@ -512,28 +865,26 @@ public abstract class ECCurve
* D.1.6) The other solution is <code>z + 1</code>.
*
* @param beta
- * The value to solve the qradratic equation for.
+ * The value to solve the quadratic equation for.
* @return the solution for <code>z<sup>2</sup> + z = beta</code> or
* <code>null</code> if no solution exists.
*/
- private ECFieldElement solveQuadradicEquation(ECFieldElement beta)
+ private ECFieldElement solveQuadraticEquation(ECFieldElement beta)
{
- ECFieldElement zeroElement = new ECFieldElement.F2m(
- this.m, this.k1, this.k2, this.k3, ECConstants.ZERO);
-
- if (beta.toBigInteger().equals(ECConstants.ZERO))
+ if (beta.isZero())
{
- return zeroElement;
+ return beta;
}
+ ECFieldElement zeroElement = fromBigInteger(ECConstants.ZERO);
+
ECFieldElement z = null;
- ECFieldElement gamma = zeroElement;
+ ECFieldElement gamma = null;
Random rand = new Random();
do
{
- ECFieldElement t = new ECFieldElement.F2m(this.m, this.k1,
- this.k2, this.k3, new BigInteger(m, rand));
+ ECFieldElement t = fromBigInteger(new BigInteger(m, rand));
z = zeroElement;
ECFieldElement w = beta;
for (int i = 1; i <= m - 1; i++)
@@ -542,13 +893,13 @@ public abstract class ECCurve
z = z.square().add(w2.multiply(t));
w = w2.add(beta);
}
- if (!w.toBigInteger().equals(ECConstants.ZERO))
+ if (!w.isZero())
{
return null;
}
gamma = z.square().add(z);
}
- while (gamma.toBigInteger().equals(ECConstants.ZERO));
+ while (gamma.isZero());
return z;
}
@@ -567,7 +918,7 @@ public abstract class ECCurve
}
ECCurve.F2m other = (ECCurve.F2m)anObject;
-
+
return (this.m == other.m) && (this.k1 == other.k1)
&& (this.k2 == other.k2) && (this.k3 == other.k3)
&& a.equals(other.a) && b.equals(other.b);
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java
index b5e9aa5..87608eb 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java
@@ -3,14 +3,17 @@ package org.bouncycastle.math.ec;
import java.math.BigInteger;
import java.util.Random;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.BigIntegers;
+
public abstract class ECFieldElement
implements ECConstants
{
-
public abstract BigInteger toBigInteger();
public abstract String getFieldName();
public abstract int getFieldSize();
public abstract ECFieldElement add(ECFieldElement b);
+ public abstract ECFieldElement addOne();
public abstract ECFieldElement subtract(ECFieldElement b);
public abstract ECFieldElement multiply(ECFieldElement b);
public abstract ECFieldElement divide(ECFieldElement b);
@@ -19,27 +22,99 @@ public abstract class ECFieldElement
public abstract ECFieldElement invert();
public abstract ECFieldElement sqrt();
+ public int bitLength()
+ {
+ return toBigInteger().bitLength();
+ }
+
+ public boolean isZero()
+ {
+ return 0 == toBigInteger().signum();
+ }
+
+ public boolean testBitZero()
+ {
+ return toBigInteger().testBit(0);
+ }
+
public String toString()
{
- return this.toBigInteger().toString(2);
+ return this.toBigInteger().toString(16);
+ }
+
+ public byte[] getEncoded()
+ {
+ return BigIntegers.asUnsignedByteArray((getFieldSize() + 7) / 8, toBigInteger());
}
public static class Fp extends ECFieldElement
{
- BigInteger x;
+ BigInteger q, r, x;
- BigInteger q;
-
+// static int[] calculateNaf(BigInteger p)
+// {
+// int[] naf = WNafUtil.generateCompactNaf(p);
+//
+// int bit = 0;
+// for (int i = 0; i < naf.length; ++i)
+// {
+// int ni = naf[i];
+// int digit = ni >> 16, zeroes = ni & 0xFFFF;
+//
+// bit += zeroes;
+// naf[i] = digit < 0 ? ~bit : bit;
+// ++bit;
+// }
+//
+// int last = naf.length - 1;
+// if (last > 0 && last <= 16)
+// {
+// int top = naf[last], top2 = naf[last - 1];
+// if (top2 < 0)
+// {
+// top2 = ~top2;
+// }
+// if (top - top2 >= 64)
+// {
+// return naf;
+// }
+// }
+//
+// return null;
+// }
+
+ static BigInteger calculateResidue(BigInteger p)
+ {
+ int bitLength = p.bitLength();
+ if (bitLength > 128)
+ {
+ BigInteger firstWord = p.shiftRight(bitLength - 64);
+ if (firstWord.longValue() == -1L)
+ {
+ return ONE.shiftLeft(bitLength).subtract(p);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @deprecated Use ECCurve.fromBigInteger to construct field elements
+ */
public Fp(BigInteger q, BigInteger x)
{
- this.x = x;
-
- if (x.compareTo(q) >= 0)
+ this(q, calculateResidue(q), x);
+ }
+
+ Fp(BigInteger q, BigInteger r, BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(q) >= 0)
{
- throw new IllegalArgumentException("x value too large in field element");
+ throw new IllegalArgumentException("x value invalid in Fp field element");
}
this.q = q;
+ this.r = r;
+ this.x = x;
}
public BigInteger toBigInteger()
@@ -66,40 +141,70 @@ public abstract class ECFieldElement
{
return q;
}
-
+
public ECFieldElement add(ECFieldElement b)
{
- return new Fp(q, x.add(b.toBigInteger()).mod(q));
+ return new Fp(q, r, modAdd(x, b.toBigInteger()));
+ }
+
+ public ECFieldElement addOne()
+ {
+ BigInteger x2 = x.add(ECConstants.ONE);
+ if (x2.compareTo(q) == 0)
+ {
+ x2 = ECConstants.ZERO;
+ }
+ return new Fp(q, r, x2);
}
public ECFieldElement subtract(ECFieldElement b)
{
- return new Fp(q, x.subtract(b.toBigInteger()).mod(q));
+ BigInteger x2 = b.toBigInteger();
+ BigInteger x3 = x.subtract(x2);
+ if (x3.signum() < 0)
+ {
+ x3 = x3.add(q);
+ }
+ return new Fp(q, r, x3);
}
public ECFieldElement multiply(ECFieldElement b)
{
- return new Fp(q, x.multiply(b.toBigInteger()).mod(q));
+ return new Fp(q, r, modMult(x, b.toBigInteger()));
}
public ECFieldElement divide(ECFieldElement b)
{
- return new Fp(q, x.multiply(b.toBigInteger().modInverse(q)).mod(q));
+ return new Fp(q, modMult(x, b.toBigInteger().modInverse(q)));
}
public ECFieldElement negate()
{
- return new Fp(q, x.negate().mod(q));
+ BigInteger x2;
+ if (x.signum() == 0)
+ {
+ x2 = x;
+ }
+ else if (ONE.equals(r))
+ {
+ x2 = q.xor(x);
+ }
+ else
+ {
+ x2 = q.subtract(x);
+ }
+ return new Fp(q, r, x2);
}
public ECFieldElement square()
{
- return new Fp(q, x.multiply(x).mod(q));
+ return new Fp(q, r, modMult(x, x));
}
public ECFieldElement invert()
{
- return new Fp(q, x.modInverse(q));
+ // TODO Modular inversion can be faster for a (Generalized) Mersenne Prime.
+ return new Fp(q, r, x.modInverse(q));
}
// D.1.4 91
@@ -120,7 +225,7 @@ public abstract class ECFieldElement
if (q.testBit(1))
{
// z = g^(u+1) + p, p = 4u + 3
- ECFieldElement z = new Fp(q, x.modPow(q.shiftRight(2).add(ECConstants.ONE), q));
+ ECFieldElement z = new Fp(q, r, x.modPow(q.shiftRight(2).add(ECConstants.ONE), q));
return z.square().equals(this) ? z : null;
}
@@ -138,7 +243,7 @@ public abstract class ECFieldElement
BigInteger k = u.shiftLeft(1).add(ECConstants.ONE);
BigInteger Q = this.x;
- BigInteger fourQ = Q.shiftLeft(2).mod(q);
+ BigInteger fourQ = modDouble(modDouble(Q));
BigInteger U, V;
Random rand = new Random();
@@ -152,11 +257,11 @@ public abstract class ECFieldElement
while (P.compareTo(q) >= 0
|| !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, q).equals(qMinusOne)));
- BigInteger[] result = lucasSequence(q, P, Q, k);
+ BigInteger[] result = lucasSequence(P, Q, k);
U = result[0];
V = result[1];
- if (V.multiply(V).mod(q).equals(fourQ))
+ if (modMult(V, V).equals(fourQ))
{
// Integer division by 2, mod q
if (V.testBit(0))
@@ -168,7 +273,7 @@ public abstract class ECFieldElement
//assert V.multiply(V).mod(q).equals(x);
- return new ECFieldElement.Fp(q, V);
+ return new ECFieldElement.Fp(q, r, V);
}
}
while (U.equals(ECConstants.ONE) || U.equals(qMinusOne));
@@ -230,8 +335,7 @@ public abstract class ECFieldElement
// return r.multiply(r).multiply(x.modPow(q.subtract(ECConstants.TWO), q)).subtract(ECConstants.TWO).mod(p);
// }
- private static BigInteger[] lucasSequence(
- BigInteger p,
+ private BigInteger[] lucasSequence(
BigInteger P,
BigInteger Q,
BigInteger k)
@@ -247,40 +351,122 @@ public abstract class ECFieldElement
for (int j = n - 1; j >= s + 1; --j)
{
- Ql = Ql.multiply(Qh).mod(p);
+ Ql = modMult(Ql, Qh);
if (k.testBit(j))
{
- Qh = Ql.multiply(Q).mod(p);
- Uh = Uh.multiply(Vh).mod(p);
- Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
- Vh = Vh.multiply(Vh).subtract(Qh.shiftLeft(1)).mod(p);
+ Qh = modMult(Ql, Q);
+ Uh = modMult(Uh, Vh);
+ Vl = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql)));
+ Vh = modReduce(Vh.multiply(Vh).subtract(Qh.shiftLeft(1)));
}
else
{
Qh = Ql;
- Uh = Uh.multiply(Vl).subtract(Ql).mod(p);
- Vh = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
- Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p);
+ Uh = modReduce(Uh.multiply(Vl).subtract(Ql));
+ Vh = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql)));
+ Vl = modReduce(Vl.multiply(Vl).subtract(Ql.shiftLeft(1)));
}
}
- Ql = Ql.multiply(Qh).mod(p);
- Qh = Ql.multiply(Q).mod(p);
- Uh = Uh.multiply(Vl).subtract(Ql).mod(p);
- Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
- Ql = Ql.multiply(Qh).mod(p);
+ Ql = modMult(Ql, Qh);
+ Qh = modMult(Ql, Q);
+ Uh = modReduce(Uh.multiply(Vl).subtract(Ql));
+ Vl = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql)));
+ Ql = modMult(Ql, Qh);
for (int j = 1; j <= s; ++j)
{
- Uh = Uh.multiply(Vl).mod(p);
- Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p);
- Ql = Ql.multiply(Ql).mod(p);
+ Uh = modMult(Uh, Vl);
+ Vl = modReduce(Vl.multiply(Vl).subtract(Ql.shiftLeft(1)));
+ Ql = modMult(Ql, Ql);
}
return new BigInteger[]{ Uh, Vl };
}
-
+
+ protected BigInteger modAdd(BigInteger x1, BigInteger x2)
+ {
+ BigInteger x3 = x1.add(x2);
+ if (x3.compareTo(q) >= 0)
+ {
+ x3 = x3.subtract(q);
+ }
+ return x3;
+ }
+
+ protected BigInteger modDouble(BigInteger x)
+ {
+ BigInteger _2x = x.shiftLeft(1);
+ if (_2x.compareTo(q) >= 0)
+ {
+ _2x = _2x.subtract(q);
+ }
+ return _2x;
+ }
+
+ protected BigInteger modMult(BigInteger x1, BigInteger x2)
+ {
+ return modReduce(x1.multiply(x2));
+ }
+
+ protected BigInteger modReduce(BigInteger x)
+ {
+// if (naf != null)
+// {
+// int last = naf.length - 1;
+// int bits = naf[last];
+// while (x.bitLength() > (bits + 1))
+// {
+// BigInteger u = x.shiftRight(bits);
+// BigInteger v = x.subtract(u.shiftLeft(bits));
+//
+// x = v;
+//
+// for (int i = 0; i < last; ++i)
+// {
+// int ni = naf[i];
+// if (ni < 0)
+// {
+// x = x.add(u.shiftLeft(~ni));
+// }
+// else
+// {
+// x = x.subtract(u.shiftLeft(ni));
+// }
+// }
+// }
+// while (x.compareTo(q) >= 0)
+// {
+// x = x.subtract(q);
+// }
+// }
+// else
+ if (r != null)
+ {
+ int qLen = q.bitLength();
+ while (x.bitLength() > (qLen + 1))
+ {
+ BigInteger u = x.shiftRight(qLen);
+ BigInteger v = x.subtract(u.shiftLeft(qLen));
+ if (!r.equals(ONE))
+ {
+ u = u.multiply(r);
+ }
+ x = u.add(v);
+ }
+ while (x.compareTo(q) >= 0)
+ {
+ x = x.subtract(q);
+ }
+ }
+ else
+ {
+ x = x.mod(q);
+ }
+ return x;
+ }
+
public boolean equals(Object other)
{
if (other == this)
@@ -669,7 +855,7 @@ public abstract class ECFieldElement
// g1z = g1z.xor(g2z.shiftLeft(j));
//// if (g1z.bitLength() > this.m) {
//// throw new ArithmeticException(
-//// "deg(g1z) >= m, g1z = " + g1z.toString(2));
+//// "deg(g1z) >= m, g1z = " + g1z.toString(16));
//// }
// }
// return new ECFieldElement.F2m(
@@ -801,41 +987,38 @@ public abstract class ECFieldElement
*/
private int m;
- /**
- * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
- * x<sup>k</sup> + 1</code> represents the reduction polynomial
- * <code>f(z)</code>.<br>
- * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br>
- */
- private int k1;
-
- /**
- * TPB: Always set to <code>0</code><br>
- * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br>
- */
- private int k2;
-
- /**
- * TPB: Always set to <code>0</code><br>
- * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br>
- */
- private int k3;
+// /**
+// * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
+// * x<sup>k</sup> + 1</code> represents the reduction polynomial
+// * <code>f(z)</code>.<br>
+// * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
+// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+// * represents the reduction polynomial <code>f(z)</code>.<br>
+// */
+// private int k1;
+//
+// /**
+// * TPB: Always set to <code>0</code><br>
+// * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
+// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+// * represents the reduction polynomial <code>f(z)</code>.<br>
+// */
+// private int k2;
+//
+// /**
+// * TPB: Always set to <code>0</code><br>
+// * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
+// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+// * represents the reduction polynomial <code>f(z)</code>.<br>
+// */
+// private int k3;
- /**
- * The <code>IntArray</code> holding the bits.
- */
- private IntArray x;
+ private int[] ks;
/**
- * The number of <code>int</code>s required to hold <code>m</code> bits.
+ * The <code>LongArray</code> holding the bits.
*/
- private int t;
+ private LongArray x;
/**
* Constructor for PPB.
@@ -851,6 +1034,7 @@ public abstract class ECFieldElement
* x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
* represents the reduction polynomial <code>f(z)</code>.
* @param x The BigInteger representing the value of the field element.
+ * @deprecated Use ECCurve.fromBigInteger to construct field elements
*/
public F2m(
int m,
@@ -859,13 +1043,10 @@ public abstract class ECFieldElement
int k3,
BigInteger x)
{
- // t = m / 32 rounded up to the next integer
- t = (m + 31) >> 5;
- this.x = new IntArray(x, t);
-
if ((k2 == 0) && (k3 == 0))
{
this.representation = TPB;
+ this.ks = new int[]{ k1 };
}
else
{
@@ -880,17 +1061,11 @@ public abstract class ECFieldElement
"k2 must be larger than 0");
}
this.representation = PPB;
- }
-
- if (x.signum() < 0)
- {
- throw new IllegalArgumentException("x value cannot be negative");
+ this.ks = new int[]{ k1, k2, k3 };
}
this.m = m;
- this.k1 = k1;
- this.k2 = k2;
- this.k3 = k3;
+ this.x = new LongArray(x);
}
/**
@@ -901,6 +1076,7 @@ public abstract class ECFieldElement
* x<sup>k</sup> + 1</code> represents the reduction
* polynomial <code>f(z)</code>.
* @param x The BigInteger representing the value of the field element.
+ * @deprecated Use ECCurve.fromBigInteger to construct field elements
*/
public F2m(int m, int k, BigInteger x)
{
@@ -908,24 +1084,27 @@ public abstract class ECFieldElement
this(m, k, 0, 0, x);
}
- private F2m(int m, int k1, int k2, int k3, IntArray x)
+ private F2m(int m, int[] ks, LongArray x)
{
- t = (m + 31) >> 5;
- this.x = x;
this.m = m;
- this.k1 = k1;
- this.k2 = k2;
- this.k3 = k3;
+ this.representation = (ks.length == 1) ? TPB : PPB;
+ this.ks = ks;
+ this.x = x;
+ }
- if ((k2 == 0) && (k3 == 0))
- {
- this.representation = TPB;
- }
- else
- {
- this.representation = PPB;
- }
+ public int bitLength()
+ {
+ return x.degree();
+ }
+
+ public boolean isZero()
+ {
+ return x.isZero();
+ }
+ public boolean testBitZero()
+ {
+ return x.testBitZero();
}
public BigInteger toBigInteger()
@@ -967,19 +1146,15 @@ public abstract class ECFieldElement
ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a;
ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b;
- if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1)
- || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3))
+ if (aF2m.representation != bF2m.representation)
{
- throw new IllegalArgumentException("Field elements are not "
- + "elements of the same field F2m");
+ // Should never occur
+ throw new IllegalArgumentException("One of the F2m field elements has incorrect representation");
}
- if (aF2m.representation != bF2m.representation)
+ if ((aF2m.m != bF2m.m) || !Arrays.areEqual(aF2m.ks, bF2m.ks))
{
- // Should never occur
- throw new IllegalArgumentException(
- "One of the field "
- + "elements are not elements has incorrect representation");
+ throw new IllegalArgumentException("Field elements are not elements of the same field F2m");
}
}
@@ -988,10 +1163,15 @@ public abstract class ECFieldElement
// No check performed here for performance reasons. Instead the
// elements involved are checked in ECPoint.F2m
// checkFieldElements(this, b);
- IntArray iarrClone = (IntArray)this.x.clone();
+ LongArray iarrClone = (LongArray)this.x.clone();
F2m bF2m = (F2m)b;
- iarrClone.addShifted(bF2m.x, 0);
- return new F2m(m, k1, k2, k3, iarrClone);
+ iarrClone.addShiftedByWords(bF2m.x, 0);
+ return new F2m(m, ks, iarrClone);
+ }
+
+ public ECFieldElement addOne()
+ {
+ return new F2m(m, ks, x.addOne());
}
public ECFieldElement subtract(final ECFieldElement b)
@@ -1002,17 +1182,14 @@ public abstract class ECFieldElement
public ECFieldElement multiply(final ECFieldElement b)
{
- // Right-to-left comb multiplication in the IntArray
+ // Right-to-left comb multiplication in the LongArray
// Input: Binary polynomials a(z) and b(z) of degree at most m-1
// Output: c(z) = a(z) * b(z) mod f(z)
// No check performed here for performance reasons. Instead the
// elements involved are checked in ECPoint.F2m
// checkFieldElements(this, b);
- F2m bF2m = (F2m)b;
- IntArray mult = x.multiply(bF2m.x, m);
- mult.reduce(m, new int[]{k1, k2, k3});
- return new F2m(m, k1, k2, k3, mult);
+ return new F2m(m, ks, x.modMultiply(((F2m)b).x, m, ks));
}
public ECFieldElement divide(final ECFieldElement b)
@@ -1030,80 +1207,12 @@ public abstract class ECFieldElement
public ECFieldElement square()
{
- IntArray squared = x.square(m);
- squared.reduce(m, new int[]{k1, k2, k3});
- return new F2m(m, k1, k2, k3, squared);
+ return new F2m(m, ks, x.modSquare(m, ks));
}
-
public ECFieldElement invert()
{
- // Inversion in F2m using the extended Euclidean algorithm
- // Input: A nonzero polynomial a(z) of degree at most m-1
- // Output: a(z)^(-1) mod f(z)
-
- // u(z) := a(z)
- IntArray uz = (IntArray)this.x.clone();
-
- // v(z) := f(z)
- IntArray vz = new IntArray(t);
- vz.setBit(m);
- vz.setBit(0);
- vz.setBit(this.k1);
- if (this.representation == PPB)
- {
- vz.setBit(this.k2);
- vz.setBit(this.k3);
- }
-
- // g1(z) := 1, g2(z) := 0
- IntArray g1z = new IntArray(t);
- g1z.setBit(0);
- IntArray g2z = new IntArray(t);
-
- // while u != 0
- while (!uz.isZero())
-// while (uz.getUsedLength() > 0)
-// while (uz.bitLength() > 1)
- {
- // j := deg(u(z)) - deg(v(z))
- int j = uz.bitLength() - vz.bitLength();
-
- // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j
- if (j < 0)
- {
- final IntArray uzCopy = uz;
- uz = vz;
- vz = uzCopy;
-
- final IntArray g1zCopy = g1z;
- g1z = g2z;
- g2z = g1zCopy;
-
- j = -j;
- }
-
- // u(z) := u(z) + z^j * v(z)
- // Note, that no reduction modulo f(z) is required, because
- // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z)))
- // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z))
- // = deg(u(z))
- // uz = uz.xor(vz.shiftLeft(j));
- // jInt = n / 32
- int jInt = j >> 5;
- // jInt = n % 32
- int jBit = j & 0x1F;
- IntArray vzShift = vz.shiftLeft(jBit);
- uz.addShifted(vzShift, jInt);
-
- // g1(z) := g1(z) + z^j * g2(z)
-// g1z = g1z.xor(g2z.shiftLeft(j));
- IntArray g2zShift = g2z.shiftLeft(jBit);
- g1z.addShifted(g2zShift, jInt);
-
- }
- return new ECFieldElement.F2m(
- this.m, this.k1, this.k2, this.k3, g2z);
+ return new ECFieldElement.F2m(this.m, this.ks, this.x.modInverse(m, ks));
}
public ECFieldElement sqrt()
@@ -1143,7 +1252,7 @@ public abstract class ECFieldElement
*/
public int getK1()
{
- return this.k1;
+ return this.ks[0];
}
/**
@@ -1154,7 +1263,7 @@ public abstract class ECFieldElement
*/
public int getK2()
{
- return this.k2;
+ return this.ks.length >= 2 ? this.ks[1] : 0;
}
/**
@@ -1165,7 +1274,7 @@ public abstract class ECFieldElement
*/
public int getK3()
{
- return this.k3;
+ return this.ks.length >= 3 ? this.ks[2] : 0;
}
public boolean equals(Object anObject)
@@ -1182,15 +1291,15 @@ public abstract class ECFieldElement
ECFieldElement.F2m b = (ECFieldElement.F2m)anObject;
- return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2)
- && (this.k3 == b.k3)
+ return ((this.m == b.m)
&& (this.representation == b.representation)
+ && Arrays.areEqual(this.ks, b.ks)
&& (this.x.equals(b.x)));
}
public int hashCode()
{
- return x.hashCode() ^ m ^ k1 ^ k2 ^ k3;
+ return x.hashCode() ^ m ^ Arrays.hashCode(ks);
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java
index 4d72e33..da1013a 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java
@@ -6,14 +6,14 @@ import java.math.BigInteger;
* Interface for classes encapsulating a point multiplication algorithm
* for <code>ECPoint</code>s.
*/
-interface ECMultiplier
+public interface ECMultiplier
{
/**
* Multiplies the <code>ECPoint p</code> by <code>k</code>, i.e.
* <code>p</code> is added <code>k</code> times to itself.
* @param p The <code>ECPoint</code> to be multiplied.
- * @param k The factor by which <code>p</code> i multiplied.
+ * @param k The factor by which <code>p</code> is multiplied.
* @return <code>p</code> multiplied by <code>k</code>.
*/
- ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo);
+ ECPoint multiply(ECPoint p, BigInteger k);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java
index cbc5aaf..7f740e4 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java
@@ -2,59 +2,324 @@ package org.bouncycastle.math.ec;
import java.math.BigInteger;
-import org.bouncycastle.asn1.x9.X9IntegerConverter;
-
/**
* base class for points on elliptic curves.
*/
public abstract class ECPoint
{
- ECCurve curve;
- ECFieldElement x;
- ECFieldElement y;
+ protected static ECFieldElement[] EMPTY_ZS = new ECFieldElement[0];
- protected boolean withCompression;
+ protected static ECFieldElement[] getInitialZCoords(ECCurve curve)
+ {
+ // Cope with null curve, most commonly used by implicitlyCa
+ int coord = null == curve ? ECCurve.COORD_AFFINE : curve.getCoordinateSystem();
- protected ECMultiplier multiplier = null;
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ return EMPTY_ZS;
+ default:
+ break;
+ }
- protected PreCompInfo preCompInfo = null;
+ ECFieldElement one = curve.fromBigInteger(ECConstants.ONE);
- private static X9IntegerConverter converter = new X9IntegerConverter();
+ switch (coord)
+ {
+ case ECCurve.COORD_HOMOGENEOUS:
+ case ECCurve.COORD_JACOBIAN:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ return new ECFieldElement[]{ one };
+ case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
+ return new ECFieldElement[]{ one, one, one };
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ return new ECFieldElement[]{ one, curve.getA() };
+ default:
+ throw new IllegalArgumentException("unknown coordinate system");
+ }
+ }
+
+ protected ECCurve curve;
+ protected ECFieldElement x;
+ protected ECFieldElement y;
+ protected ECFieldElement[] zs;
+
+ protected boolean withCompression;
+
+ protected PreCompInfo preCompInfo = null;
protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y)
{
+ this(curve, x, y, getInitialZCoords(curve));
+ }
+
+ protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs)
+ {
this.curve = curve;
this.x = x;
this.y = y;
+ this.zs = zs;
}
-
+
public ECCurve getCurve()
{
return curve;
}
-
+
+ protected int getCurveCoordinateSystem()
+ {
+ // Cope with null curve, most commonly used by implicitlyCa
+ return null == curve ? ECCurve.COORD_AFFINE : curve.getCoordinateSystem();
+ }
+
+ /**
+ * Normalizes this point, and then returns the affine x-coordinate.
+ *
+ * Note: normalization can be expensive, this method is deprecated in favour
+ * of caller-controlled normalization.
+ *
+ * @deprecated Use getAffineXCoord, or normalize() and getXCoord(), instead
+ */
public ECFieldElement getX()
{
- return x;
+ return normalize().getXCoord();
}
+
+ /**
+ * Normalizes this point, and then returns the affine y-coordinate.
+ *
+ * Note: normalization can be expensive, this method is deprecated in favour
+ * of caller-controlled normalization.
+ *
+ * @deprecated Use getAffineYCoord, or normalize() and getYCoord(), instead
+ */
public ECFieldElement getY()
{
+ return normalize().getYCoord();
+ }
+
+ /**
+ * Returns the affine x-coordinate after checking that this point is normalized.
+ *
+ * @return The affine x-coordinate of this point
+ * @throws IllegalStateException if the point is not normalized
+ */
+ public ECFieldElement getAffineXCoord()
+ {
+ checkNormalized();
+ return getXCoord();
+ }
+
+ /**
+ * Returns the affine y-coordinate after checking that this point is normalized
+ *
+ * @return The affine y-coordinate of this point
+ * @throws IllegalStateException if the point is not normalized
+ */
+ public ECFieldElement getAffineYCoord()
+ {
+ checkNormalized();
+ return getYCoord();
+ }
+
+ /**
+ * Returns the x-coordinate.
+ *
+ * Caution: depending on the curve's coordinate system, this may not be the same value as in an
+ * affine coordinate system; use normalize() to get a point where the coordinates have their
+ * affine values, or use getAffineXCoord if you expect the point to already have been
+ * normalized.
+ *
+ * @return the x-coordinate of this point
+ */
+ public ECFieldElement getXCoord()
+ {
+ return x;
+ }
+
+ /**
+ * Returns the y-coordinate.
+ *
+ * Caution: depending on the curve's coordinate system, this may not be the same value as in an
+ * affine coordinate system; use normalize() to get a point where the coordinates have their
+ * affine values, or use getAffineYCoord if you expect the point to already have been
+ * normalized.
+ *
+ * @return the y-coordinate of this point
+ */
+ public ECFieldElement getYCoord()
+ {
return y;
}
+ public ECFieldElement getZCoord(int index)
+ {
+ return (index < 0 || index >= zs.length) ? null : zs[index];
+ }
+
+ public ECFieldElement[] getZCoords()
+ {
+ int zsLen = zs.length;
+ if (zsLen == 0)
+ {
+ return zs;
+ }
+ ECFieldElement[] copy = new ECFieldElement[zsLen];
+ System.arraycopy(zs, 0, copy, 0, zsLen);
+ return copy;
+ }
+
+ protected ECFieldElement getRawXCoord()
+ {
+ return x;
+ }
+
+ protected ECFieldElement getRawYCoord()
+ {
+ return y;
+ }
+
+ protected void checkNormalized()
+ {
+ if (!isNormalized())
+ {
+ throw new IllegalStateException("point not in normal form");
+ }
+ }
+
+ public boolean isNormalized()
+ {
+ int coord = this.getCurveCoordinateSystem();
+
+ return coord == ECCurve.COORD_AFFINE
+ || coord == ECCurve.COORD_LAMBDA_AFFINE
+ || isInfinity()
+ || zs[0].bitLength() == 1;
+ }
+
+ /**
+ * Normalization ensures that any projective coordinate is 1, and therefore that the x, y
+ * coordinates reflect those of the equivalent point in an affine coordinate system.
+ *
+ * @return a new ECPoint instance representing the same point, but with normalized coordinates
+ */
+ public ECPoint normalize()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ switch (this.getCurveCoordinateSystem())
+ {
+ case ECCurve.COORD_AFFINE:
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ {
+ return this;
+ }
+ default:
+ {
+ ECFieldElement Z1 = getZCoord(0);
+ if (Z1.bitLength() == 1)
+ {
+ return this;
+ }
+
+ return normalize(Z1.invert());
+ }
+ }
+ }
+
+ ECPoint normalize(ECFieldElement zInv)
+ {
+ switch (this.getCurveCoordinateSystem())
+ {
+ case ECCurve.COORD_HOMOGENEOUS:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ return createScaledPoint(zInv, zInv);
+ }
+ case ECCurve.COORD_JACOBIAN:
+ case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ ECFieldElement zInv2 = zInv.square(), zInv3 = zInv2.multiply(zInv);
+ return createScaledPoint(zInv2, zInv3);
+ }
+ default:
+ {
+ throw new IllegalStateException("not a projective coordinate system");
+ }
+ }
+ }
+
+ protected ECPoint createScaledPoint(ECFieldElement sx, ECFieldElement sy)
+ {
+ return this.getCurve().createRawPoint(getRawXCoord().multiply(sx), getRawYCoord().multiply(sy), this.withCompression);
+ }
+
public boolean isInfinity()
{
- return x == null && y == null;
+ return x == null || y == null || (zs.length > 0 && zs[0].isZero());
}
public boolean isCompressed()
{
- return withCompression;
+ return this.withCompression;
+ }
+
+ public boolean equals(ECPoint other)
+ {
+ if (null == other)
+ {
+ return false;
+ }
+
+ ECCurve c1 = this.getCurve(), c2 = other.getCurve();
+ boolean n1 = (null == c1), n2 = (null == c2);
+ boolean i1 = isInfinity(), i2 = other.isInfinity();
+
+ if (i1 || i2)
+ {
+ return (i1 && i2) && (n1 || n2 || c1.equals(c2));
+ }
+
+ ECPoint p1 = this, p2 = other;
+ if (n1 && n2)
+ {
+ // Points with null curve are in affine form, so already normalized
+ }
+ else if (n1)
+ {
+ p2 = p2.normalize();
+ }
+ else if (n2)
+ {
+ p1 = p1.normalize();
+ }
+ else if (!c1.equals(c2))
+ {
+ return false;
+ }
+ else
+ {
+ // TODO Consider just requiring already normalized, to avoid silent performance degradation
+
+ ECPoint[] points = new ECPoint[]{ this, c1.importPoint(p2) };
+
+ // TODO This is a little strong, really only requires coZNormalizeAll to get Zs equal
+ c1.normalizeAll(points);
+
+ p1 = points[0];
+ p2 = points[1];
+ }
+
+ return p1.getXCoord().equals(p2.getXCoord()) && p1.getYCoord().equals(p2.getYCoord());
}
- public boolean equals(
- Object other)
+ public boolean equals(Object other)
{
if (other == this)
{
@@ -66,69 +331,117 @@ public abstract class ECPoint
return false;
}
- ECPoint o = (ECPoint)other;
+ return equals((ECPoint)other);
+ }
- if (this.isInfinity())
+ public int hashCode()
+ {
+ ECCurve c = this.getCurve();
+ int hc = (null == c) ? 0 : ~c.hashCode();
+
+ if (!this.isInfinity())
{
- return o.isInfinity();
+ // TODO Consider just requiring already normalized, to avoid silent performance degradation
+
+ ECPoint p = normalize();
+
+ hc ^= p.getXCoord().hashCode() * 17;
+ hc ^= p.getYCoord().hashCode() * 257;
}
- return x.equals(o.x) && y.equals(o.y);
+ return hc;
}
- public int hashCode()
+ public String toString()
{
if (this.isInfinity())
{
- return 0;
+ return "INF";
}
-
- return x.hashCode() ^ y.hashCode();
+
+ StringBuffer sb = new StringBuffer();
+ sb.append('(');
+ sb.append(getRawXCoord());
+ sb.append(',');
+ sb.append(getRawYCoord());
+ for (int i = 0; i < zs.length; ++i)
+ {
+ sb.append(',');
+ sb.append(zs[i]);
+ }
+ sb.append(')');
+ return sb.toString();
}
-// /**
-// * Mainly for testing. Explicitly set the <code>ECMultiplier</code>.
-// * @param multiplier The <code>ECMultiplier</code> to be used to multiply
-// * this <code>ECPoint</code>.
-// */
-// public void setECMultiplier(ECMultiplier multiplier)
-// {
-// this.multiplier = multiplier;
-// }
+ public byte[] getEncoded()
+ {
+ return getEncoded(this.withCompression);
+ }
/**
- * Sets the <code>PreCompInfo</code>. Used by <code>ECMultiplier</code>s
- * to save the precomputation for this <code>ECPoint</code> to store the
- * precomputation result for use by subsequent multiplication.
- * @param preCompInfo The values precomputed by the
- * <code>ECMultiplier</code>.
+ * return the field element encoded with point compression. (S 4.3.6)
*/
- void setPreCompInfo(PreCompInfo preCompInfo)
+ public byte[] getEncoded(boolean compressed)
{
- this.preCompInfo = preCompInfo;
- }
+ if (this.isInfinity())
+ {
+ return new byte[1];
+ }
- public byte[] getEncoded()
- {
- return getEncoded(withCompression);
+ ECPoint normed = normalize();
+
+ byte[] X = normed.getXCoord().getEncoded();
+
+ if (compressed)
+ {
+ byte[] PO = new byte[X.length + 1];
+ PO[0] = (byte)(normed.getCompressionYTilde() ? 0x03 : 0x02);
+ System.arraycopy(X, 0, PO, 1, X.length);
+ return PO;
+ }
+
+ byte[] Y = normed.getYCoord().getEncoded();
+
+ byte[] PO = new byte[X.length + Y.length + 1];
+ PO[0] = 0x04;
+ System.arraycopy(X, 0, PO, 1, X.length);
+ System.arraycopy(Y, 0, PO, X.length + 1, Y.length);
+ return PO;
}
- public abstract byte[] getEncoded(boolean compressed);
+ protected abstract boolean getCompressionYTilde();
public abstract ECPoint add(ECPoint b);
- public abstract ECPoint subtract(ECPoint b);
+
public abstract ECPoint negate();
- public abstract ECPoint twice();
- /**
- * Sets the default <code>ECMultiplier</code>, unless already set.
- */
- synchronized void assertECMultiplier()
+ public abstract ECPoint subtract(ECPoint b);
+
+ public ECPoint timesPow2(int e)
{
- if (this.multiplier == null)
+ if (e < 0)
+ {
+ throw new IllegalArgumentException("'e' cannot be negative");
+ }
+
+ ECPoint p = this;
+ while (--e >= 0)
{
- this.multiplier = new FpNafMultiplier();
+ p = p.twice();
}
+ return p;
+ }
+
+ public abstract ECPoint twice();
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ return twicePlus(this);
}
/**
@@ -138,23 +451,7 @@ public abstract class ECPoint
*/
public ECPoint multiply(BigInteger k)
{
- if (k.signum() < 0)
- {
- throw new IllegalArgumentException("The multiplicator cannot be negative");
- }
-
- if (this.isInfinity())
- {
- return this;
- }
-
- if (k.signum() == 0)
- {
- return this.curve.getInfinity();
- }
-
- assertECMultiplier();
- return this.multiplier.multiply(this, k, preCompInfo);
+ return this.getCurve().getMultiplier().multiply(this, k);
}
/**
@@ -162,13 +459,14 @@ public abstract class ECPoint
*/
public static class Fp extends ECPoint
{
-
/**
* Create a point which encodes with point compression.
*
* @param curve the curve to use
* @param x affine x co-ordinate
* @param y affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
*/
public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y)
{
@@ -182,6 +480,8 @@ public abstract class ECPoint
* @param x affine x co-ordinate
* @param y affine y co-ordinate
* @param withCompression if true encode with point compression
+ *
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
*/
public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
{
@@ -194,112 +494,537 @@ public abstract class ECPoint
this.withCompression = withCompression;
}
-
- /**
- * return the field element encoded with point compression. (S 4.3.6)
- */
- public byte[] getEncoded(boolean compressed)
+
+ Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
{
- if (this.isInfinity())
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected boolean getCompressionYTilde()
+ {
+ return this.getAffineYCoord().testBitZero();
+ }
+
+ public ECFieldElement getZCoord(int index)
+ {
+ if (index == 1 && ECCurve.COORD_JACOBIAN_MODIFIED == this.getCurveCoordinateSystem())
{
- return new byte[1];
+ return getJacobianModifiedW();
}
- int qLength = converter.getByteLength(x);
-
- if (compressed)
+ return super.getZCoord(index);
+ }
+
+ // B.3 pg 62
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
{
- byte PC;
-
- if (this.getY().toBigInteger().testBit(0))
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ ECFieldElement X1 = this.x, Y1 = this.y;
+ ECFieldElement X2 = b.x, Y2 = b.y;
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ {
+ ECFieldElement dx = X2.subtract(X1), dy = Y2.subtract(Y1);
+
+ if (dx.isZero())
{
- PC = 0x03;
+ if (dy.isZero())
+ {
+ // this == b, i.e. this must be doubled
+ return twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
}
- else
+
+ ECFieldElement gamma = dy.divide(dx);
+ ECFieldElement X3 = gamma.square().subtract(X1).subtract(X2);
+ ECFieldElement Y3 = gamma.multiply(X1.subtract(X3)).subtract(Y1);
+
+ return new ECPoint.Fp(curve, X3, Y3, this.withCompression);
+ }
+
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Z1 = this.zs[0];
+ ECFieldElement Z2 = b.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+ boolean Z2IsOne = Z2.bitLength() == 1;
+
+ ECFieldElement u1 = Z1IsOne ? Y2 : Y2.multiply(Z1);
+ ECFieldElement u2 = Z2IsOne ? Y1 : Y1.multiply(Z2);
+ ECFieldElement u = u1.subtract(u2);
+ ECFieldElement v1 = Z1IsOne ? X2 : X2.multiply(Z1);
+ ECFieldElement v2 = Z2IsOne ? X1 : X1.multiply(Z2);
+ ECFieldElement v = v1.subtract(v2);
+
+ // Check if b == this or b == -this
+ if (v.isZero())
{
- PC = 0x02;
+ if (u.isZero())
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
}
+
+ // TODO Optimize for when w == 1
+ ECFieldElement w = Z1IsOne ? Z2 : Z2IsOne ? Z1 : Z1.multiply(Z2);
+ ECFieldElement vSquared = v.square();
+ ECFieldElement vCubed = vSquared.multiply(v);
+ ECFieldElement vSquaredV2 = vSquared.multiply(v2);
+ ECFieldElement A = u.square().multiply(w).subtract(vCubed).subtract(two(vSquaredV2));
+
+ ECFieldElement X3 = v.multiply(A);
+ ECFieldElement Y3 = vSquaredV2.subtract(A).multiply(u).subtract(vCubed.multiply(u2));
+ ECFieldElement Z3 = vCubed.multiply(w);
+
+ return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ case ECCurve.COORD_JACOBIAN:
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ ECFieldElement Z1 = this.zs[0];
+ ECFieldElement Z2 = b.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+
+ ECFieldElement X3, Y3, Z3, Z3Squared = null;
+
+ if (!Z1IsOne && Z1.equals(Z2))
+ {
+ // TODO Make this available as public method coZAdd?
+
+ ECFieldElement dx = X1.subtract(X2), dy = Y1.subtract(Y2);
+ if (dx.isZero())
+ {
+ if (dy.isZero())
+ {
+ return twice();
+ }
+ return curve.getInfinity();
+ }
+
+ ECFieldElement C = dx.square();
+ ECFieldElement W1 = X1.multiply(C), W2 = X2.multiply(C);
+ ECFieldElement A1 = W1.subtract(W2).multiply(Y1);
+
+ X3 = dy.square().subtract(W1).subtract(W2);
+ Y3 = W1.subtract(X3).multiply(dy).subtract(A1);
+ Z3 = dx;
+
+ if (Z1IsOne)
+ {
+ Z3Squared = C;
+ }
+ else
+ {
+ Z3 = Z3.multiply(Z1);
+ }
+ }
+ else
+ {
+ ECFieldElement Z1Squared, U2, S2;
+ if (Z1IsOne)
+ {
+ Z1Squared = Z1; U2 = X2; S2 = Y2;
+ }
+ else
+ {
+ Z1Squared = Z1.square();
+ U2 = Z1Squared.multiply(X2);
+ ECFieldElement Z1Cubed = Z1Squared.multiply(Z1);
+ S2 = Z1Cubed.multiply(Y2);
+ }
+
+ boolean Z2IsOne = Z2.bitLength() == 1;
+ ECFieldElement Z2Squared, U1, S1;
+ if (Z2IsOne)
+ {
+ Z2Squared = Z2; U1 = X1; S1 = Y1;
+ }
+ else
+ {
+ Z2Squared = Z2.square();
+ U1 = Z2Squared.multiply(X1);
+ ECFieldElement Z2Cubed = Z2Squared.multiply(Z2);
+ S1 = Z2Cubed.multiply(Y1);
+ }
+
+ ECFieldElement H = U1.subtract(U2);
+ ECFieldElement R = S1.subtract(S2);
+
+ // Check if b == this or b == -this
+ if (H.isZero())
+ {
+ if (R.isZero())
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
- byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
- byte[] PO = new byte[X.length + 1];
+ ECFieldElement HSquared = H.square();
+ ECFieldElement G = HSquared.multiply(H);
+ ECFieldElement V = HSquared.multiply(U1);
- PO[0] = PC;
- System.arraycopy(X, 0, PO, 1, X.length);
+ X3 = R.square().add(G).subtract(two(V));
+ Y3 = V.subtract(X3).multiply(R).subtract(S1.multiply(G));
- return PO;
+ Z3 = H;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.multiply(Z1);
+ }
+ if (!Z2IsOne)
+ {
+ Z3 = Z3.multiply(Z2);
+ }
+
+ // Alternative calculation of Z3 using fast square
+ // X3 = four(X3);
+ // Y3 = eight(Y3);
+ // Z3 = doubleProductFromSquares(Z1, Z2, Z1Squared, Z2Squared).multiply(H);
+
+ if (Z3 == H)
+ {
+ Z3Squared = HSquared;
+ }
+ }
+
+ ECFieldElement[] zs;
+ if (coord == ECCurve.COORD_JACOBIAN_MODIFIED)
+ {
+ // TODO If the result will only be used in a subsequent addition, we don't need W3
+ ECFieldElement W3 = calculateJacobianModifiedW(Z3, Z3Squared);
+
+ zs = new ECFieldElement[]{ Z3, W3 };
+ }
+ else
+ {
+ zs = new ECFieldElement[]{ Z3 };
+ }
+
+ return new ECPoint.Fp(curve, X3, Y3, zs, this.withCompression);
}
- else
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+ }
+ }
+
+ // B.3 pg 62
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ int coord = curve.getCoordinateSystem();
+
+ ECFieldElement X1 = this.x;
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ {
+ ECFieldElement X1Squared = X1.square();
+ ECFieldElement gamma = three(X1Squared).add(this.getCurve().getA()).divide(two(Y1));
+ ECFieldElement X3 = gamma.square().subtract(two(X1));
+ ECFieldElement Y3 = gamma.multiply(X1.subtract(X3)).subtract(Y1);
+
+ return new ECPoint.Fp(curve, X3, Y3, this.withCompression);
+ }
+
+ case ECCurve.COORD_HOMOGENEOUS:
{
- byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
- byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), qLength);
- byte[] PO = new byte[X.length + Y.length + 1];
+ ECFieldElement Z1 = this.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+ ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
+
+ // TODO Optimize for small negative a4 and -3
+ ECFieldElement w = curve.getA();
+ if (!Z1IsOne)
+ {
+ w = w.multiply(Z1Squared);
+ }
+ w = w.add(three(X1.square()));
- PO[0] = 0x04;
- System.arraycopy(X, 0, PO, 1, X.length);
- System.arraycopy(Y, 0, PO, X.length + 1, Y.length);
+ ECFieldElement s = Z1IsOne ? Y1 : Y1.multiply(Z1);
+ ECFieldElement t = Z1IsOne ? Y1.square() : s.multiply(Y1);
+ ECFieldElement B = X1.multiply(t);
+ ECFieldElement _4B = four(B);
+ ECFieldElement h = w.square().subtract(two(_4B));
+
+ ECFieldElement X3 = two(h.multiply(s));
+ ECFieldElement Y3 = w.multiply(_4B.subtract(h)).subtract(two(two(t).square()));
+ ECFieldElement _4sSquared = Z1IsOne ? four(t) : two(s).square();
+ ECFieldElement Z3 = two(_4sSquared).multiply(s);
+
+ return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ case ECCurve.COORD_JACOBIAN:
+ {
+ ECFieldElement Z1 = this.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+ ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
+
+ ECFieldElement Y1Squared = Y1.square();
+ ECFieldElement T = Y1Squared.square();
+
+ ECFieldElement a4 = curve.getA();
+ ECFieldElement a4Neg = a4.negate();
+
+ ECFieldElement M, S;
+ if (a4Neg.toBigInteger().equals(BigInteger.valueOf(3)))
+ {
+ M = three(X1.add(Z1Squared).multiply(X1.subtract(Z1Squared)));
+ S = four(Y1Squared.multiply(X1));
+ }
+ else
+ {
+ ECFieldElement X1Squared = X1.square();
+ M = three(X1Squared);
+ if (Z1IsOne)
+ {
+ M = M.add(a4);
+ }
+ else
+ {
+ ECFieldElement Z1Pow4 = Z1Squared.square();
+ if (a4Neg.bitLength() < a4.bitLength())
+ {
+ M = M.subtract(Z1Pow4.multiply(a4Neg));
+ }
+ else
+ {
+ M = M.add(Z1Pow4.multiply(a4));
+ }
+ }
+ S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T));
+ }
+
+ ECFieldElement X3 = M.square().subtract(two(S));
+ ECFieldElement Y3 = S.subtract(X3).multiply(M).subtract(eight(T));
+
+ ECFieldElement Z3 = two(Y1);
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.multiply(Z1);
+ }
- return PO;
+ // Alternative calculation of Z3 using fast square
+// ECFieldElement Z3 = doubleProductFromSquares(Y1, Z1, Y1Squared, Z1Squared);
+
+ return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ return twiceJacobianModified(true);
+ }
+
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
}
}
- // B.3 pg 62
- public ECPoint add(ECPoint b)
+ public ECPoint twicePlus(ECPoint b)
{
+ if (this == b)
+ {
+ return threeTimes();
+ }
if (this.isInfinity())
{
return b;
}
-
if (b.isInfinity())
{
- return this;
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
}
- // Check if b = this or b = -this
- if (this.x.equals(b.x))
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
{
- if (this.y.equals(b.y))
+ ECFieldElement X1 = this.x;
+ ECFieldElement X2 = b.x, Y2 = b.y;
+
+ ECFieldElement dx = X2.subtract(X1), dy = Y2.subtract(Y1);
+
+ if (dx.isZero())
{
- // this = b, i.e. this must be doubled
- return this.twice();
+ if (dy.isZero())
+ {
+ // this == b i.e. the result is 3P
+ return threeTimes();
+ }
+
+ // this == -b, i.e. the result is P
+ return this;
}
- // this = -b, i.e. the result is the point at infinity
- return this.curve.getInfinity();
- }
+ /*
+ * Optimized calculation of 2P + Q, as described in "Trading Inversions for
+ * Multiplications in Elliptic Curve Cryptography", by Ciet, Joye, Lauter, Montgomery.
+ */
- ECFieldElement gamma = b.y.subtract(this.y).divide(b.x.subtract(this.x));
+ ECFieldElement X = dx.square(), Y = dy.square();
+ ECFieldElement d = X.multiply(two(X1).add(X2)).subtract(Y);
+ if (d.isZero())
+ {
+ return curve.getInfinity();
+ }
- ECFieldElement x3 = gamma.square().subtract(this.x).subtract(b.x);
- ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
+ ECFieldElement D = d.multiply(dx);
+ ECFieldElement I = D.invert();
+ ECFieldElement L1 = d.multiply(I).multiply(dy);
+ ECFieldElement L2 = two(Y1).multiply(X).multiply(dx).multiply(I).subtract(L1);
+ ECFieldElement X4 = (L2.subtract(L1)).multiply(L1.add(L2)).add(X2);
+ ECFieldElement Y4 = (X1.subtract(X4)).multiply(L2).subtract(Y1);
- return new ECPoint.Fp(curve, x3, y3, withCompression);
+ return new ECPoint.Fp(curve, X4, Y4, this.withCompression);
+ }
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ return twiceJacobianModified(false).add(b);
+ }
+ default:
+ {
+ return twice().add(b);
+ }
+ }
}
- // B.3 pg 62
- public ECPoint twice()
+ public ECPoint threeTimes()
{
- if (this.isInfinity())
+ if (this.isInfinity() || this.y.isZero())
{
- // Twice identity element (point at infinity) is identity
return this;
}
- if (this.y.toBigInteger().signum() == 0)
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
{
- // if y1 == 0, then (x1, y1) == (x1, -y1)
- // and hence this = -this and thus 2(x1, y1) == infinity
- return this.curve.getInfinity();
+ ECFieldElement X1 = this.x, Y1 = this.y;
+
+ ECFieldElement _2Y1 = two(Y1);
+ ECFieldElement X = _2Y1.square();
+ ECFieldElement Z = three(X1.square()).add(this.getCurve().getA());
+ ECFieldElement Y = Z.square();
+
+ ECFieldElement d = three(X1).multiply(X).subtract(Y);
+ if (d.isZero())
+ {
+ return this.getCurve().getInfinity();
+ }
+
+ ECFieldElement D = d.multiply(_2Y1);
+ ECFieldElement I = D.invert();
+ ECFieldElement L1 = d.multiply(I).multiply(Z);
+ ECFieldElement L2 = X.square().multiply(I).subtract(L1);
+
+ ECFieldElement X4 = (L2.subtract(L1)).multiply(L1.add(L2)).add(X1);
+ ECFieldElement Y4 = (X1.subtract(X4)).multiply(L2).subtract(Y1);
+ return new ECPoint.Fp(curve, X4, Y4, this.withCompression);
+ }
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ return twiceJacobianModified(false).add(this);
+ }
+ default:
+ {
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
}
+ }
+ }
- ECFieldElement TWO = this.curve.fromBigInteger(BigInteger.valueOf(2));
- ECFieldElement THREE = this.curve.fromBigInteger(BigInteger.valueOf(3));
- ECFieldElement gamma = this.x.square().multiply(THREE).add(curve.a).divide(y.multiply(TWO));
+ protected ECFieldElement two(ECFieldElement x)
+ {
+ return x.add(x);
+ }
- ECFieldElement x3 = gamma.square().subtract(this.x.multiply(TWO));
- ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
-
- return new ECPoint.Fp(curve, x3, y3, this.withCompression);
+ protected ECFieldElement three(ECFieldElement x)
+ {
+ return two(x).add(x);
+ }
+
+ protected ECFieldElement four(ECFieldElement x)
+ {
+ return two(two(x));
+ }
+
+ protected ECFieldElement eight(ECFieldElement x)
+ {
+ return four(two(x));
+ }
+
+ protected ECFieldElement doubleProductFromSquares(ECFieldElement a, ECFieldElement b,
+ ECFieldElement aSquared, ECFieldElement bSquared)
+ {
+ /*
+ * NOTE: If squaring in the field is faster than multiplication, then this is a quicker
+ * way to calculate 2.A.B, if A^2 and B^2 are already known.
+ */
+ return a.add(b).square().subtract(aSquared).subtract(bSquared);
}
// D.3.2 pg 102 (see Note:)
@@ -316,18 +1041,70 @@ public abstract class ECPoint
public ECPoint negate()
{
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ if (ECCurve.COORD_AFFINE != coord)
+ {
+ return new ECPoint.Fp(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+
return new ECPoint.Fp(curve, this.x, this.y.negate(), this.withCompression);
}
- /**
- * Sets the default <code>ECMultiplier</code>, unless already set.
- */
- synchronized void assertECMultiplier()
+ protected ECFieldElement calculateJacobianModifiedW(ECFieldElement Z, ECFieldElement ZSquared)
{
- if (this.multiplier == null)
+ if (ZSquared == null)
+ {
+ ZSquared = Z.square();
+ }
+
+ ECFieldElement W = ZSquared.square();
+ ECFieldElement a4 = this.getCurve().getA();
+ ECFieldElement a4Neg = a4.negate();
+ if (a4Neg.bitLength() < a4.bitLength())
{
- this.multiplier = new WNafMultiplier();
+ W = W.multiply(a4Neg).negate();
}
+ else
+ {
+ W = W.multiply(a4);
+ }
+ return W;
+ }
+
+ protected ECFieldElement getJacobianModifiedW()
+ {
+ ECFieldElement W = this.zs[1];
+ if (W == null)
+ {
+ // NOTE: Rarely, twicePlus will result in the need for a lazy W1 calculation here
+ this.zs[1] = W = calculateJacobianModifiedW(this.zs[0], null);
+ }
+ return W;
+ }
+
+ protected ECPoint.Fp twiceJacobianModified(boolean calculateW)
+ {
+ ECFieldElement X1 = this.x, Y1 = this.y, Z1 = this.zs[0], W1 = getJacobianModifiedW();
+
+ ECFieldElement X1Squared = X1.square();
+ ECFieldElement M = three(X1Squared).add(W1);
+ ECFieldElement Y1Squared = Y1.square();
+ ECFieldElement T = Y1Squared.square();
+ ECFieldElement S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T));
+ ECFieldElement X3 = M.square().subtract(two(S));
+ ECFieldElement _8T = eight(T);
+ ECFieldElement Y3 = M.multiply(S.subtract(X3)).subtract(_8T);
+ ECFieldElement W3 = calculateW ? two(_8T.multiply(W1)) : null;
+ ECFieldElement Z3 = two(Z1.bitLength() == 1 ? Y1 : Y1.multiply(Z1));
+
+ return new ECPoint.Fp(this.getCurve(), X3, Y3, new ECFieldElement[]{ Z3, W3 }, this.withCompression);
}
}
@@ -340,6 +1117,8 @@ public abstract class ECPoint
* @param curve base curve
* @param x x point
* @param y y point
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
*/
public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
{
@@ -351,6 +1130,8 @@ public abstract class ECPoint
* @param x x point
* @param y y point
* @param withCompression true if encode with point compression.
+ *
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
*/
public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
{
@@ -360,71 +1141,91 @@ public abstract class ECPoint
{
throw new IllegalArgumentException("Exactly one of the field elements is null");
}
-
+
if (x != null)
{
// Check if x and y are elements of the same field
ECFieldElement.F2m.checkFieldElements(this.x, this.y);
-
+
// Check if x and a are elements of the same field
if (curve != null)
{
ECFieldElement.F2m.checkFieldElements(this.x, this.curve.getA());
}
}
-
+
this.withCompression = withCompression;
+
+// checkCurveEquation();
}
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#getEncoded()
- */
- public byte[] getEncoded(boolean compressed)
+ F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
{
- if (this.isInfinity())
- {
- return new byte[1];
- }
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+
+// checkCurveEquation();
+ }
- int byteCount = converter.getByteLength(this.x);
- byte[] X = converter.integerToBytes(this.getX().toBigInteger(), byteCount);
- byte[] PO;
+ public ECFieldElement getYCoord()
+ {
+ int coord = this.getCurveCoordinateSystem();
- if (compressed)
+ switch (coord)
+ {
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
{
- // See X9.62 4.3.6 and 4.2.2
- PO = new byte[byteCount + 1];
+ // TODO The X == 0 stuff needs further thought
+ if (this.isInfinity() || x.isZero())
+ {
+ return y;
+ }
- PO[0] = 0x02;
- // X9.62 4.2.2 and 4.3.6:
- // if x = 0 then ypTilde := 0, else ypTilde is the rightmost
- // bit of y * x^(-1)
- // if ypTilde = 0, then PC := 02, else PC := 03
- // Note: PC === PO[0]
- if (!(this.getX().toBigInteger().equals(ECConstants.ZERO)))
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement X = x, L = y;
+ ECFieldElement Y = L.subtract(X).multiply(X);
+ if (ECCurve.COORD_LAMBDA_PROJECTIVE == coord)
{
- if (this.getY().multiply(this.getX().invert())
- .toBigInteger().testBit(0))
+ ECFieldElement Z = zs[0];
+ if (Z.bitLength() != 1)
{
- // ypTilde = 1, hence PC = 03
- PO[0] = 0x03;
+ Y = Y.divide(Z);
}
}
-
- System.arraycopy(X, 0, PO, 1, byteCount);
+ return Y;
}
- else
+ default:
{
- byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), byteCount);
-
- PO = new byte[byteCount + byteCount + 1];
-
- PO[0] = 0x04;
- System.arraycopy(X, 0, PO, 1, byteCount);
- System.arraycopy(Y, 0, PO, byteCount + 1, byteCount);
+ return y;
+ }
+ }
+ }
+
+ protected boolean getCompressionYTilde()
+ {
+ ECFieldElement X = this.getRawXCoord();
+ if (X.isZero())
+ {
+ return false;
}
- return PO;
+ ECFieldElement Y = this.getRawYCoord();
+
+ switch (this.getCurveCoordinateSystem())
+ {
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ // Y is actually Lambda (X + Y/X) here
+ return Y.subtract(X).testBitZero();
+ }
+ default:
+ {
+ return Y.divide(X).testBitZero();
+ }
+ }
}
/**
@@ -437,7 +1238,7 @@ public abstract class ECPoint
private static void checkPoints(ECPoint a, ECPoint b)
{
// Check, if points are on the same curve
- if (!(a.curve.equals(b.curve)))
+ if (a.curve != b.curve)
{
throw new IllegalArgumentException("Only points on the same "
+ "curve can be added or subtracted");
@@ -466,43 +1267,162 @@ public abstract class ECPoint
*/
public ECPoint.F2m addSimple(ECPoint.F2m b)
{
- ECPoint.F2m other = b;
if (this.isInfinity())
{
- return other;
+ return b;
}
-
- if (other.isInfinity())
+ if (b.isInfinity())
{
return this;
}
- ECFieldElement.F2m x2 = (ECFieldElement.F2m)other.getX();
- ECFieldElement.F2m y2 = (ECFieldElement.F2m)other.getY();
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ ECFieldElement X1 = this.x;
+ ECFieldElement X2 = b.x;
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ {
+ ECFieldElement Y1 = this.y;
+ ECFieldElement Y2 = b.y;
+
+ if (X1.equals(X2))
+ {
+ if (Y1.equals(Y2))
+ {
+ return (ECPoint.F2m)twice();
+ }
+
+ return (ECPoint.F2m)curve.getInfinity();
+ }
+
+ ECFieldElement sumX = X1.add(X2);
+ ECFieldElement L = Y1.add(Y2).divide(sumX);
+
+ ECFieldElement X3 = L.square().add(L).add(sumX).add(curve.getA());
+ ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1);
- // Check if other = this or other = -this
- if (this.x.equals(x2))
+ return new ECPoint.F2m(curve, X3, Y3, this.withCompression);
+ }
+ case ECCurve.COORD_HOMOGENEOUS:
{
- if (this.y.equals(y2))
+ ECFieldElement Y1 = this.y, Z1 = this.zs[0];
+ ECFieldElement Y2 = b.y, Z2 = b.zs[0];
+
+ boolean Z2IsOne = Z2.bitLength() == 1;
+
+ ECFieldElement U1 = Z1.multiply(Y2);
+ ECFieldElement U2 = Z2IsOne ? Y1 : Y1.multiply(Z2);
+ ECFieldElement U = U1.subtract(U2);
+ ECFieldElement V1 = Z1.multiply(X2);
+ ECFieldElement V2 = Z2IsOne ? X1 : X1.multiply(Z2);
+ ECFieldElement V = V1.subtract(V2);
+
+ if (V1.equals(V2))
{
- // this = other, i.e. this must be doubled
- return (ECPoint.F2m)this.twice();
+ if (U1.equals(U2))
+ {
+ return (ECPoint.F2m)twice();
+ }
+
+ return (ECPoint.F2m)curve.getInfinity();
}
- // this = -other, i.e. the result is the point at infinity
- return (ECPoint.F2m)this.curve.getInfinity();
+ ECFieldElement VSq = V.square();
+ ECFieldElement W = Z2IsOne ? Z1 : Z1.multiply(Z2);
+ ECFieldElement A = U.square().add(U.multiply(V).add(VSq.multiply(curve.getA()))).multiply(W).add(V.multiply(VSq));
+
+ ECFieldElement X3 = V.multiply(A);
+ ECFieldElement VSqZ2 = Z2IsOne ? VSq : VSq.multiply(Z2);
+ ECFieldElement Y3 = VSqZ2.multiply(U.multiply(X1).add(Y1.multiply(V))).add(A.multiply(U.add(V)));
+ ECFieldElement Z3 = VSq.multiply(V).multiply(W);
+
+ return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
}
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ if (X1.isZero())
+ {
+ return b.addSimple(this);
+ }
- ECFieldElement.F2m lambda
- = (ECFieldElement.F2m)(this.y.add(y2)).divide(this.x.add(x2));
+ ECFieldElement L1 = this.y, Z1 = this.zs[0];
+ ECFieldElement L2 = b.y, Z2 = b.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.multiply(Z1);
+ S2 = S2.multiply(Z1);
+ }
- ECFieldElement.F2m x3
- = (ECFieldElement.F2m)lambda.square().add(lambda).add(this.x).add(x2).add(this.curve.getA());
+ boolean Z2IsOne = Z2.bitLength() == 1;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.multiply(Z2);
+ S1 = S1.multiply(Z2);
+ }
- ECFieldElement.F2m y3
- = (ECFieldElement.F2m)lambda.multiply(this.x.add(x3)).add(x3).add(this.y);
+ ECFieldElement A = S1.add(S2);
+ ECFieldElement B = U1.add(U2);
- return new ECPoint.F2m(curve, x3, y3, withCompression);
+ if (B.isZero())
+ {
+ if (A.isZero())
+ {
+ return (ECPoint.F2m)twice();
+ }
+
+ return (ECPoint.F2m)curve.getInfinity();
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.isZero())
+ {
+ // TODO This can probably be optimized quite a bit
+
+ ECFieldElement Y1 = getYCoord(), Y2 = L2;
+ ECFieldElement L = Y1.add(Y2).divide(X1);
+
+ X3 = L.square().add(L).add(X1).add(curve.getA());
+ ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1);
+ L3 = X3.isZero() ? Y3 : Y3.divide(X3).add(X3);
+ Z3 = curve.fromBigInteger(ECConstants.ONE);
+ }
+ else
+ {
+ B = B.square();
+
+ ECFieldElement AU1 = A.multiply(U1);
+ ECFieldElement AU2 = A.multiply(U2);
+ ECFieldElement ABZ2 = A.multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.multiply(Z2);
+ }
+
+ X3 = AU1.multiply(AU2);
+ L3 = AU2.add(B).square().add(ABZ2.multiply(L1.add(Z1)));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.multiply(Z1);
+ }
+ }
+
+ return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+ }
}
/* (non-Javadoc)
@@ -534,59 +1454,279 @@ public abstract class ECPoint
return addSimple((ECPoint.F2m)b.negate());
}
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#twice()
- */
+ public ECPoint.F2m tau()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ ECFieldElement X1 = this.x;
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ {
+ ECFieldElement Y1 = this.y;
+ return new ECPoint.F2m(curve, X1.square(), Y1.square(), this.withCompression);
+ }
+ case ECCurve.COORD_HOMOGENEOUS:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ ECFieldElement Y1 = this.y, Z1 = this.zs[0];
+ return new ECPoint.F2m(curve, X1.square(), Y1.square(), new ECFieldElement[]{ Z1.square() }, this.withCompression);
+ }
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+ }
+ }
+
public ECPoint twice()
{
if (this.isInfinity())
{
- // Twice identity element (point at infinity) is identity
return this;
}
- if (this.x.toBigInteger().signum() == 0)
+ ECCurve curve = this.getCurve();
+
+ ECFieldElement X1 = this.x;
+ if (X1.isZero())
{
- // if x1 == 0, then (x1, y1) == (x1, x1 + y1)
- // and hence this = -this and thus 2(x1, y1) == infinity
- return this.curve.getInfinity();
+ // A point with X == 0 is it's own additive inverse
+ return curve.getInfinity();
}
- ECFieldElement.F2m lambda
- = (ECFieldElement.F2m)this.x.add(this.y.divide(this.x));
+ int coord = curve.getCoordinateSystem();
- ECFieldElement.F2m x3
- = (ECFieldElement.F2m)lambda.square().add(lambda).
- add(this.curve.getA());
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ {
+ ECFieldElement Y1 = this.y;
- ECFieldElement ONE = this.curve.fromBigInteger(ECConstants.ONE);
- ECFieldElement.F2m y3
- = (ECFieldElement.F2m)this.x.square().add(
- x3.multiply(lambda.add(ONE)));
+ ECFieldElement L1 = Y1.divide(X1).add(X1);
- return new ECPoint.F2m(this.curve, x3, y3, withCompression);
- }
+ ECFieldElement X3 = L1.square().add(L1).add(curve.getA());
+ ECFieldElement Y3 = X1.square().add(X3.multiply(L1.addOne()));
- public ECPoint negate()
- {
- return new ECPoint.F2m(curve, this.getX(), this.getY().add(this.getX()), withCompression);
+ return new ECPoint.F2m(curve, X3, Y3, this.withCompression);
+ }
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Y1 = this.y, Z1 = this.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.multiply(Z1);
+ ECFieldElement Y1Z1 = Z1IsOne ? Y1 : Y1.multiply(Z1);
+
+ ECFieldElement X1Sq = X1.square();
+ ECFieldElement S = X1Sq.add(Y1Z1);
+ ECFieldElement V = X1Z1;
+ ECFieldElement vSquared = V.square();
+ ECFieldElement h = S.square().add(S.multiply(V)).add(curve.getA().multiply(vSquared));
+
+ ECFieldElement X3 = V.multiply(h);
+ ECFieldElement Y3 = h.multiply(S.add(V)).add(X1Sq.square().multiply(V));
+ ECFieldElement Z3 = V.multiply(vSquared);
+
+ return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ ECFieldElement L1 = this.y, Z1 = this.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.square();
+ ECFieldElement a = curve.getA();
+ ECFieldElement aZ1Sq = Z1IsOne ? a : a.multiply(Z1Sq);
+ ECFieldElement T = L1.square().add(L1Z1).add(aZ1Sq);
+
+ ECFieldElement X3 = T.square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.multiply(Z1Sq);
+
+ ECFieldElement b = curve.getB();
+ ECFieldElement L3;
+ if (b.bitLength() < (curve.getFieldSize() >> 1))
+ {
+ ECFieldElement t1 = L1.add(X1).square();
+ ECFieldElement t2 = aZ1Sq.square();
+ ECFieldElement t3 = curve.getB().multiply(Z1Sq.square());
+ L3 = t1.add(T).add(Z1Sq).multiply(t1).add(t2.add(t3)).add(X3).add(a.addOne().multiply(Z3));
+ }
+ else
+ {
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.multiply(Z1);
+ L3 = X1Z1.square().add(X3).add(T.multiply(L1Z1)).add(Z3);
+ }
+
+ return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+ }
}
- /**
- * Sets the appropriate <code>ECMultiplier</code>, unless already set.
- */
- synchronized void assertECMultiplier()
+ public ECPoint twicePlus(ECPoint b)
{
- if (this.multiplier == null)
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
{
- if (((ECCurve.F2m)this.curve).isKoblitz())
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ ECFieldElement X1 = this.x;
+ if (X1.isZero())
+ {
+ // A point with X == 0 is it's own additive inverse
+ return b;
+ }
+
+ int coord = curve.getCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ // NOTE: twicePlus() only optimized for lambda-affine argument
+ ECFieldElement X2 = b.x, Z2 = b.zs[0];
+ if (X2.isZero() || Z2.bitLength() != 1)
{
- this.multiplier = new WTauNafMultiplier();
+ return twice().add(b);
}
- else
+
+ ECFieldElement L1 = this.y, Z1 = this.zs[0];
+ ECFieldElement L2 = b.y;
+
+ ECFieldElement X1Sq = X1.square();
+ ECFieldElement L1Sq = L1.square();
+ ECFieldElement Z1Sq = Z1.square();
+ ECFieldElement L1Z1 = L1.multiply(Z1);
+
+ ECFieldElement T = curve.getA().multiply(Z1Sq).add(L1Sq).add(L1Z1);
+ ECFieldElement L2plus1 = L2.addOne();
+ ECFieldElement A = curve.getA().add(L2plus1).multiply(Z1Sq).add(L1Sq).multiply(T).add(X1Sq.multiply(Z1Sq));
+ ECFieldElement X2Z1Sq = X2.multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.add(T).square();
+
+ ECFieldElement X3 = A.square().multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.multiply(B).multiply(Z1Sq);
+ ECFieldElement L3 = A.add(B).square().multiply(T).add(L2plus1.multiply(Z3));
+
+ return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+ default:
+ {
+ return twice().add(b);
+ }
+ }
+ }
+
+ protected void checkCurveEquation()
+ {
+ if (this.isInfinity())
+ {
+ return;
+ }
+
+ ECFieldElement Z;
+ switch (this.getCurveCoordinateSystem())
+ {
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ Z = curve.fromBigInteger(ECConstants.ONE);
+ break;
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ Z = this.zs[0];
+ break;
+ default:
+ return;
+ }
+
+ if (Z.isZero())
+ {
+ throw new IllegalStateException();
+ }
+
+ ECFieldElement X = this.x;
+ if (X.isZero())
+ {
+ // NOTE: For x == 0, we expect the affine-y instead of the lambda-y
+ ECFieldElement Y = this.y;
+ if (!Y.square().equals(curve.getB().multiply(Z)))
{
- this.multiplier = new WNafMultiplier();
+ throw new IllegalStateException();
}
+
+ return;
+ }
+
+ ECFieldElement L = this.y;
+ ECFieldElement XSq = X.square();
+ ECFieldElement ZSq = Z.square();
+
+ ECFieldElement lhs = L.square().add(L.multiply(Z)).add(this.getCurve().getA().multiply(ZSq)).multiply(XSq);
+ ECFieldElement rhs = ZSq.square().multiply(this.getCurve().getB()).add(XSq.square());
+
+ if (!lhs.equals(rhs))
+ {
+ throw new IllegalStateException("F2m Lambda-Projective invariant broken");
+ }
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECFieldElement X = this.x;
+ if (X.isZero())
+ {
+ return this;
+ }
+
+ switch (this.getCurveCoordinateSystem())
+ {
+ case ECCurve.COORD_AFFINE:
+ {
+ ECFieldElement Y = this.y;
+ return new ECPoint.F2m(curve, X, Y.add(X), this.withCompression);
+ }
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Y = this.y, Z = this.zs[0];
+ return new ECPoint.F2m(curve, X, Y.add(X), new ECFieldElement[]{ Z }, this.withCompression);
+ }
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ {
+ ECFieldElement L = this.y;
+ return new ECPoint.F2m(curve, X, L.addOne(), this.withCompression);
+ }
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.y, Z = this.zs[0];
+ return new ECPoint.F2m(curve, X, L.add(Z), new ECFieldElement[]{ Z }, this.withCompression);
+ }
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/FpNafMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/FpNafMultiplier.java
deleted file mode 100644
index 35e601d..0000000
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/FpNafMultiplier.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm.
- */
-class FpNafMultiplier implements ECMultiplier
-{
- /**
- * D.3.2 pg 101
- * @see org.bouncycastle.math.ec.ECMultiplier#multiply(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger)
- */
- public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
- {
- // TODO Probably should try to add this
- // BigInteger e = k.mod(n); // n == order of p
- BigInteger e = k;
- BigInteger h = e.multiply(BigInteger.valueOf(3));
-
- ECPoint neg = p.negate();
- ECPoint R = p;
-
- for (int i = h.bitLength() - 2; i > 0; --i)
- {
- R = R.twice();
-
- boolean hBit = h.testBit(i);
- boolean eBit = e.testBit(i);
-
- if (hBit != eBit)
- {
- R = R.add(hBit ? p : neg);
- }
- }
-
- return R;
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java b/bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java
index ead38c4..34395a5 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java
@@ -6,6 +6,60 @@ import java.math.BigInteger;
class IntArray
{
+// private static int DEINTERLEAVE_MASK = 0x55555555;
+
+ /*
+ * This expands 8 bit indices into 16 bit contents, by inserting 0s between bits.
+ * In a binary field, this operation is the same as squaring an 8 bit number.
+ */
+ private static final int[] INTERLEAVE_TABLE = new int[] { 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014,
+ 0x0015, 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, 0x0100, 0x0101, 0x0104, 0x0105, 0x0110,
+ 0x0111, 0x0114, 0x0115, 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, 0x0400, 0x0401, 0x0404,
+ 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, 0x0500,
+ 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554,
+ 0x0555, 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, 0x1040, 0x1041, 0x1044, 0x1045, 0x1050,
+ 0x1051, 0x1054, 0x1055, 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, 0x1140, 0x1141, 0x1144,
+ 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, 0x1440,
+ 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514,
+ 0x1515, 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, 0x4000, 0x4001, 0x4004, 0x4005, 0x4010,
+ 0x4011, 0x4014, 0x4015, 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, 0x4100, 0x4101, 0x4104,
+ 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, 0x4400,
+ 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454,
+ 0x4455, 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, 0x4540, 0x4541, 0x4544, 0x4545, 0x4550,
+ 0x4551, 0x4554, 0x4555, 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, 0x5040, 0x5041, 0x5044,
+ 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, 0x5140,
+ 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414,
+ 0x5415, 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, 0x5500, 0x5501, 0x5504, 0x5505, 0x5510,
+ 0x5511, 0x5514, 0x5515, 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 };
+
+ // For toString(); must have length 32
+ private static final String ZEROES = "00000000000000000000000000000000";
+
+ private final static byte[] bitLengths =
+ {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
+ };
+
+ public static int getWordLength(int bits)
+ {
+ return (bits + 31) >>> 5;
+ }
+
// TODO make m fixed for the IntArray, and hence compute T once and for all
private int[] m_ints;
@@ -22,16 +76,12 @@ class IntArray
public IntArray(BigInteger bigInt)
{
- this(bigInt, 0);
- }
-
- public IntArray(BigInteger bigInt, int minIntLen)
- {
- if (bigInt.signum() == -1)
+ if (bigInt == null || bigInt.signum() < 0)
{
- throw new IllegalArgumentException("Only positive Integers allowed");
+ throw new IllegalArgumentException("invalid F2m field value");
}
- if (bigInt.equals(ECConstants.ZERO))
+
+ if (bigInt.signum() == 0)
{
m_ints = new int[] { 0 };
return;
@@ -48,14 +98,7 @@ class IntArray
barrStart = 1;
}
int intLen = (barrLen + 3) / 4;
- if (intLen < minIntLen)
- {
- m_ints = new int[minIntLen];
- }
- else
- {
- m_ints = new int[intLen];
- }
+ m_ints = new int[intLen];
int iarrJ = intLen - 1;
int rem = barrLen % 4 + barrStart;
@@ -66,11 +109,7 @@ class IntArray
for (; barrI < rem; barrI++)
{
temp <<= 8;
- int barrBarrI = barr[barrI];
- if (barrBarrI < 0)
- {
- barrBarrI += 256;
- }
+ int barrBarrI = barr[barrI] & 0xFF;
temp |= barrBarrI;
}
m_ints[iarrJ--] = temp;
@@ -82,11 +121,7 @@ class IntArray
for (int i = 0; i < 4; i++)
{
temp <<= 8;
- int barrBarrI = barr[barrI++];
- if (barrBarrI < 0)
- {
- barrBarrI += 256;
- }
+ int barrBarrI = barr[barrI++] & 0xFF;
temp |= barrBarrI;
}
m_ints[iarrJ] = temp;
@@ -95,88 +130,86 @@ class IntArray
public boolean isZero()
{
- return m_ints.length == 0
- || (m_ints[0] == 0 && getUsedLength() == 0);
+ int[] a = m_ints;
+ for (int i = 0; i < a.length; ++i)
+ {
+ if (a[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
}
public int getUsedLength()
{
- int highestIntPos = m_ints.length;
+ return getUsedLengthFrom(m_ints.length);
+ }
- if (highestIntPos < 1)
+ public int getUsedLengthFrom(int from)
+ {
+ int[] a = m_ints;
+ from = Math.min(from, a.length);
+
+ if (from < 1)
{
return 0;
}
// Check if first element will act as sentinel
- if (m_ints[0] != 0)
+ if (a[0] != 0)
{
- while (m_ints[--highestIntPos] == 0)
+ while (a[--from] == 0)
{
}
- return highestIntPos + 1;
+ return from + 1;
}
do
{
- if (m_ints[--highestIntPos] != 0)
+ if (a[--from] != 0)
{
- return highestIntPos + 1;
+ return from + 1;
}
}
- while (highestIntPos > 0);
+ while (from > 0);
return 0;
}
- public int bitLength()
+ public int degree()
{
- // JDK 1.5: see Integer.numberOfLeadingZeros()
- int intLen = getUsedLength();
- if (intLen == 0)
- {
- return 0;
- }
-
- int last = intLen - 1;
- int highest = m_ints[last];
- int bits = (last << 5) + 1;
-
- // A couple of binary search steps
- if ((highest & 0xffff0000) != 0)
+ int i = m_ints.length, w;
+ do
{
- if ((highest & 0xff000000) != 0)
- {
- bits += 24;
- highest >>>= 24;
- }
- else
+ if (i == 0)
{
- bits += 16;
- highest >>>= 16;
+ return 0;
}
+ w = m_ints[--i];
}
- else if (highest > 0x000000ff)
- {
- bits += 8;
- highest >>>= 8;
- }
+ while (w == 0);
- while (highest != 1)
+ return (i << 5) + bitLength(w);
+ }
+
+ private static int bitLength(int w)
+ {
+ int t = w >>> 16;
+ if (t == 0)
{
- ++bits;
- highest >>>= 1;
+ t = w >>> 8;
+ return (t == 0) ? bitLengths[w] : 8 + bitLengths[t];
}
- return bits;
+ int u = t >>> 8;
+ return (u == 0) ? 16 + bitLengths[t] : 24 + bitLengths[u];
}
private int[] resizedInts(int newLen)
{
int[] newInts = new int[newLen];
- int oldLen = m_ints.length;
- int copyLen = oldLen < newLen ? oldLen : newLen;
- System.arraycopy(m_ints, 0, newInts, 0, copyLen);
+ System.arraycopy(m_ints, 0, newInts, 0, Math.min(m_ints.length, newLen));
return newInts;
}
@@ -220,86 +253,128 @@ class IntArray
return new BigInteger(1, barr);
}
- public void shiftLeft()
+ private static int shiftLeft(int[] x, int count)
{
- int usedLen = getUsedLength();
- if (usedLen == 0)
+ int prev = 0;
+ for (int i = 0; i < count; ++i)
+ {
+ int next = x[i];
+ x[i] = (next << 1) | prev;
+ prev = next >>> 31;
+ }
+ return prev;
+ }
+
+ public void addOneShifted(int shift)
+ {
+ if (shift >= m_ints.length)
+ {
+ m_ints = resizedInts(shift + 1);
+ }
+
+ m_ints[shift] ^= 1;
+ }
+
+ private void addShiftedByBits(IntArray other, int bits)
+ {
+ int words = bits >>> 5;
+ int shift = bits & 0x1F;
+
+ if (shift == 0)
+ {
+ addShiftedByWords(other, words);
+ return;
+ }
+
+ int otherUsedLen = other.getUsedLength();
+ if (otherUsedLen == 0)
{
return;
}
- if (m_ints[usedLen - 1] < 0)
+
+ int minLen = otherUsedLen + words + 1;
+ if (minLen > m_ints.length)
{
- // highest bit of highest used byte is set, so shifting left will
- // make the IntArray one byte longer
- usedLen++;
- if (usedLen > m_ints.length)
- {
- // make the m_ints one byte longer, because we need one more
- // byte which is not available in m_ints
- m_ints = resizedInts(m_ints.length + 1);
- }
+ m_ints = resizedInts(minLen);
}
- boolean carry = false;
- for (int i = 0; i < usedLen; i++)
+ int shiftInv = 32 - shift, prev = 0;
+ for (int i = 0; i < otherUsedLen; ++i)
{
- // nextCarry is true if highest bit is set
- boolean nextCarry = m_ints[i] < 0;
- m_ints[i] <<= 1;
- if (carry)
- {
- // set lowest bit
- m_ints[i] |= 1;
- }
- carry = nextCarry;
+ int next = other.m_ints[i];
+ m_ints[i + words] ^= (next << shift) | prev;
+ prev = next >>> shiftInv;
}
+ m_ints[otherUsedLen + words] ^= prev;
}
- public IntArray shiftLeft(int n)
+ private static int addShiftedByBits(int[] x, int[] y, int count, int shift)
{
- int usedLen = getUsedLength();
- if (usedLen == 0)
+ int shiftInv = 32 - shift, prev = 0;
+ for (int i = 0; i < count; ++i)
{
- return this;
+ int next = y[i];
+ x[i] ^= (next << shift) | prev;
+ prev = next >>> shiftInv;
}
+ return prev;
+ }
- if (n == 0)
+ private static int addShiftedByBits(int[] x, int xOff, int[] y, int yOff, int count, int shift)
+ {
+ int shiftInv = 32 - shift, prev = 0;
+ for (int i = 0; i < count; ++i)
{
- return this;
+ int next = y[yOff + i];
+ x[xOff + i] ^= (next << shift) | prev;
+ prev = next >>> shiftInv;
}
+ return prev;
+ }
- if (n > 31)
+ public void addShiftedByWords(IntArray other, int words)
+ {
+ int otherUsedLen = other.getUsedLength();
+ if (otherUsedLen == 0)
{
- throw new IllegalArgumentException("shiftLeft() for max 31 bits "
- + ", " + n + "bit shift is not possible");
+ return;
}
- int[] newInts = new int[usedLen + 1];
+ int minLen = otherUsedLen + words;
+ if (minLen > m_ints.length)
+ {
+ m_ints = resizedInts(minLen);
+ }
- int nm32 = 32 - n;
- newInts[0] = m_ints[0] << n;
- for (int i = 1; i < usedLen; i++)
+ for (int i = 0; i < otherUsedLen; i++)
{
- newInts[i] = (m_ints[i] << n) | (m_ints[i - 1] >>> nm32);
+ m_ints[words + i] ^= other.m_ints[i];
}
- newInts[usedLen] = m_ints[usedLen - 1] >>> nm32;
+ }
- return new IntArray(newInts);
+ private static void addShiftedByWords(int[] x, int xOff, int[] y, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ x[xOff + i] ^= y[i];
+ }
}
- public void addShifted(IntArray other, int shift)
+ private static void add(int[] x, int[] y, int count)
{
- int usedLenOther = other.getUsedLength();
- int newMinUsedLen = usedLenOther + shift;
- if (newMinUsedLen > m_ints.length)
+ for (int i = 0; i < count; ++i)
{
- m_ints = resizedInts(newMinUsedLen);
- //System.out.println("Resize required");
+ x[i] ^= y[i];
}
+ }
- for (int i = 0; i < usedLenOther; i++)
+ private static void distribute(int[] x, int dst1, int dst2, int src, int count)
+ {
+ for (int i = 0; i < count; ++i)
{
- m_ints[i + shift] ^= other.m_ints[i];
+ int v = x[src + i];
+ x[dst1 + i] ^= v;
+ x[dst2 + i] ^= v;
}
}
@@ -308,10 +383,58 @@ class IntArray
return m_ints.length;
}
+ public void flipWord(int bit, int word)
+ {
+ int len = m_ints.length;
+ int n = bit >>> 5;
+ if (n < len)
+ {
+ int shift = bit & 0x1F;
+ if (shift == 0)
+ {
+ m_ints[n] ^= word;
+ }
+ else
+ {
+ m_ints[n] ^= word << shift;
+ if (++n < len)
+ {
+ m_ints[n] ^= word >>> (32 - shift);
+ }
+ }
+ }
+ }
+
+ public int getWord(int bit)
+ {
+ int len = m_ints.length;
+ int n = bit >>> 5;
+ if (n >= len)
+ {
+ return 0;
+ }
+ int shift = bit & 0x1F;
+ if (shift == 0)
+ {
+ return m_ints[n];
+ }
+ int result = m_ints[n] >>> shift;
+ if (++n < len)
+ {
+ result |= m_ints[n] << (32 - shift);
+ }
+ return result;
+ }
+
+ public boolean testBitZero()
+ {
+ return m_ints.length > 0 && (m_ints[0] & 1) != 0;
+ }
+
public boolean testBit(int n)
{
// theInt = n / 32
- int theInt = n >> 5;
+ int theInt = n >>> 5;
// theBit = n % 32
int theBit = n & 0x1F;
int tester = 1 << theBit;
@@ -321,7 +444,7 @@ class IntArray
public void flipBit(int n)
{
// theInt = n / 32
- int theInt = n >> 5;
+ int theInt = n >>> 5;
// theBit = n % 32
int theBit = n & 0x1F;
int flipper = 1 << theBit;
@@ -331,127 +454,344 @@ class IntArray
public void setBit(int n)
{
// theInt = n / 32
- int theInt = n >> 5;
+ int theInt = n >>> 5;
// theBit = n % 32
int theBit = n & 0x1F;
int setter = 1 << theBit;
m_ints[theInt] |= setter;
}
+ public void clearBit(int n)
+ {
+ // theInt = n / 32
+ int theInt = n >>> 5;
+ // theBit = n % 32
+ int theBit = n & 0x1F;
+ int setter = 1 << theBit;
+ m_ints[theInt] &= ~setter;
+ }
+
public IntArray multiply(IntArray other, int m)
{
- // Lenght of c is 2m bits rounded up to the next int (32 bit)
- int t = (m + 31) >> 5;
- if (m_ints.length < t)
+ int aLen = getUsedLength();
+ if (aLen == 0)
+ {
+ return new IntArray(1);
+ }
+
+ int bLen = other.getUsedLength();
+ if (bLen == 0)
+ {
+ return new IntArray(1);
+ }
+
+ IntArray A = this, B = other;
+ if (aLen > bLen)
+ {
+ A = other; B = this;
+ int tmp = aLen; aLen = bLen; bLen = tmp;
+ }
+
+ if (aLen == 1)
+ {
+ int a = A.m_ints[0];
+ int[] b = B.m_ints;
+ int[] c = new int[aLen + bLen];
+ if ((a & 1) != 0)
+ {
+ add(c, b, bLen);
+ }
+ int k = 1;
+ while ((a >>>= 1) != 0)
+ {
+ if ((a & 1) != 0)
+ {
+ addShiftedByBits(c, b, bLen, k);
+ }
+ ++k;
+ }
+ return new IntArray(c);
+ }
+
+ // TODO It'd be better to be able to tune the width directly (need support for interleaving arbitrary widths)
+ int complexity = aLen <= 8 ? 1 : 2;
+
+ int width = 1 << complexity;
+ int shifts = (32 >>> complexity);
+
+ int bExt = bLen;
+ if ((B.m_ints[bLen - 1] >>> (33 - shifts)) != 0)
{
- m_ints = resizedInts(t);
+ ++bExt;
}
- IntArray b = new IntArray(other.resizedInts(other.getLength() + 1));
- IntArray c = new IntArray((m + m + 31) >> 5);
- // IntArray c = new IntArray(t + t);
- int testBit = 1;
- for (int k = 0; k < 32; k++)
+ int cLen = bExt + aLen;
+
+ int[] c = new int[cLen << width];
+ System.arraycopy(B.m_ints, 0, c, 0, bLen);
+ interleave(A.m_ints, 0, c, bExt, aLen, complexity);
+
+ int[] ci = new int[1 << width];
+ for (int i = 1; i < ci.length; ++i)
+ {
+ ci[i] = ci[i - 1] + cLen;
+ }
+
+ int MASK = (1 << width) - 1;
+
+ int k = 0;
+ for (;;)
{
- for (int j = 0; j < t; j++)
+ for (int aPos = 0; aPos < aLen; ++aPos)
{
- if ((m_ints[j] & testBit) != 0)
+ int index = (c[bExt + aPos] >>> k) & MASK;
+ if (index != 0)
{
- // The kth bit of m_ints[j] is set
- c.addShifted(b, j);
+ addShiftedByWords(c, aPos + ci[index], c, bExt);
}
}
- testBit <<= 1;
- b.shiftLeft();
- }
- return c;
- }
-
- // public IntArray multiplyLeftToRight(IntArray other, int m) {
- // // Lenght of c is 2m bits rounded up to the next int (32 bit)
- // int t = (m + 31) / 32;
- // if (m_ints.length < t) {
- // m_ints = resizedInts(t);
- // }
- //
- // IntArray b = new IntArray(other.resizedInts(other.getLength() + 1));
- // IntArray c = new IntArray((m + m + 31) / 32);
- // // IntArray c = new IntArray(t + t);
- // int testBit = 1 << 31;
- // for (int k = 31; k >= 0; k--) {
- // for (int j = 0; j < t; j++) {
- // if ((m_ints[j] & testBit) != 0) {
- // // The kth bit of m_ints[j] is set
- // c.addShifted(b, j);
- // }
- // }
- // testBit >>>= 1;
- // if (k > 0) {
- // c.shiftLeft();
- // }
- // }
- // return c;
- // }
-
- // TODO note, redPol.length must be 3 for TPB and 5 for PPB
- public void reduce(int m, int[] redPol)
- {
- for (int i = m + m - 2; i >= m; i--)
+
+ if ((k += width) >= 32)
+ {
+ break;
+ }
+
+ shiftLeft(c, bExt);
+ }
+
+ int ciPos = ci.length, pow2 = ciPos >>> 1, offset = 32;
+ while (--ciPos > 1)
+ {
+ if (ciPos == pow2)
+ {
+ offset -= shifts;
+ addShiftedByBits(c, ci[1], c, ci[pow2], cLen, offset);
+ pow2 >>>= 1;
+ }
+ else
+ {
+ distribute(c, ci[pow2], ci[ciPos - pow2], ci[ciPos], cLen);
+ }
+ }
+
+ // TODO reduce in place to avoid extra copying
+ IntArray p = new IntArray(cLen);
+ System.arraycopy(c, ci[1], p.m_ints, 0, cLen);
+ return p;
+ }
+
+// private static void deInterleave(int[] x, int xOff, int[] z, int zOff, int count, int rounds)
+// {
+// for (int i = 0; i < count; ++i)
+// {
+// z[zOff + i] = deInterleave(x[zOff + i], rounds);
+// }
+// }
+//
+// private static int deInterleave(int x, int rounds)
+// {
+// while (--rounds >= 0)
+// {
+// x = deInterleave16(x & DEINTERLEAVE_MASK) | (deInterleave16((x >>> 1) & DEINTERLEAVE_MASK) << 16);
+// }
+// return x;
+// }
+//
+// private static int deInterleave16(int x)
+// {
+// x = (x | (x >>> 1)) & 0x33333333;
+// x = (x | (x >>> 2)) & 0x0F0F0F0F;
+// x = (x | (x >>> 4)) & 0x00FF00FF;
+// x = (x | (x >>> 8)) & 0x0000FFFF;
+// return x;
+// }
+
+ public void reduce(int m, int[] ks)
+ {
+ int len = getUsedLength();
+ int mLen = (m + 31) >>> 5;
+ if (len < mLen)
+ {
+ return;
+ }
+
+ int _2m = m << 1;
+ int pos = Math.min(_2m - 2, (len << 5) - 1);
+
+ int kMax = ks[ks.length - 1];
+ if (kMax < m - 31)
+ {
+ reduceWordWise(pos, m, ks);
+ }
+ else
+ {
+ reduceBitWise(pos, m, ks);
+ }
+
+ // Instead of flipping the high bits in the loop, explicitly clear any partial word above m bits
+ int partial = m & 0x1F;
+ if (partial != 0)
+ {
+ m_ints[mLen - 1] &= (1 << partial) - 1;
+ }
+
+ if (len > mLen)
+ {
+ m_ints = resizedInts(mLen);
+ }
+ }
+
+ private void reduceBitWise(int from, int m, int[] ks)
+ {
+ for (int i = from; i >= m; --i)
{
if (testBit(i))
{
+// clearBit(i);
int bit = i - m;
flipBit(bit);
- flipBit(i);
- int l = redPol.length;
- while (--l >= 0)
+ int j = ks.length;
+ while (--j >= 0)
+ {
+ flipBit(ks[j] + bit);
+ }
+ }
+ }
+ }
+
+ private void reduceWordWise(int from, int m, int[] ks)
+ {
+ int pos = m + ((from - m) & ~0x1F);
+ for (int i = pos; i >= m; i -= 32)
+ {
+ int word = getWord(i);
+ if (word != 0)
+ {
+// flipWord(i);
+ int bit = i - m;
+ flipWord(bit, word);
+ int j = ks.length;
+ while (--j >= 0)
{
- flipBit(redPol[l] + bit);
+ flipWord(ks[j] + bit, word);
}
}
}
- m_ints = resizedInts((m + 31) >> 5);
}
public IntArray square(int m)
{
- // TODO make the table static final
- final int[] table = { 0x0, 0x1, 0x4, 0x5, 0x10, 0x11, 0x14, 0x15, 0x40,
- 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 };
+ int len = getUsedLength();
+ if (len == 0)
+ {
+ return this;
+ }
- int t = (m + 31) >> 5;
- if (m_ints.length < t)
+ int _2len = len << 1;
+ int[] r = new int[_2len];
+
+ int pos = 0;
+ while (pos < _2len)
{
- m_ints = resizedInts(t);
+ int mi = m_ints[pos >>> 1];
+ r[pos++] = interleave16(mi & 0xFFFF);
+ r[pos++] = interleave16(mi >>> 16);
}
- IntArray c = new IntArray(t + t);
+ return new IntArray(r);
+ }
- // TODO twice the same code, put in separate private method
- for (int i = 0; i < t; i++)
+ private static void interleave(int[] x, int xOff, int[] z, int zOff, int count, int rounds)
+ {
+ for (int i = 0; i < count; ++i)
{
- int v0 = 0;
- for (int j = 0; j < 4; j++)
+ z[zOff + i] = interleave(x[xOff + i], rounds);
+ }
+ }
+
+ private static int interleave(int x, int rounds)
+ {
+ while (--rounds >= 0)
+ {
+ x = interleave16(x & 0xFFFF) | (interleave16(x >>> 16) << 1);
+ }
+ return x;
+ }
+
+ private static int interleave16(int n)
+ {
+ return INTERLEAVE_TABLE[n & 0xFF] | INTERLEAVE_TABLE[n >>> 8] << 16;
+ }
+
+ public IntArray modInverse(int m, int[] ks)
+ {
+ // Inversion in F2m using the extended Euclidean algorithm
+ // Input: A nonzero polynomial a(z) of degree at most m-1
+ // Output: a(z)^(-1) mod f(z)
+
+ int uzDegree = degree();
+ if (uzDegree == 1)
+ {
+ return this;
+ }
+
+ // u(z) := a(z)
+ IntArray uz = (IntArray)clone();
+
+ int t = getWordLength(m);
+
+ // v(z) := f(z)
+ IntArray vz = new IntArray(t);
+ vz.setBit(m);
+ vz.setBit(0);
+ vz.setBit(ks[0]);
+ if (ks.length > 1)
+ {
+ vz.setBit(ks[1]);
+ vz.setBit(ks[2]);
+ }
+
+ // g1(z) := 1, g2(z) := 0
+ IntArray g1z = new IntArray(t);
+ g1z.setBit(0);
+ IntArray g2z = new IntArray(t);
+
+ while (uzDegree != 0)
+ {
+ // j := deg(u(z)) - deg(v(z))
+ int j = uzDegree - vz.degree();
+
+ // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j
+ if (j < 0)
{
- v0 = v0 >>> 8;
- int u = (m_ints[i] >>> (j * 4)) & 0xF;
- int w = table[u] << 24;
- v0 |= w;
+ final IntArray uzCopy = uz;
+ uz = vz;
+ vz = uzCopy;
+
+ final IntArray g1zCopy = g1z;
+ g1z = g2z;
+ g2z = g1zCopy;
+
+ j = -j;
}
- c.m_ints[i + i] = v0;
- v0 = 0;
- int upper = m_ints[i] >>> 16;
- for (int j = 0; j < 4; j++)
+ // u(z) := u(z) + z^j * v(z)
+ // Note, that no reduction modulo f(z) is required, because
+ // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z)))
+ // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z))
+ // = deg(u(z))
+ // uz = uz.xor(vz.shiftLeft(j));
+ uz.addShiftedByBits(vz, j);
+ uzDegree = uz.degree();
+
+ // g1(z) := g1(z) + z^j * g2(z)
+// g1z = g1z.xor(g2z.shiftLeft(j));
+ if (uzDegree != 0)
{
- v0 = v0 >>> 8;
- int u = (upper >>> (j * 4)) & 0xF;
- int w = table[u] << 24;
- v0 |= w;
+ g1z.addShiftedByBits(g2z, j);
}
- c.m_ints[i + i + 1] = v0;
}
- return c;
+ return g2z;
}
public boolean equals(Object o)
@@ -482,7 +822,8 @@ class IntArray
int hash = 1;
for (int i = 0; i < usedLen; i++)
{
- hash = hash * 31 + m_ints[i];
+ hash *= 31;
+ hash ^= m_ints[i];
}
return hash;
}
@@ -494,25 +835,26 @@ class IntArray
public String toString()
{
- int usedLen = getUsedLength();
- if (usedLen == 0)
+ int i = getUsedLength();
+ if (i == 0)
{
return "0";
}
- StringBuffer sb = new StringBuffer(Integer
- .toBinaryString(m_ints[usedLen - 1]));
- for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
+ StringBuffer sb = new StringBuffer(Integer.toBinaryString(m_ints[--i]));
+ while (--i >= 0)
{
- String hexString = Integer.toBinaryString(m_ints[iarrJ]);
+ String s = Integer.toBinaryString(m_ints[i]);
- // Add leading zeroes, except for highest significant int
- for (int i = hexString.length(); i < 8; i++)
+ // Add leading zeroes, except for highest significant word
+ int len = s.length();
+ if (len < 32)
{
- hexString = "0" + hexString;
+ sb.append(ZEROES.substring(len));
}
- sb.append(hexString);
+
+ sb.append(s);
}
return sb.toString();
}
-}
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java b/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java
new file mode 100644
index 0000000..7e8b172
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java
@@ -0,0 +1,1995 @@
+package org.bouncycastle.math.ec;
+
+import org.bouncycastle.util.Arrays;
+
+import java.math.BigInteger;
+
+class LongArray
+{
+// private static long DEINTERLEAVE_MASK = 0x5555555555555555L;
+
+ /*
+ * This expands 8 bit indices into 16 bit contents (high bit 14), by inserting 0s between bits.
+ * In a binary field, this operation is the same as squaring an 8 bit number.
+ */
+ private static final int[] INTERLEAVE2_TABLE = new int[]
+ {
+ 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,
+ 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,
+ 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115,
+ 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,
+ 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415,
+ 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455,
+ 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515,
+ 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,
+ 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015,
+ 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055,
+ 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115,
+ 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,
+ 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415,
+ 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455,
+ 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515,
+ 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,
+ 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015,
+ 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055,
+ 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115,
+ 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,
+ 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415,
+ 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455,
+ 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515,
+ 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,
+ 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015,
+ 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055,
+ 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115,
+ 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,
+ 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415,
+ 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455,
+ 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515,
+ 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
+ };
+
+ /*
+ * This expands 7 bit indices into 21 bit contents (high bit 18), by inserting 0s between bits.
+ */
+ private static final int[] INTERLEAVE3_TABLE = new int[]
+ {
+ 0x00000, 0x00001, 0x00008, 0x00009, 0x00040, 0x00041, 0x00048, 0x00049,
+ 0x00200, 0x00201, 0x00208, 0x00209, 0x00240, 0x00241, 0x00248, 0x00249,
+ 0x01000, 0x01001, 0x01008, 0x01009, 0x01040, 0x01041, 0x01048, 0x01049,
+ 0x01200, 0x01201, 0x01208, 0x01209, 0x01240, 0x01241, 0x01248, 0x01249,
+ 0x08000, 0x08001, 0x08008, 0x08009, 0x08040, 0x08041, 0x08048, 0x08049,
+ 0x08200, 0x08201, 0x08208, 0x08209, 0x08240, 0x08241, 0x08248, 0x08249,
+ 0x09000, 0x09001, 0x09008, 0x09009, 0x09040, 0x09041, 0x09048, 0x09049,
+ 0x09200, 0x09201, 0x09208, 0x09209, 0x09240, 0x09241, 0x09248, 0x09249,
+ 0x40000, 0x40001, 0x40008, 0x40009, 0x40040, 0x40041, 0x40048, 0x40049,
+ 0x40200, 0x40201, 0x40208, 0x40209, 0x40240, 0x40241, 0x40248, 0x40249,
+ 0x41000, 0x41001, 0x41008, 0x41009, 0x41040, 0x41041, 0x41048, 0x41049,
+ 0x41200, 0x41201, 0x41208, 0x41209, 0x41240, 0x41241, 0x41248, 0x41249,
+ 0x48000, 0x48001, 0x48008, 0x48009, 0x48040, 0x48041, 0x48048, 0x48049,
+ 0x48200, 0x48201, 0x48208, 0x48209, 0x48240, 0x48241, 0x48248, 0x48249,
+ 0x49000, 0x49001, 0x49008, 0x49009, 0x49040, 0x49041, 0x49048, 0x49049,
+ 0x49200, 0x49201, 0x49208, 0x49209, 0x49240, 0x49241, 0x49248, 0x49249
+ };
+
+ /*
+ * This expands 8 bit indices into 32 bit contents (high bit 28), by inserting 0s between bits.
+ */
+ private static final int[] INTERLEAVE4_TABLE = new int[]
+ {
+ 0x00000000, 0x00000001, 0x00000010, 0x00000011, 0x00000100, 0x00000101, 0x00000110, 0x00000111,
+ 0x00001000, 0x00001001, 0x00001010, 0x00001011, 0x00001100, 0x00001101, 0x00001110, 0x00001111,
+ 0x00010000, 0x00010001, 0x00010010, 0x00010011, 0x00010100, 0x00010101, 0x00010110, 0x00010111,
+ 0x00011000, 0x00011001, 0x00011010, 0x00011011, 0x00011100, 0x00011101, 0x00011110, 0x00011111,
+ 0x00100000, 0x00100001, 0x00100010, 0x00100011, 0x00100100, 0x00100101, 0x00100110, 0x00100111,
+ 0x00101000, 0x00101001, 0x00101010, 0x00101011, 0x00101100, 0x00101101, 0x00101110, 0x00101111,
+ 0x00110000, 0x00110001, 0x00110010, 0x00110011, 0x00110100, 0x00110101, 0x00110110, 0x00110111,
+ 0x00111000, 0x00111001, 0x00111010, 0x00111011, 0x00111100, 0x00111101, 0x00111110, 0x00111111,
+ 0x01000000, 0x01000001, 0x01000010, 0x01000011, 0x01000100, 0x01000101, 0x01000110, 0x01000111,
+ 0x01001000, 0x01001001, 0x01001010, 0x01001011, 0x01001100, 0x01001101, 0x01001110, 0x01001111,
+ 0x01010000, 0x01010001, 0x01010010, 0x01010011, 0x01010100, 0x01010101, 0x01010110, 0x01010111,
+ 0x01011000, 0x01011001, 0x01011010, 0x01011011, 0x01011100, 0x01011101, 0x01011110, 0x01011111,
+ 0x01100000, 0x01100001, 0x01100010, 0x01100011, 0x01100100, 0x01100101, 0x01100110, 0x01100111,
+ 0x01101000, 0x01101001, 0x01101010, 0x01101011, 0x01101100, 0x01101101, 0x01101110, 0x01101111,
+ 0x01110000, 0x01110001, 0x01110010, 0x01110011, 0x01110100, 0x01110101, 0x01110110, 0x01110111,
+ 0x01111000, 0x01111001, 0x01111010, 0x01111011, 0x01111100, 0x01111101, 0x01111110, 0x01111111,
+ 0x10000000, 0x10000001, 0x10000010, 0x10000011, 0x10000100, 0x10000101, 0x10000110, 0x10000111,
+ 0x10001000, 0x10001001, 0x10001010, 0x10001011, 0x10001100, 0x10001101, 0x10001110, 0x10001111,
+ 0x10010000, 0x10010001, 0x10010010, 0x10010011, 0x10010100, 0x10010101, 0x10010110, 0x10010111,
+ 0x10011000, 0x10011001, 0x10011010, 0x10011011, 0x10011100, 0x10011101, 0x10011110, 0x10011111,
+ 0x10100000, 0x10100001, 0x10100010, 0x10100011, 0x10100100, 0x10100101, 0x10100110, 0x10100111,
+ 0x10101000, 0x10101001, 0x10101010, 0x10101011, 0x10101100, 0x10101101, 0x10101110, 0x10101111,
+ 0x10110000, 0x10110001, 0x10110010, 0x10110011, 0x10110100, 0x10110101, 0x10110110, 0x10110111,
+ 0x10111000, 0x10111001, 0x10111010, 0x10111011, 0x10111100, 0x10111101, 0x10111110, 0x10111111,
+ 0x11000000, 0x11000001, 0x11000010, 0x11000011, 0x11000100, 0x11000101, 0x11000110, 0x11000111,
+ 0x11001000, 0x11001001, 0x11001010, 0x11001011, 0x11001100, 0x11001101, 0x11001110, 0x11001111,
+ 0x11010000, 0x11010001, 0x11010010, 0x11010011, 0x11010100, 0x11010101, 0x11010110, 0x11010111,
+ 0x11011000, 0x11011001, 0x11011010, 0x11011011, 0x11011100, 0x11011101, 0x11011110, 0x11011111,
+ 0x11100000, 0x11100001, 0x11100010, 0x11100011, 0x11100100, 0x11100101, 0x11100110, 0x11100111,
+ 0x11101000, 0x11101001, 0x11101010, 0x11101011, 0x11101100, 0x11101101, 0x11101110, 0x11101111,
+ 0x11110000, 0x11110001, 0x11110010, 0x11110011, 0x11110100, 0x11110101, 0x11110110, 0x11110111,
+ 0x11111000, 0x11111001, 0x11111010, 0x11111011, 0x11111100, 0x11111101, 0x11111110, 0x11111111
+ };
+
+ /*
+ * This expands 7 bit indices into 35 bit contents (high bit 30), by inserting 0s between bits.
+ */
+ private static final int[] INTERLEAVE5_TABLE = new int[] {
+ 0x00000000, 0x00000001, 0x00000020, 0x00000021, 0x00000400, 0x00000401, 0x00000420, 0x00000421,
+ 0x00008000, 0x00008001, 0x00008020, 0x00008021, 0x00008400, 0x00008401, 0x00008420, 0x00008421,
+ 0x00100000, 0x00100001, 0x00100020, 0x00100021, 0x00100400, 0x00100401, 0x00100420, 0x00100421,
+ 0x00108000, 0x00108001, 0x00108020, 0x00108021, 0x00108400, 0x00108401, 0x00108420, 0x00108421,
+ 0x02000000, 0x02000001, 0x02000020, 0x02000021, 0x02000400, 0x02000401, 0x02000420, 0x02000421,
+ 0x02008000, 0x02008001, 0x02008020, 0x02008021, 0x02008400, 0x02008401, 0x02008420, 0x02008421,
+ 0x02100000, 0x02100001, 0x02100020, 0x02100021, 0x02100400, 0x02100401, 0x02100420, 0x02100421,
+ 0x02108000, 0x02108001, 0x02108020, 0x02108021, 0x02108400, 0x02108401, 0x02108420, 0x02108421,
+ 0x40000000, 0x40000001, 0x40000020, 0x40000021, 0x40000400, 0x40000401, 0x40000420, 0x40000421,
+ 0x40008000, 0x40008001, 0x40008020, 0x40008021, 0x40008400, 0x40008401, 0x40008420, 0x40008421,
+ 0x40100000, 0x40100001, 0x40100020, 0x40100021, 0x40100400, 0x40100401, 0x40100420, 0x40100421,
+ 0x40108000, 0x40108001, 0x40108020, 0x40108021, 0x40108400, 0x40108401, 0x40108420, 0x40108421,
+ 0x42000000, 0x42000001, 0x42000020, 0x42000021, 0x42000400, 0x42000401, 0x42000420, 0x42000421,
+ 0x42008000, 0x42008001, 0x42008020, 0x42008021, 0x42008400, 0x42008401, 0x42008420, 0x42008421,
+ 0x42100000, 0x42100001, 0x42100020, 0x42100021, 0x42100400, 0x42100401, 0x42100420, 0x42100421,
+ 0x42108000, 0x42108001, 0x42108020, 0x42108021, 0x42108400, 0x42108401, 0x42108420, 0x42108421
+ };
+
+ /*
+ * This expands 9 bit indices into 63 bit (long) contents (high bit 56), by inserting 0s between bits.
+ */
+ private static final long[] INTERLEAVE7_TABLE = new long[]
+ {
+ 0x0000000000000000L, 0x0000000000000001L, 0x0000000000000080L, 0x0000000000000081L,
+ 0x0000000000004000L, 0x0000000000004001L, 0x0000000000004080L, 0x0000000000004081L,
+ 0x0000000000200000L, 0x0000000000200001L, 0x0000000000200080L, 0x0000000000200081L,
+ 0x0000000000204000L, 0x0000000000204001L, 0x0000000000204080L, 0x0000000000204081L,
+ 0x0000000010000000L, 0x0000000010000001L, 0x0000000010000080L, 0x0000000010000081L,
+ 0x0000000010004000L, 0x0000000010004001L, 0x0000000010004080L, 0x0000000010004081L,
+ 0x0000000010200000L, 0x0000000010200001L, 0x0000000010200080L, 0x0000000010200081L,
+ 0x0000000010204000L, 0x0000000010204001L, 0x0000000010204080L, 0x0000000010204081L,
+ 0x0000000800000000L, 0x0000000800000001L, 0x0000000800000080L, 0x0000000800000081L,
+ 0x0000000800004000L, 0x0000000800004001L, 0x0000000800004080L, 0x0000000800004081L,
+ 0x0000000800200000L, 0x0000000800200001L, 0x0000000800200080L, 0x0000000800200081L,
+ 0x0000000800204000L, 0x0000000800204001L, 0x0000000800204080L, 0x0000000800204081L,
+ 0x0000000810000000L, 0x0000000810000001L, 0x0000000810000080L, 0x0000000810000081L,
+ 0x0000000810004000L, 0x0000000810004001L, 0x0000000810004080L, 0x0000000810004081L,
+ 0x0000000810200000L, 0x0000000810200001L, 0x0000000810200080L, 0x0000000810200081L,
+ 0x0000000810204000L, 0x0000000810204001L, 0x0000000810204080L, 0x0000000810204081L,
+ 0x0000040000000000L, 0x0000040000000001L, 0x0000040000000080L, 0x0000040000000081L,
+ 0x0000040000004000L, 0x0000040000004001L, 0x0000040000004080L, 0x0000040000004081L,
+ 0x0000040000200000L, 0x0000040000200001L, 0x0000040000200080L, 0x0000040000200081L,
+ 0x0000040000204000L, 0x0000040000204001L, 0x0000040000204080L, 0x0000040000204081L,
+ 0x0000040010000000L, 0x0000040010000001L, 0x0000040010000080L, 0x0000040010000081L,
+ 0x0000040010004000L, 0x0000040010004001L, 0x0000040010004080L, 0x0000040010004081L,
+ 0x0000040010200000L, 0x0000040010200001L, 0x0000040010200080L, 0x0000040010200081L,
+ 0x0000040010204000L, 0x0000040010204001L, 0x0000040010204080L, 0x0000040010204081L,
+ 0x0000040800000000L, 0x0000040800000001L, 0x0000040800000080L, 0x0000040800000081L,
+ 0x0000040800004000L, 0x0000040800004001L, 0x0000040800004080L, 0x0000040800004081L,
+ 0x0000040800200000L, 0x0000040800200001L, 0x0000040800200080L, 0x0000040800200081L,
+ 0x0000040800204000L, 0x0000040800204001L, 0x0000040800204080L, 0x0000040800204081L,
+ 0x0000040810000000L, 0x0000040810000001L, 0x0000040810000080L, 0x0000040810000081L,
+ 0x0000040810004000L, 0x0000040810004001L, 0x0000040810004080L, 0x0000040810004081L,
+ 0x0000040810200000L, 0x0000040810200001L, 0x0000040810200080L, 0x0000040810200081L,
+ 0x0000040810204000L, 0x0000040810204001L, 0x0000040810204080L, 0x0000040810204081L,
+ 0x0002000000000000L, 0x0002000000000001L, 0x0002000000000080L, 0x0002000000000081L,
+ 0x0002000000004000L, 0x0002000000004001L, 0x0002000000004080L, 0x0002000000004081L,
+ 0x0002000000200000L, 0x0002000000200001L, 0x0002000000200080L, 0x0002000000200081L,
+ 0x0002000000204000L, 0x0002000000204001L, 0x0002000000204080L, 0x0002000000204081L,
+ 0x0002000010000000L, 0x0002000010000001L, 0x0002000010000080L, 0x0002000010000081L,
+ 0x0002000010004000L, 0x0002000010004001L, 0x0002000010004080L, 0x0002000010004081L,
+ 0x0002000010200000L, 0x0002000010200001L, 0x0002000010200080L, 0x0002000010200081L,
+ 0x0002000010204000L, 0x0002000010204001L, 0x0002000010204080L, 0x0002000010204081L,
+ 0x0002000800000000L, 0x0002000800000001L, 0x0002000800000080L, 0x0002000800000081L,
+ 0x0002000800004000L, 0x0002000800004001L, 0x0002000800004080L, 0x0002000800004081L,
+ 0x0002000800200000L, 0x0002000800200001L, 0x0002000800200080L, 0x0002000800200081L,
+ 0x0002000800204000L, 0x0002000800204001L, 0x0002000800204080L, 0x0002000800204081L,
+ 0x0002000810000000L, 0x0002000810000001L, 0x0002000810000080L, 0x0002000810000081L,
+ 0x0002000810004000L, 0x0002000810004001L, 0x0002000810004080L, 0x0002000810004081L,
+ 0x0002000810200000L, 0x0002000810200001L, 0x0002000810200080L, 0x0002000810200081L,
+ 0x0002000810204000L, 0x0002000810204001L, 0x0002000810204080L, 0x0002000810204081L,
+ 0x0002040000000000L, 0x0002040000000001L, 0x0002040000000080L, 0x0002040000000081L,
+ 0x0002040000004000L, 0x0002040000004001L, 0x0002040000004080L, 0x0002040000004081L,
+ 0x0002040000200000L, 0x0002040000200001L, 0x0002040000200080L, 0x0002040000200081L,
+ 0x0002040000204000L, 0x0002040000204001L, 0x0002040000204080L, 0x0002040000204081L,
+ 0x0002040010000000L, 0x0002040010000001L, 0x0002040010000080L, 0x0002040010000081L,
+ 0x0002040010004000L, 0x0002040010004001L, 0x0002040010004080L, 0x0002040010004081L,
+ 0x0002040010200000L, 0x0002040010200001L, 0x0002040010200080L, 0x0002040010200081L,
+ 0x0002040010204000L, 0x0002040010204001L, 0x0002040010204080L, 0x0002040010204081L,
+ 0x0002040800000000L, 0x0002040800000001L, 0x0002040800000080L, 0x0002040800000081L,
+ 0x0002040800004000L, 0x0002040800004001L, 0x0002040800004080L, 0x0002040800004081L,
+ 0x0002040800200000L, 0x0002040800200001L, 0x0002040800200080L, 0x0002040800200081L,
+ 0x0002040800204000L, 0x0002040800204001L, 0x0002040800204080L, 0x0002040800204081L,
+ 0x0002040810000000L, 0x0002040810000001L, 0x0002040810000080L, 0x0002040810000081L,
+ 0x0002040810004000L, 0x0002040810004001L, 0x0002040810004080L, 0x0002040810004081L,
+ 0x0002040810200000L, 0x0002040810200001L, 0x0002040810200080L, 0x0002040810200081L,
+ 0x0002040810204000L, 0x0002040810204001L, 0x0002040810204080L, 0x0002040810204081L,
+ 0x0100000000000000L, 0x0100000000000001L, 0x0100000000000080L, 0x0100000000000081L,
+ 0x0100000000004000L, 0x0100000000004001L, 0x0100000000004080L, 0x0100000000004081L,
+ 0x0100000000200000L, 0x0100000000200001L, 0x0100000000200080L, 0x0100000000200081L,
+ 0x0100000000204000L, 0x0100000000204001L, 0x0100000000204080L, 0x0100000000204081L,
+ 0x0100000010000000L, 0x0100000010000001L, 0x0100000010000080L, 0x0100000010000081L,
+ 0x0100000010004000L, 0x0100000010004001L, 0x0100000010004080L, 0x0100000010004081L,
+ 0x0100000010200000L, 0x0100000010200001L, 0x0100000010200080L, 0x0100000010200081L,
+ 0x0100000010204000L, 0x0100000010204001L, 0x0100000010204080L, 0x0100000010204081L,
+ 0x0100000800000000L, 0x0100000800000001L, 0x0100000800000080L, 0x0100000800000081L,
+ 0x0100000800004000L, 0x0100000800004001L, 0x0100000800004080L, 0x0100000800004081L,
+ 0x0100000800200000L, 0x0100000800200001L, 0x0100000800200080L, 0x0100000800200081L,
+ 0x0100000800204000L, 0x0100000800204001L, 0x0100000800204080L, 0x0100000800204081L,
+ 0x0100000810000000L, 0x0100000810000001L, 0x0100000810000080L, 0x0100000810000081L,
+ 0x0100000810004000L, 0x0100000810004001L, 0x0100000810004080L, 0x0100000810004081L,
+ 0x0100000810200000L, 0x0100000810200001L, 0x0100000810200080L, 0x0100000810200081L,
+ 0x0100000810204000L, 0x0100000810204001L, 0x0100000810204080L, 0x0100000810204081L,
+ 0x0100040000000000L, 0x0100040000000001L, 0x0100040000000080L, 0x0100040000000081L,
+ 0x0100040000004000L, 0x0100040000004001L, 0x0100040000004080L, 0x0100040000004081L,
+ 0x0100040000200000L, 0x0100040000200001L, 0x0100040000200080L, 0x0100040000200081L,
+ 0x0100040000204000L, 0x0100040000204001L, 0x0100040000204080L, 0x0100040000204081L,
+ 0x0100040010000000L, 0x0100040010000001L, 0x0100040010000080L, 0x0100040010000081L,
+ 0x0100040010004000L, 0x0100040010004001L, 0x0100040010004080L, 0x0100040010004081L,
+ 0x0100040010200000L, 0x0100040010200001L, 0x0100040010200080L, 0x0100040010200081L,
+ 0x0100040010204000L, 0x0100040010204001L, 0x0100040010204080L, 0x0100040010204081L,
+ 0x0100040800000000L, 0x0100040800000001L, 0x0100040800000080L, 0x0100040800000081L,
+ 0x0100040800004000L, 0x0100040800004001L, 0x0100040800004080L, 0x0100040800004081L,
+ 0x0100040800200000L, 0x0100040800200001L, 0x0100040800200080L, 0x0100040800200081L,
+ 0x0100040800204000L, 0x0100040800204001L, 0x0100040800204080L, 0x0100040800204081L,
+ 0x0100040810000000L, 0x0100040810000001L, 0x0100040810000080L, 0x0100040810000081L,
+ 0x0100040810004000L, 0x0100040810004001L, 0x0100040810004080L, 0x0100040810004081L,
+ 0x0100040810200000L, 0x0100040810200001L, 0x0100040810200080L, 0x0100040810200081L,
+ 0x0100040810204000L, 0x0100040810204001L, 0x0100040810204080L, 0x0100040810204081L,
+ 0x0102000000000000L, 0x0102000000000001L, 0x0102000000000080L, 0x0102000000000081L,
+ 0x0102000000004000L, 0x0102000000004001L, 0x0102000000004080L, 0x0102000000004081L,
+ 0x0102000000200000L, 0x0102000000200001L, 0x0102000000200080L, 0x0102000000200081L,
+ 0x0102000000204000L, 0x0102000000204001L, 0x0102000000204080L, 0x0102000000204081L,
+ 0x0102000010000000L, 0x0102000010000001L, 0x0102000010000080L, 0x0102000010000081L,
+ 0x0102000010004000L, 0x0102000010004001L, 0x0102000010004080L, 0x0102000010004081L,
+ 0x0102000010200000L, 0x0102000010200001L, 0x0102000010200080L, 0x0102000010200081L,
+ 0x0102000010204000L, 0x0102000010204001L, 0x0102000010204080L, 0x0102000010204081L,
+ 0x0102000800000000L, 0x0102000800000001L, 0x0102000800000080L, 0x0102000800000081L,
+ 0x0102000800004000L, 0x0102000800004001L, 0x0102000800004080L, 0x0102000800004081L,
+ 0x0102000800200000L, 0x0102000800200001L, 0x0102000800200080L, 0x0102000800200081L,
+ 0x0102000800204000L, 0x0102000800204001L, 0x0102000800204080L, 0x0102000800204081L,
+ 0x0102000810000000L, 0x0102000810000001L, 0x0102000810000080L, 0x0102000810000081L,
+ 0x0102000810004000L, 0x0102000810004001L, 0x0102000810004080L, 0x0102000810004081L,
+ 0x0102000810200000L, 0x0102000810200001L, 0x0102000810200080L, 0x0102000810200081L,
+ 0x0102000810204000L, 0x0102000810204001L, 0x0102000810204080L, 0x0102000810204081L,
+ 0x0102040000000000L, 0x0102040000000001L, 0x0102040000000080L, 0x0102040000000081L,
+ 0x0102040000004000L, 0x0102040000004001L, 0x0102040000004080L, 0x0102040000004081L,
+ 0x0102040000200000L, 0x0102040000200001L, 0x0102040000200080L, 0x0102040000200081L,
+ 0x0102040000204000L, 0x0102040000204001L, 0x0102040000204080L, 0x0102040000204081L,
+ 0x0102040010000000L, 0x0102040010000001L, 0x0102040010000080L, 0x0102040010000081L,
+ 0x0102040010004000L, 0x0102040010004001L, 0x0102040010004080L, 0x0102040010004081L,
+ 0x0102040010200000L, 0x0102040010200001L, 0x0102040010200080L, 0x0102040010200081L,
+ 0x0102040010204000L, 0x0102040010204001L, 0x0102040010204080L, 0x0102040010204081L,
+ 0x0102040800000000L, 0x0102040800000001L, 0x0102040800000080L, 0x0102040800000081L,
+ 0x0102040800004000L, 0x0102040800004001L, 0x0102040800004080L, 0x0102040800004081L,
+ 0x0102040800200000L, 0x0102040800200001L, 0x0102040800200080L, 0x0102040800200081L,
+ 0x0102040800204000L, 0x0102040800204001L, 0x0102040800204080L, 0x0102040800204081L,
+ 0x0102040810000000L, 0x0102040810000001L, 0x0102040810000080L, 0x0102040810000081L,
+ 0x0102040810004000L, 0x0102040810004001L, 0x0102040810004080L, 0x0102040810004081L,
+ 0x0102040810200000L, 0x0102040810200001L, 0x0102040810200080L, 0x0102040810200081L,
+ 0x0102040810204000L, 0x0102040810204001L, 0x0102040810204080L, 0x0102040810204081L
+ };
+
+ // For toString(); must have length 64
+ private static final String ZEROES = "0000000000000000000000000000000000000000000000000000000000000000";
+
+ final static byte[] bitLengths =
+ {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
+ };
+
+ // TODO make m fixed for the LongArray, and hence compute T once and for all
+
+ private long[] m_ints;
+
+ public LongArray(int intLen)
+ {
+ m_ints = new long[intLen];
+ }
+
+ public LongArray(long[] ints)
+ {
+ m_ints = ints;
+ }
+
+ public LongArray(long[] ints, int off, int len)
+ {
+ if (off == 0 && len == ints.length)
+ {
+ m_ints = ints;
+ }
+ else
+ {
+ m_ints = new long[len];
+ System.arraycopy(ints, off, m_ints, 0, len);
+ }
+ }
+
+ public LongArray(BigInteger bigInt)
+ {
+ if (bigInt == null || bigInt.signum() < 0)
+ {
+ throw new IllegalArgumentException("invalid F2m field value");
+ }
+
+ if (bigInt.signum() == 0)
+ {
+ m_ints = new long[] { 0L };
+ return;
+ }
+
+ byte[] barr = bigInt.toByteArray();
+ int barrLen = barr.length;
+ int barrStart = 0;
+ if (barr[0] == 0)
+ {
+ // First byte is 0 to enforce highest (=sign) bit is zero.
+ // In this case ignore barr[0].
+ barrLen--;
+ barrStart = 1;
+ }
+ int intLen = (barrLen + 7) / 8;
+ m_ints = new long[intLen];
+
+ int iarrJ = intLen - 1;
+ int rem = barrLen % 8 + barrStart;
+ long temp = 0;
+ int barrI = barrStart;
+ if (barrStart < rem)
+ {
+ for (; barrI < rem; barrI++)
+ {
+ temp <<= 8;
+ int barrBarrI = barr[barrI] & 0xFF;
+ temp |= barrBarrI;
+ }
+ m_ints[iarrJ--] = temp;
+ }
+
+ for (; iarrJ >= 0; iarrJ--)
+ {
+ temp = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ temp <<= 8;
+ int barrBarrI = barr[barrI++] & 0xFF;
+ temp |= barrBarrI;
+ }
+ m_ints[iarrJ] = temp;
+ }
+ }
+
+ public boolean isZero()
+ {
+ long[] a = m_ints;
+ for (int i = 0; i < a.length; ++i)
+ {
+ if (a[i] != 0L)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public int getUsedLength()
+ {
+ return getUsedLengthFrom(m_ints.length);
+ }
+
+ public int getUsedLengthFrom(int from)
+ {
+ long[] a = m_ints;
+ from = Math.min(from, a.length);
+
+ if (from < 1)
+ {
+ return 0;
+ }
+
+ // Check if first element will act as sentinel
+ if (a[0] != 0)
+ {
+ while (a[--from] == 0)
+ {
+ }
+ return from + 1;
+ }
+
+ do
+ {
+ if (a[--from] != 0)
+ {
+ return from + 1;
+ }
+ }
+ while (from > 0);
+
+ return 0;
+ }
+
+ public int degree()
+ {
+ int i = m_ints.length;
+ long w;
+ do
+ {
+ if (i == 0)
+ {
+ return 0;
+ }
+ w = m_ints[--i];
+ }
+ while (w == 0);
+
+ return (i << 6) + bitLength(w);
+ }
+
+ private int degreeFrom(int limit)
+ {
+ int i = (limit + 62) >>> 6;
+ long w;
+ do
+ {
+ if (i == 0)
+ {
+ return 0;
+ }
+ w = m_ints[--i];
+ }
+ while (w == 0);
+
+ return (i << 6) + bitLength(w);
+ }
+
+// private int lowestCoefficient()
+// {
+// for (int i = 0; i < m_ints.length; ++i)
+// {
+// long mi = m_ints[i];
+// if (mi != 0)
+// {
+// int j = 0;
+// while ((mi & 0xFFL) == 0)
+// {
+// j += 8;
+// mi >>>= 8;
+// }
+// while ((mi & 1L) == 0)
+// {
+// ++j;
+// mi >>>= 1;
+// }
+// return (i << 6) + j;
+// }
+// }
+// return -1;
+// }
+
+ private static int bitLength(long w)
+ {
+ int u = (int)(w >>> 32), b;
+ if (u == 0)
+ {
+ u = (int)w;
+ b = 0;
+ }
+ else
+ {
+ b = 32;
+ }
+
+ int t = u >>> 16, k;
+ if (t == 0)
+ {
+ t = u >>> 8;
+ k = (t == 0) ? bitLengths[u] : 8 + bitLengths[t];
+ }
+ else
+ {
+ int v = t >>> 8;
+ k = (v == 0) ? 16 + bitLengths[t] : 24 + bitLengths[v];
+ }
+
+ return b + k;
+ }
+
+ private long[] resizedInts(int newLen)
+ {
+ long[] newInts = new long[newLen];
+ System.arraycopy(m_ints, 0, newInts, 0, Math.min(m_ints.length, newLen));
+ return newInts;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ int usedLen = getUsedLength();
+ if (usedLen == 0)
+ {
+ return ECConstants.ZERO;
+ }
+
+ long highestInt = m_ints[usedLen - 1];
+ byte[] temp = new byte[8];
+ int barrI = 0;
+ boolean trailingZeroBytesDone = false;
+ for (int j = 7; j >= 0; j--)
+ {
+ byte thisByte = (byte)(highestInt >>> (8 * j));
+ if (trailingZeroBytesDone || (thisByte != 0))
+ {
+ trailingZeroBytesDone = true;
+ temp[barrI++] = thisByte;
+ }
+ }
+
+ int barrLen = 8 * (usedLen - 1) + barrI;
+ byte[] barr = new byte[barrLen];
+ for (int j = 0; j < barrI; j++)
+ {
+ barr[j] = temp[j];
+ }
+ // Highest value int is done now
+
+ for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
+ {
+ long mi = m_ints[iarrJ];
+ for (int j = 7; j >= 0; j--)
+ {
+ barr[barrI++] = (byte)(mi >>> (8 * j));
+ }
+ }
+ return new BigInteger(1, barr);
+ }
+
+// private static long shiftUp(long[] x, int xOff, int count)
+// {
+// long prev = 0;
+// for (int i = 0; i < count; ++i)
+// {
+// long next = x[xOff + i];
+// x[xOff + i] = (next << 1) | prev;
+// prev = next >>> 63;
+// }
+// return prev;
+// }
+
+ private static long shiftUp(long[] x, int xOff, int count, int shift)
+ {
+ int shiftInv = 64 - shift;
+ long prev = 0;
+ for (int i = 0; i < count; ++i)
+ {
+ long next = x[xOff + i];
+ x[xOff + i] = (next << shift) | prev;
+ prev = next >>> shiftInv;
+ }
+ return prev;
+ }
+
+ private static long shiftUp(long[] x, int xOff, long[] z, int zOff, int count, int shift)
+ {
+ int shiftInv = 64 - shift;
+ long prev = 0;
+ for (int i = 0; i < count; ++i)
+ {
+ long next = x[xOff + i];
+ z[zOff + i] = (next << shift) | prev;
+ prev = next >>> shiftInv;
+ }
+ return prev;
+ }
+
+ public LongArray addOne()
+ {
+ if (m_ints.length == 0)
+ {
+ return new LongArray(new long[]{ 1L });
+ }
+
+ int resultLen = Math.max(1, getUsedLength());
+ long[] ints = resizedInts(resultLen);
+ ints[0] ^= 1L;
+ return new LongArray(ints);
+ }
+
+// private void addShiftedByBits(LongArray other, int bits)
+// {
+// int words = bits >>> 6;
+// int shift = bits & 0x3F;
+//
+// if (shift == 0)
+// {
+// addShiftedByWords(other, words);
+// return;
+// }
+//
+// int otherUsedLen = other.getUsedLength();
+// if (otherUsedLen == 0)
+// {
+// return;
+// }
+//
+// int minLen = otherUsedLen + words + 1;
+// if (minLen > m_ints.length)
+// {
+// m_ints = resizedInts(minLen);
+// }
+//
+// long carry = addShiftedByBits(m_ints, words, other.m_ints, 0, otherUsedLen, shift);
+// m_ints[otherUsedLen + words] ^= carry;
+// }
+
+ private void addShiftedByBitsSafe(LongArray other, int otherDegree, int bits)
+ {
+ int otherLen = (otherDegree + 63) >>> 6;
+
+ int words = bits >>> 6;
+ int shift = bits & 0x3F;
+
+ if (shift == 0)
+ {
+ add(m_ints, words, other.m_ints, 0, otherLen);
+ return;
+ }
+
+ long carry = addShiftedUp(m_ints, words, other.m_ints, 0, otherLen, shift);
+ if (carry != 0L)
+ {
+ m_ints[otherLen + words] ^= carry;
+ }
+ }
+
+ private static long addShiftedUp(long[] x, int xOff, long[] y, int yOff, int count, int shift)
+ {
+ int shiftInv = 64 - shift;
+ long prev = 0;
+ for (int i = 0; i < count; ++i)
+ {
+ long next = y[yOff + i];
+ x[xOff + i] ^= (next << shift) | prev;
+ prev = next >>> shiftInv;
+ }
+ return prev;
+ }
+
+ private static long addShiftedDown(long[] x, int xOff, long[] y, int yOff, int count, int shift)
+ {
+ int shiftInv = 64 - shift;
+ long prev = 0;
+ int i = count;
+ while (--i >= 0)
+ {
+ long next = y[yOff + i];
+ x[xOff + i] ^= (next >>> shift) | prev;
+ prev = next << shiftInv;
+ }
+ return prev;
+ }
+
+ public void addShiftedByWords(LongArray other, int words)
+ {
+ int otherUsedLen = other.getUsedLength();
+ if (otherUsedLen == 0)
+ {
+ return;
+ }
+
+ int minLen = otherUsedLen + words;
+ if (minLen > m_ints.length)
+ {
+ m_ints = resizedInts(minLen);
+ }
+
+ add(m_ints, words, other.m_ints, 0, otherUsedLen);
+ }
+
+ private static void add(long[] x, int xOff, long[] y, int yOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ x[xOff + i] ^= y[yOff + i];
+ }
+ }
+
+ private static void add(long[] x, int xOff, long[] y, int yOff, long[] z, int zOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ z[zOff + i] = x[xOff + i] ^ y[yOff + i];
+ }
+ }
+
+ private static void addBoth(long[] x, int xOff, long[] y1, int y1Off, long[] y2, int y2Off, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ x[xOff + i] ^= y1[y1Off + i] ^ y2[y2Off + i];
+ }
+ }
+
+ private static void distribute(long[] x, int src, int dst1, int dst2, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ long v = x[src + i];
+ x[dst1 + i] ^= v;
+ x[dst2 + i] ^= v;
+ }
+ }
+
+ public int getLength()
+ {
+ return m_ints.length;
+ }
+
+ private static void flipWord(long[] buf, int off, int bit, long word)
+ {
+ int n = off + (bit >>> 6);
+ int shift = bit & 0x3F;
+ if (shift == 0)
+ {
+ buf[n] ^= word;
+ }
+ else
+ {
+ buf[n] ^= word << shift;
+ word >>>= (64 - shift);
+ if (word != 0)
+ {
+ buf[++n] ^= word;
+ }
+ }
+ }
+
+// private static long getWord(long[] buf, int off, int len, int bit)
+// {
+// int n = off + (bit >>> 6);
+// int shift = bit & 0x3F;
+// if (shift == 0)
+// {
+// return buf[n];
+// }
+// long result = buf[n] >>> shift;
+// if (++n < len)
+// {
+// result |= buf[n] << (64 - shift);
+// }
+// return result;
+// }
+
+ public boolean testBitZero()
+ {
+ return m_ints.length > 0 && (m_ints[0] & 1L) != 0;
+ }
+
+ private static boolean testBit(long[] buf, int off, int n)
+ {
+ // theInt = n / 64
+ int theInt = n >>> 6;
+ // theBit = n % 64
+ int theBit = n & 0x3F;
+ long tester = 1L << theBit;
+ return (buf[off + theInt] & tester) != 0;
+ }
+
+ private static void flipBit(long[] buf, int off, int n)
+ {
+ // theInt = n / 64
+ int theInt = n >>> 6;
+ // theBit = n % 64
+ int theBit = n & 0x3F;
+ long flipper = 1L << theBit;
+ buf[off + theInt] ^= flipper;
+ }
+
+// private static void setBit(long[] buf, int off, int n)
+// {
+// // theInt = n / 64
+// int theInt = n >>> 6;
+// // theBit = n % 64
+// int theBit = n & 0x3F;
+// long setter = 1L << theBit;
+// buf[off + theInt] |= setter;
+// }
+//
+// private static void clearBit(long[] buf, int off, int n)
+// {
+// // theInt = n / 64
+// int theInt = n >>> 6;
+// // theBit = n % 64
+// int theBit = n & 0x3F;
+// long setter = 1L << theBit;
+// buf[off + theInt] &= ~setter;
+// }
+
+ private static void multiplyWord(long a, long[] b, int bLen, long[] c, int cOff)
+ {
+ if ((a & 1L) != 0L)
+ {
+ add(c, cOff, b, 0, bLen);
+ }
+ int k = 1;
+ while ((a >>>= 1) != 0)
+ {
+ if ((a & 1L) != 0L)
+ {
+ long carry = addShiftedUp(c, cOff, b, 0, bLen, k);
+ if (carry != 0)
+ {
+ c[cOff + bLen] ^= carry;
+ }
+ }
+ ++k;
+ }
+ }
+
+ public LongArray modMultiplyLD(LongArray other, int m, int[] ks)
+ {
+ /*
+ * Find out the degree of each argument and handle the zero cases
+ */
+ int aDeg = degree();
+ if (aDeg == 0)
+ {
+ return this;
+ }
+ int bDeg = other.degree();
+ if (bDeg == 0)
+ {
+ return other;
+ }
+
+ /*
+ * Swap if necessary so that A is the smaller argument
+ */
+ LongArray A = this, B = other;
+ if (aDeg > bDeg)
+ {
+ A = other; B = this;
+ int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+ }
+
+ /*
+ * Establish the word lengths of the arguments and result
+ */
+ int aLen = (aDeg + 63) >>> 6;
+ int bLen = (bDeg + 63) >>> 6;
+ int cLen = (aDeg + bDeg + 62) >>> 6;
+
+ if (aLen == 1)
+ {
+ long a = A.m_ints[0];
+ if (a == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c = new long[cLen];
+ multiplyWord(a, B.m_ints, bLen, c, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+ return reduceResult(c, 0, cLen, m, ks);
+ }
+
+ /*
+ * Determine if B will get bigger during shifting
+ */
+ int bMax = (bDeg + 7 + 63) >>> 6;
+
+ /*
+ * Lookup table for the offset of each B in the tables
+ */
+ int[] ti = new int[16];
+
+ /*
+ * Precompute table of all 4-bit products of B
+ */
+ long[] T0 = new long[bMax << 4];
+ int tOff = bMax;
+ ti[1] = tOff;
+ System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
+ for (int i = 2; i < 16; ++i)
+ {
+ ti[i] = (tOff += bMax);
+ if ((i & 1) == 0)
+ {
+ shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
+ }
+ else
+ {
+ add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
+ }
+ }
+
+ /*
+ * Second table with all 4-bit products of B shifted 4 bits
+ */
+ long[] T1 = new long[T0.length];
+ shiftUp(T0, 0, T1, 0, T0.length, 4);
+// shiftUp(T0, bMax, T1, bMax, tOff, 4);
+
+ long[] a = A.m_ints;
+ long[] c = new long[cLen];
+
+ int MASK = 0xF;
+
+ /*
+ * Lopez-Dahab algorithm
+ */
+
+ for (int k = 56; k >= 0; k -= 8)
+ {
+ for (int j = 1; j < aLen; j += 2)
+ {
+ int aVal = (int)(a[j] >>> k);
+ int u = aVal & MASK;
+ int v = (aVal >>> 4) & MASK;
+ addBoth(c, j - 1, T0, ti[u], T1, ti[v], bMax);
+ }
+ shiftUp(c, 0, cLen, 8);
+ }
+
+ for (int k = 56; k >= 0; k -= 8)
+ {
+ for (int j = 0; j < aLen; j += 2)
+ {
+ int aVal = (int)(a[j] >>> k);
+ int u = aVal & MASK;
+ int v = (aVal >>> 4) & MASK;
+ addBoth(c, j, T0, ti[u], T1, ti[v], bMax);
+ }
+ if (k > 0)
+ {
+ shiftUp(c, 0, cLen, 8);
+ }
+ }
+
+ /*
+ * Finally the raw answer is collected, reduce it against the reduction coefficients
+ */
+ return reduceResult(c, 0, cLen, m, ks);
+ }
+
+ public LongArray modMultiply(LongArray other, int m, int[] ks)
+ {
+ /*
+ * Find out the degree of each argument and handle the zero cases
+ */
+ int aDeg = degree();
+ if (aDeg == 0)
+ {
+ return this;
+ }
+ int bDeg = other.degree();
+ if (bDeg == 0)
+ {
+ return other;
+ }
+
+ /*
+ * Swap if necessary so that A is the smaller argument
+ */
+ LongArray A = this, B = other;
+ if (aDeg > bDeg)
+ {
+ A = other; B = this;
+ int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+ }
+
+ /*
+ * Establish the word lengths of the arguments and result
+ */
+ int aLen = (aDeg + 63) >>> 6;
+ int bLen = (bDeg + 63) >>> 6;
+ int cLen = (aDeg + bDeg + 62) >>> 6;
+
+ if (aLen == 1)
+ {
+ long a = A.m_ints[0];
+ if (a == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c = new long[cLen];
+ multiplyWord(a, B.m_ints, bLen, c, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+ return reduceResult(c, 0, cLen, m, ks);
+ }
+
+ /*
+ * Determine if B will get bigger during shifting
+ */
+ int bMax = (bDeg + 7 + 63) >>> 6;
+
+ /*
+ * Lookup table for the offset of each B in the tables
+ */
+ int[] ti = new int[16];
+
+ /*
+ * Precompute table of all 4-bit products of B
+ */
+ long[] T0 = new long[bMax << 4];
+ int tOff = bMax;
+ ti[1] = tOff;
+ System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
+ for (int i = 2; i < 16; ++i)
+ {
+ ti[i] = (tOff += bMax);
+ if ((i & 1) == 0)
+ {
+ shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
+ }
+ else
+ {
+ add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
+ }
+ }
+
+ /*
+ * Second table with all 4-bit products of B shifted 4 bits
+ */
+ long[] T1 = new long[T0.length];
+ shiftUp(T0, 0, T1, 0, T0.length, 4);
+// shiftUp(T0, bMax, T1, bMax, tOff, 4);
+
+ long[] a = A.m_ints;
+ long[] c = new long[cLen << 3];
+
+ int MASK = 0xF;
+
+ /*
+ * Lopez-Dahab (Modified) algorithm
+ */
+
+ for (int aPos = 0; aPos < aLen; ++aPos)
+ {
+ long aVal = a[aPos];
+ int cOff = aPos;
+ for (;;)
+ {
+ int u = (int)aVal & MASK;
+ aVal >>>= 4;
+ int v = (int)aVal & MASK;
+ addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
+ if ((aVal >>>= 4) == 0L)
+ {
+ break;
+ }
+ cOff += cLen;
+ }
+ }
+
+ int cOff = c.length;
+ while ((cOff -= cLen) != 0)
+ {
+ addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+ }
+
+ /*
+ * Finally the raw answer is collected, reduce it against the reduction coefficients
+ */
+ return reduceResult(c, 0, cLen, m, ks);
+ }
+
+ public LongArray modMultiplyAlt(LongArray other, int m, int[] ks)
+ {
+ /*
+ * Find out the degree of each argument and handle the zero cases
+ */
+ int aDeg = degree();
+ if (aDeg == 0)
+ {
+ return this;
+ }
+ int bDeg = other.degree();
+ if (bDeg == 0)
+ {
+ return other;
+ }
+
+ /*
+ * Swap if necessary so that A is the smaller argument
+ */
+ LongArray A = this, B = other;
+ if (aDeg > bDeg)
+ {
+ A = other; B = this;
+ int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+ }
+
+ /*
+ * Establish the word lengths of the arguments and result
+ */
+ int aLen = (aDeg + 63) >>> 6;
+ int bLen = (bDeg + 63) >>> 6;
+ int cLen = (aDeg + bDeg + 62) >>> 6;
+
+ if (aLen == 1)
+ {
+ long a = A.m_ints[0];
+ if (a == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c = new long[cLen];
+ multiplyWord(a, B.m_ints, bLen, c, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+ return reduceResult(c, 0, cLen, m, ks);
+ }
+
+ // NOTE: This works, but is slower than width 4 processing
+// if (aLen == 2)
+// {
+// /*
+// * Use common-multiplicand optimization to save ~1/4 of the adds
+// */
+// long a1 = A.m_ints[0], a2 = A.m_ints[1];
+// long aa = a1 & a2; a1 ^= aa; a2 ^= aa;
+//
+// long[] b = B.m_ints;
+// long[] c = new long[cLen];
+// multiplyWord(aa, b, bLen, c, 1);
+// add(c, 0, c, 1, cLen - 1);
+// multiplyWord(a1, b, bLen, c, 0);
+// multiplyWord(a2, b, bLen, c, 1);
+//
+// /*
+// * Reduce the raw answer against the reduction coefficients
+// */
+// return reduceResult(c, 0, cLen, m, ks);
+// }
+
+ /*
+ * Determine the parameters of the interleaved window algorithm: the 'width' in bits to
+ * process together, the number of evaluation 'positions' implied by that width, and the
+ * 'top' position at which the regular window algorithm stops.
+ */
+ int width, positions, top, banks;
+
+ // NOTE: width 4 is the fastest over the entire range of sizes used in current crypto
+// width = 1; positions = 64; top = 64; banks = 4;
+// width = 2; positions = 32; top = 64; banks = 4;
+// width = 3; positions = 21; top = 63; banks = 3;
+ width = 4; positions = 16; top = 64; banks = 8;
+// width = 5; positions = 13; top = 65; banks = 7;
+// width = 7; positions = 9; top = 63; banks = 9;
+// width = 8; positions = 8; top = 64; banks = 8;
+
+ /*
+ * Determine if B will get bigger during shifting
+ */
+ int shifts = top < 64 ? positions : positions - 1;
+ int bMax = (bDeg + shifts + 63) >>> 6;
+
+ int bTotal = bMax * banks, stride = width * banks;
+
+ /*
+ * Create a single temporary buffer, with an offset table to find the positions of things in it
+ */
+ int[] ci = new int[1 << width];
+ int cTotal = aLen;
+ {
+ ci[0] = cTotal;
+ cTotal += bTotal;
+ ci[1] = cTotal;
+ for (int i = 2; i < ci.length; ++i)
+ {
+ cTotal += cLen;
+ ci[i] = cTotal;
+ }
+ cTotal += cLen;
+ }
+ // NOTE: Provide a safe dump for "high zeroes" since we are adding 'bMax' and not 'bLen'
+ ++cTotal;
+
+ long[] c = new long[cTotal];
+
+ // Prepare A in interleaved form, according to the chosen width
+ interleave(A.m_ints, 0, c, 0, aLen, width);
+
+ // Make a working copy of B, since we will be shifting it
+ {
+ int bOff = aLen;
+ System.arraycopy(B.m_ints, 0, c, bOff, bLen);
+ for (int bank = 1; bank < banks; ++bank)
+ {
+ shiftUp(c, aLen, c, bOff += bMax, bMax, bank);
+ }
+ }
+
+ /*
+ * The main loop analyzes the interleaved windows in A, and for each non-zero window
+ * a single word-array XOR is performed to a carefully selected slice of 'c'. The loop is
+ * breadth-first, checking the lowest window in each word, then looping again for the
+ * next higher window position.
+ */
+ int MASK = (1 << width) - 1;
+
+ int k = 0;
+ for (;;)
+ {
+ int aPos = 0;
+ do
+ {
+ long aVal = c[aPos] >>> k;
+ int bank = 0, bOff = aLen;
+ for (;;)
+ {
+ int index = (int)(aVal) & MASK;
+ if (index != 0)
+ {
+ /*
+ * Add to a 'c' buffer based on the bit-pattern of 'index'. Since A is in
+ * interleaved form, the bits represent the current B shifted by 0, 'positions',
+ * 'positions' * 2, ..., 'positions' * ('width' - 1)
+ */
+ add(c, aPos + ci[index], c, bOff, bMax);
+ }
+ if (++bank == banks)
+ {
+ break;
+ }
+ bOff += bMax;
+ aVal >>>= width;
+ }
+ }
+ while (++aPos < aLen);
+
+ if ((k += stride) >= top)
+ {
+ if (k >= 64)
+ {
+ break;
+ }
+
+ /*
+ * Adjustment for window setups with top == 63, the final bit (if any) is processed
+ * as the top-bit of a window
+ */
+ k = 64 - width;
+ MASK &= MASK << (top - k);
+ }
+
+ /*
+ * After each position has been checked for all words of A, B is shifted up 1 place
+ */
+ shiftUp(c, aLen, bTotal, banks);
+ }
+
+ int ciPos = ci.length;
+ while (--ciPos > 1)
+ {
+ if ((ciPos & 1L) == 0L)
+ {
+ /*
+ * For even numbers, shift contents and add to the half-position
+ */
+ addShiftedUp(c, ci[ciPos >>> 1], c, ci[ciPos], cLen, positions);
+ }
+ else
+ {
+ /*
+ * For odd numbers, 'distribute' contents to the result and the next-lowest position
+ */
+ distribute(c, ci[ciPos], ci[ciPos - 1], ci[1], cLen);
+ }
+ }
+
+ /*
+ * Finally the raw answer is collected, reduce it against the reduction coefficients
+ */
+ return reduceResult(c, ci[1], cLen, m, ks);
+ }
+
+ private static LongArray reduceResult(long[] buf, int off, int len, int m, int[] ks)
+ {
+ int rLen = reduceInPlace(buf, off, len, m, ks);
+ return new LongArray(buf, off, rLen);
+ }
+
+// private static void deInterleave(long[] x, int xOff, long[] z, int zOff, int count, int rounds)
+// {
+// for (int i = 0; i < count; ++i)
+// {
+// z[zOff + i] = deInterleave(x[zOff + i], rounds);
+// }
+// }
+//
+// private static long deInterleave(long x, int rounds)
+// {
+// while (--rounds >= 0)
+// {
+// x = deInterleave32(x & DEINTERLEAVE_MASK) | (deInterleave32((x >>> 1) & DEINTERLEAVE_MASK) << 32);
+// }
+// return x;
+// }
+//
+// private static long deInterleave32(long x)
+// {
+// x = (x | (x >>> 1)) & 0x3333333333333333L;
+// x = (x | (x >>> 2)) & 0x0F0F0F0F0F0F0F0FL;
+// x = (x | (x >>> 4)) & 0x00FF00FF00FF00FFL;
+// x = (x | (x >>> 8)) & 0x0000FFFF0000FFFFL;
+// x = (x | (x >>> 16)) & 0x00000000FFFFFFFFL;
+// return x;
+// }
+
+ private static int reduceInPlace(long[] buf, int off, int len, int m, int[] ks)
+ {
+ int mLen = (m + 63) >>> 6;
+ if (len < mLen)
+ {
+ return len;
+ }
+
+ int numBits = Math.min(len << 6, (m << 1) - 1); // TODO use actual degree?
+ int excessBits = (len << 6) - numBits;
+ while (excessBits >= 64)
+ {
+ --len;
+ excessBits -= 64;
+ }
+
+ int kLen = ks.length, kMax = ks[kLen - 1], kNext = kLen > 1 ? ks[kLen - 2] : 0;
+ int wordWiseLimit = Math.max(m, kMax + 64);
+ int vectorableWords = (excessBits + Math.min(numBits - wordWiseLimit, m - kNext)) >> 6;
+ if (vectorableWords > 1)
+ {
+ int vectorWiseWords = len - vectorableWords;
+ reduceVectorWise(buf, off, len, vectorWiseWords, m, ks);
+ while (len > vectorWiseWords)
+ {
+ buf[off + --len] = 0L;
+ }
+ numBits = vectorWiseWords << 6;
+ }
+
+ if (numBits > wordWiseLimit)
+ {
+ reduceWordWise(buf, off, len, wordWiseLimit, m, ks);
+ numBits = wordWiseLimit;
+ }
+
+ if (numBits > m)
+ {
+ reduceBitWise(buf, off, numBits, m, ks);
+ }
+
+ return mLen;
+ }
+
+ private static void reduceBitWise(long[] buf, int off, int bitlength, int m, int[] ks)
+ {
+ while (--bitlength >= m)
+ {
+ if (testBit(buf, off, bitlength))
+ {
+ reduceBit(buf, off, bitlength, m, ks);
+ }
+ }
+ }
+
+ private static void reduceBit(long[] buf, int off, int bit, int m, int[] ks)
+ {
+ flipBit(buf, off, bit);
+ int base = bit - m;
+ int j = ks.length;
+ while (--j >= 0)
+ {
+ flipBit(buf, off, ks[j] + base);
+ }
+ flipBit(buf, off, base);
+ }
+
+ private static void reduceWordWise(long[] buf, int off, int len, int toBit, int m, int[] ks)
+ {
+ int toPos = toBit >>> 6;
+
+ while (--len > toPos)
+ {
+ long word = buf[off + len];
+ if (word != 0)
+ {
+ buf[off + len] = 0;
+ reduceWord(buf, off, (len << 6), word, m, ks);
+ }
+ }
+
+ int partial = toBit & 0x3F;
+ long word = buf[off + toPos] >>> partial;
+ if (word != 0)
+ {
+ buf[off + toPos] ^= word << partial;
+ reduceWord(buf, off, toBit, word, m, ks);
+ }
+ }
+
+ private static void reduceWord(long[] buf, int off, int bit, long word, int m, int[] ks)
+ {
+ int offset = bit - m;
+ int j = ks.length;
+ while (--j >= 0)
+ {
+ flipWord(buf, off, offset + ks[j], word);
+ }
+ flipWord(buf, off, offset, word);
+ }
+
+ private static void reduceVectorWise(long[] buf, int off, int len, int words, int m, int[] ks)
+ {
+ /*
+ * NOTE: It's important we go from highest coefficient to lowest, because for the highest
+ * one (only) we allow the ranges to partially overlap, and therefore any changes must take
+ * effect for the subsequent lower coefficients.
+ */
+ int baseBit = (words << 6) - m;
+ int j = ks.length;
+ while (--j >= 0)
+ {
+ flipVector(buf, off, buf, off + words, len - words, baseBit + ks[j]);
+ }
+ flipVector(buf, off, buf, off + words, len - words, baseBit);
+ }
+
+ private static void flipVector(long[] x, int xOff, long[] y, int yOff, int yLen, int bits)
+ {
+ xOff += bits >>> 6;
+ bits &= 0x3F;
+
+ if (bits == 0)
+ {
+ add(x, xOff, y, yOff, yLen);
+ }
+ else
+ {
+ long carry = addShiftedDown(x, xOff + 1, y, yOff, yLen, 64 - bits);
+ x[xOff] ^= carry;
+ }
+ }
+
+ public LongArray modSquare(int m, int[] ks)
+ {
+ int len = getUsedLength();
+ if (len == 0)
+ {
+ return this;
+ }
+
+ int _2len = len << 1;
+ long[] r = new long[_2len];
+
+ int pos = 0;
+ while (pos < _2len)
+ {
+ long mi = m_ints[pos >>> 1];
+ r[pos++] = interleave2_32to64((int)mi);
+ r[pos++] = interleave2_32to64((int)(mi >>> 32));
+ }
+
+ return new LongArray(r, 0, reduceInPlace(r, 0, r.length, m, ks));
+ }
+
+// private LongArray modSquareN(int n, int m, int[] ks)
+// {
+// int len = getUsedLength();
+// if (len == 0)
+// {
+// return this;
+// }
+//
+// int mLen = (m + 63) >>> 6;
+// long[] r = new long[mLen << 1];
+// System.arraycopy(m_ints, 0, r, 0, len);
+//
+// while (--n >= 0)
+// {
+// squareInPlace(r, len, m, ks);
+// len = reduceInPlace(r, 0, r.length, m, ks);
+// }
+//
+// return new LongArray(r, 0, len);
+// }
+//
+// private static void squareInPlace(long[] x, int xLen, int m, int[] ks)
+// {
+// int pos = xLen << 1;
+// while (--xLen >= 0)
+// {
+// long xVal = x[xLen];
+// x[--pos] = interleave2_32to64((int)(xVal >>> 32));
+// x[--pos] = interleave2_32to64((int)xVal);
+// }
+// }
+
+ private static void interleave(long[] x, int xOff, long[] z, int zOff, int count, int width)
+ {
+ switch (width)
+ {
+ case 3:
+ interleave3(x, xOff, z, zOff, count);
+ break;
+ case 5:
+ interleave5(x, xOff, z, zOff, count);
+ break;
+ case 7:
+ interleave7(x, xOff, z, zOff, count);
+ break;
+ default:
+ interleave2_n(x, xOff, z, zOff, count, bitLengths[width] - 1);
+ break;
+ }
+ }
+
+ private static void interleave3(long[] x, int xOff, long[] z, int zOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ z[zOff + i] = interleave3(x[xOff + i]);
+ }
+ }
+
+ private static long interleave3(long x)
+ {
+ long z = x & (1L << 63);
+ return z
+ | interleave3_21to63((int)x & 0x1FFFFF)
+ | interleave3_21to63((int)(x >>> 21) & 0x1FFFFF) << 1
+ | interleave3_21to63((int)(x >>> 42) & 0x1FFFFF) << 2;
+
+// int zPos = 0, wPos = 0, xPos = 0;
+// for (;;)
+// {
+// z |= ((x >>> xPos) & 1L) << zPos;
+// if (++zPos == 63)
+// {
+// String sz2 = Long.toBinaryString(z);
+// return z;
+// }
+// if ((xPos += 21) >= 63)
+// {
+// xPos = ++wPos;
+// }
+// }
+ }
+
+ private static long interleave3_21to63(int x)
+ {
+ int r00 = INTERLEAVE3_TABLE[x & 0x7F];
+ int r21 = INTERLEAVE3_TABLE[(x >>> 7) & 0x7F];
+ int r42 = INTERLEAVE3_TABLE[x >>> 14];
+ return (r42 & 0xFFFFFFFFL) << 42 | (r21 & 0xFFFFFFFFL) << 21 | (r00 & 0xFFFFFFFFL);
+ }
+
+ private static void interleave5(long[] x, int xOff, long[] z, int zOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ z[zOff + i] = interleave5(x[xOff + i]);
+ }
+ }
+
+ private static long interleave5(long x)
+ {
+ return interleave3_13to65((int)x & 0x1FFF)
+ | interleave3_13to65((int)(x >>> 13) & 0x1FFF) << 1
+ | interleave3_13to65((int)(x >>> 26) & 0x1FFF) << 2
+ | interleave3_13to65((int)(x >>> 39) & 0x1FFF) << 3
+ | interleave3_13to65((int)(x >>> 52) & 0x1FFF) << 4;
+
+// long z = 0;
+// int zPos = 0, wPos = 0, xPos = 0;
+// for (;;)
+// {
+// z |= ((x >>> xPos) & 1L) << zPos;
+// if (++zPos == 64)
+// {
+// return z;
+// }
+// if ((xPos += 13) >= 64)
+// {
+// xPos = ++wPos;
+// }
+// }
+ }
+
+ private static long interleave3_13to65(int x)
+ {
+ int r00 = INTERLEAVE5_TABLE[x & 0x7F];
+ int r35 = INTERLEAVE5_TABLE[x >>> 7];
+ return (r35 & 0xFFFFFFFFL) << 35 | (r00 & 0xFFFFFFFFL);
+ }
+
+ private static void interleave7(long[] x, int xOff, long[] z, int zOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ z[zOff + i] = interleave7(x[xOff + i]);
+ }
+ }
+
+ private static long interleave7(long x)
+ {
+ long z = x & (1L << 63);
+ return z
+ | INTERLEAVE7_TABLE[(int)x & 0x1FF]
+ | INTERLEAVE7_TABLE[(int)(x >>> 9) & 0x1FF] << 1
+ | INTERLEAVE7_TABLE[(int)(x >>> 18) & 0x1FF] << 2
+ | INTERLEAVE7_TABLE[(int)(x >>> 27) & 0x1FF] << 3
+ | INTERLEAVE7_TABLE[(int)(x >>> 36) & 0x1FF] << 4
+ | INTERLEAVE7_TABLE[(int)(x >>> 45) & 0x1FF] << 5
+ | INTERLEAVE7_TABLE[(int)(x >>> 54) & 0x1FF] << 6;
+
+// int zPos = 0, wPos = 0, xPos = 0;
+// for (;;)
+// {
+// z |= ((x >>> xPos) & 1L) << zPos;
+// if (++zPos == 63)
+// {
+// return z;
+// }
+// if ((xPos += 9) >= 63)
+// {
+// xPos = ++wPos;
+// }
+// }
+ }
+
+ private static void interleave2_n(long[] x, int xOff, long[] z, int zOff, int count, int rounds)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ z[zOff + i] = interleave2_n(x[xOff + i], rounds);
+ }
+ }
+
+ private static long interleave2_n(long x, int rounds)
+ {
+ while (rounds > 1)
+ {
+ rounds -= 2;
+ x = interleave4_16to64((int)x & 0xFFFF)
+ | interleave4_16to64((int)(x >>> 16) & 0xFFFF) << 1
+ | interleave4_16to64((int)(x >>> 32) & 0xFFFF) << 2
+ | interleave4_16to64((int)(x >>> 48) & 0xFFFF) << 3;
+ }
+ if (rounds > 0)
+ {
+ x = interleave2_32to64((int)x) | interleave2_32to64((int)(x >>> 32)) << 1;
+ }
+ return x;
+ }
+
+ private static long interleave4_16to64(int x)
+ {
+ int r00 = INTERLEAVE4_TABLE[x & 0xFF];
+ int r32 = INTERLEAVE4_TABLE[x >>> 8];
+ return (r32 & 0xFFFFFFFFL) << 32 | (r00 & 0xFFFFFFFFL);
+ }
+
+ private static long interleave2_32to64(int x)
+ {
+ int r00 = INTERLEAVE2_TABLE[x & 0xFF] | INTERLEAVE2_TABLE[(x >>> 8) & 0xFF] << 16;
+ int r32 = INTERLEAVE2_TABLE[(x >>> 16) & 0xFF] | INTERLEAVE2_TABLE[x >>> 24] << 16;
+ return (r32 & 0xFFFFFFFFL) << 32 | (r00 & 0xFFFFFFFFL);
+ }
+
+// private static LongArray expItohTsujii2(LongArray B, int n, int m, int[] ks)
+// {
+// LongArray t1 = B, t3 = new LongArray(new long[]{ 1L });
+// int scale = 1;
+//
+// int numTerms = n;
+// while (numTerms > 1)
+// {
+// if ((numTerms & 1) != 0)
+// {
+// t3 = t3.modMultiply(t1, m, ks);
+// t1 = t1.modSquareN(scale, m, ks);
+// }
+//
+// LongArray t2 = t1.modSquareN(scale, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+// numTerms >>>= 1; scale <<= 1;
+// }
+//
+// return t3.modMultiply(t1, m, ks);
+// }
+//
+// private static LongArray expItohTsujii23(LongArray B, int n, int m, int[] ks)
+// {
+// LongArray t1 = B, t3 = new LongArray(new long[]{ 1L });
+// int scale = 1;
+//
+// int numTerms = n;
+// while (numTerms > 1)
+// {
+// boolean m03 = numTerms % 3 == 0;
+// boolean m14 = !m03 && (numTerms & 1) != 0;
+//
+// if (m14)
+// {
+// t3 = t3.modMultiply(t1, m, ks);
+// t1 = t1.modSquareN(scale, m, ks);
+// }
+//
+// LongArray t2 = t1.modSquareN(scale, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+//
+// if (m03)
+// {
+// t2 = t2.modSquareN(scale, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+// numTerms /= 3; scale *= 3;
+// }
+// else
+// {
+// numTerms >>>= 1; scale <<= 1;
+// }
+// }
+//
+// return t3.modMultiply(t1, m, ks);
+// }
+//
+// private static LongArray expItohTsujii235(LongArray B, int n, int m, int[] ks)
+// {
+// LongArray t1 = B, t4 = new LongArray(new long[]{ 1L });
+// int scale = 1;
+//
+// int numTerms = n;
+// while (numTerms > 1)
+// {
+// if (numTerms % 5 == 0)
+// {
+//// t1 = expItohTsujii23(t1, 5, m, ks);
+//
+// LongArray t3 = t1;
+// t1 = t1.modSquareN(scale, m, ks);
+//
+// LongArray t2 = t1.modSquareN(scale, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+// t2 = t1.modSquareN(scale << 1, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+//
+// t1 = t1.modMultiply(t3, m, ks);
+//
+// numTerms /= 5; scale *= 5;
+// continue;
+// }
+//
+// boolean m03 = numTerms % 3 == 0;
+// boolean m14 = !m03 && (numTerms & 1) != 0;
+//
+// if (m14)
+// {
+// t4 = t4.modMultiply(t1, m, ks);
+// t1 = t1.modSquareN(scale, m, ks);
+// }
+//
+// LongArray t2 = t1.modSquareN(scale, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+//
+// if (m03)
+// {
+// t2 = t2.modSquareN(scale, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+// numTerms /= 3; scale *= 3;
+// }
+// else
+// {
+// numTerms >>>= 1; scale <<= 1;
+// }
+// }
+//
+// return t4.modMultiply(t1, m, ks);
+// }
+
+ public LongArray modInverse(int m, int[] ks)
+ {
+ /*
+ * Fermat's Little Theorem
+ */
+// LongArray A = this;
+// LongArray B = A.modSquare(m, ks);
+// LongArray R0 = B, R1 = B;
+// for (int i = 2; i < m; ++i)
+// {
+// R1 = R1.modSquare(m, ks);
+// R0 = R0.modMultiply(R1, m, ks);
+// }
+//
+// return R0;
+
+ /*
+ * Itoh-Tsujii
+ */
+// LongArray B = modSquare(m, ks);
+// switch (m)
+// {
+// case 409:
+// return expItohTsujii23(B, m - 1, m, ks);
+// case 571:
+// return expItohTsujii235(B, m - 1, m, ks);
+// case 163:
+// case 233:
+// case 283:
+// default:
+// return expItohTsujii2(B, m - 1, m, ks);
+// }
+
+ /*
+ * Inversion in F2m using the extended Euclidean algorithm
+ *
+ * Input: A nonzero polynomial a(z) of degree at most m-1
+ * Output: a(z)^(-1) mod f(z)
+ */
+ int uzDegree = degree();
+ if (uzDegree == 1)
+ {
+ return this;
+ }
+
+ // u(z) := a(z)
+ LongArray uz = (LongArray)clone();
+
+ int t = (m + 63) >>> 6;
+
+ // v(z) := f(z)
+ LongArray vz = new LongArray(t);
+ reduceBit(vz.m_ints, 0, m, m, ks);
+
+ // g1(z) := 1, g2(z) := 0
+ LongArray g1z = new LongArray(t);
+ g1z.m_ints[0] = 1L;
+ LongArray g2z = new LongArray(t);
+
+ int[] uvDeg = new int[]{ uzDegree, m + 1 };
+ LongArray[] uv = new LongArray[]{ uz, vz };
+
+ int[] ggDeg = new int[]{ 1, 0 };
+ LongArray[] gg = new LongArray[]{ g1z, g2z };
+
+ int b = 1;
+ int duv1 = uvDeg[b];
+ int dgg1 = ggDeg[b];
+ int j = duv1 - uvDeg[1 - b];
+
+ for (;;)
+ {
+ if (j < 0)
+ {
+ j = -j;
+ uvDeg[b] = duv1;
+ ggDeg[b] = dgg1;
+ b = 1 - b;
+ duv1 = uvDeg[b];
+ dgg1 = ggDeg[b];
+ }
+
+ uv[b].addShiftedByBitsSafe(uv[1 - b], uvDeg[1 - b], j);
+
+ int duv2 = uv[b].degreeFrom(duv1);
+ if (duv2 == 0)
+ {
+ return gg[1 - b];
+ }
+
+ {
+ int dgg2 = ggDeg[1 - b];
+ gg[b].addShiftedByBitsSafe(gg[1 - b], dgg2, j);
+ dgg2 += j;
+
+ if (dgg2 > dgg1)
+ {
+ dgg1 = dgg2;
+ }
+ else if (dgg2 == dgg1)
+ {
+ dgg1 = gg[b].degreeFrom(dgg1);
+ }
+ }
+
+ j += (duv2 - duv1);
+ duv1 = duv2;
+ }
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof LongArray))
+ {
+ return false;
+ }
+ LongArray other = (LongArray) o;
+ int usedLen = getUsedLength();
+ if (other.getUsedLength() != usedLen)
+ {
+ return false;
+ }
+ for (int i = 0; i < usedLen; i++)
+ {
+ if (m_ints[i] != other.m_ints[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int usedLen = getUsedLength();
+ int hash = 1;
+ for (int i = 0; i < usedLen; i++)
+ {
+ long mi = m_ints[i];
+ hash *= 31;
+ hash ^= (int)mi;
+ hash *= 31;
+ hash ^= (int)(mi >>> 32);
+ }
+ return hash;
+ }
+
+ public Object clone()
+ {
+ return new LongArray(Arrays.clone(m_ints));
+ }
+
+ public String toString()
+ {
+ int i = getUsedLength();
+ if (i == 0)
+ {
+ return "0";
+ }
+
+ StringBuffer sb = new StringBuffer(Long.toBinaryString(m_ints[--i]));
+ while (--i >= 0)
+ {
+ String s = Long.toBinaryString(m_ints[i]);
+
+ // Add leading zeroes, except for highest significant word
+ int len = s.length();
+ if (len < 64)
+ {
+ sb.append(ZEROES.substring(len));
+ }
+
+ sb.append(s);
+ }
+ return sb.toString();
+ }
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java b/bcprov/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java
index 804dcf7..3849858 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java
@@ -2,9 +2,9 @@ package org.bouncycastle.math.ec;
/**
* Interface for classes storing precomputation data for multiplication
- * algorithms. Used as a Memento (see GOF patterns) for
- * <code>WNafMultiplier</code>.
+ * algorithms. Used as a Memento (see GOF patterns) by e.g.
+ * <code>WNafL2RMultiplier</code>.
*/
-interface PreCompInfo
+public interface PreCompInfo
{
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java b/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java
index af4355f..42d6738 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java
@@ -392,15 +392,7 @@ class Tnaf
*/
public static ECPoint.F2m tau(ECPoint.F2m p)
{
- if (p.isInfinity())
- {
- return p;
- }
-
- ECFieldElement x = p.getX();
- ECFieldElement y = p.getY();
-
- return new ECPoint.F2m(p.getCurve(), x.square(), y.square(), p.isCompressed());
+ return p.tau();
}
/**
@@ -415,23 +407,17 @@ class Tnaf
*/
public static byte getMu(ECCurve.F2m curve)
{
- BigInteger a = curve.getA().toBigInteger();
- byte mu;
-
- if (a.equals(ECConstants.ZERO))
- {
- mu = -1;
- }
- else if (a.equals(ECConstants.ONE))
+ if (!curve.isKoblitz())
{
- mu = 1;
+ throw new IllegalArgumentException("No Koblitz curve (ABC), TNAF multiplication not possible");
}
- else
+
+ if (curve.getA().isZero())
{
- throw new IllegalArgumentException("No Koblitz curve (ABC), " +
- "TNAF multiplication not possible");
+ return -1;
}
- return mu;
+
+ return 1;
}
/**
@@ -838,7 +824,9 @@ class Tnaf
{
pu[i] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]);
}
-
+
+ p.getCurve().normalizeAll(pu);
+
return pu;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java
new file mode 100644
index 0000000..59a9313
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java
@@ -0,0 +1,101 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+/**
+ * Class implementing the WNAF (Window Non-Adjacent Form) multiplication
+ * algorithm.
+ */
+public class WNafL2RMultiplier extends AbstractECMultiplier
+{
+ /**
+ * Multiplies <code>this</code> by an integer <code>k</code> using the
+ * Window NAF method.
+ * @param k The integer by which <code>this</code> is multiplied.
+ * @return A new <code>ECPoint</code> which equals <code>this</code>
+ * multiplied by <code>k</code>.
+ */
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ // Clamp the window width in the range [2, 16]
+ int width = Math.max(2, Math.min(16, getWindowSize(k.bitLength())));
+
+ WNafPreCompInfo wnafPreCompInfo = WNafUtil.precompute(p, width, true);
+ ECPoint[] preComp = wnafPreCompInfo.getPreComp();
+ ECPoint[] preCompNeg = wnafPreCompInfo.getPreCompNeg();
+
+ int[] wnaf = WNafUtil.generateCompactWindowNaf(width, k);
+
+ ECPoint R = p.getCurve().getInfinity();
+
+ int i = wnaf.length;
+
+ /*
+ * NOTE This code optimizes the first window using the precomputed points to substitute an
+ * addition for 2 or more doublings.
+ */
+ if (i > 1)
+ {
+ int wi = wnaf[--i];
+ int digit = wi >> 16, zeroes = wi & 0xFFFF;
+
+ int n = Math.abs(digit);
+ ECPoint[] table = digit < 0 ? preCompNeg : preComp;
+
+ /*
+ * NOTE: We use this optimization conservatively, since some coordinate systems have
+ * significantly cheaper doubling relative to addition.
+ *
+ * (n << 2) selects precomputed values in the lower half of the table
+ * (n << 3) selects precomputed values in the lower quarter of the table
+ */
+ //if ((n << 2) < (1 << width))
+ if ((n << 3) < (1 << width))
+ {
+ int highest = LongArray.bitLengths[n];
+ int lowBits = n ^ (1 << (highest - 1));
+ int scale = width - highest;
+
+ int i1 = ((1 << (width - 1)) - 1);
+ int i2 = (lowBits << scale) + 1;
+ R = table[i1 >>> 1].add(table[i2 >>> 1]);
+
+ zeroes -= scale;
+
+// System.out.println("Optimized: 2^" + scale + " * " + n + " = " + i1 + " + " + i2);
+ }
+ else
+ {
+ R = table[n >>> 1];
+ }
+
+ R = R.timesPow2(zeroes);
+ }
+
+ while (i > 0)
+ {
+ int wi = wnaf[--i];
+ int digit = wi >> 16, zeroes = wi & 0xFFFF;
+
+ int n = Math.abs(digit);
+ ECPoint[] table = digit < 0 ? preCompNeg : preComp;
+ ECPoint r = table[n >>> 1];
+
+ R = R.twicePlus(r);
+ R = R.timesPow2(zeroes);
+ }
+
+ return R;
+ }
+
+ /**
+ * Determine window width to use for a scalar multiplication of the given size.
+ *
+ * @param bits the bit-length of the scalar to multiply by
+ * @return the window size to use
+ */
+ protected int getWindowSize(int bits)
+ {
+ return WNafUtil.getWindowSize(bits);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafMultiplier.java
deleted file mode 100644
index 10c8ed2..0000000
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafMultiplier.java
+++ /dev/null
@@ -1,240 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Class implementing the WNAF (Window Non-Adjacent Form) multiplication
- * algorithm.
- */
-class WNafMultiplier implements ECMultiplier
-{
- /**
- * Computes the Window NAF (non-adjacent Form) of an integer.
- * @param width The width <code>w</code> of the Window NAF. The width is
- * defined as the minimal number <code>w</code>, such that for any
- * <code>w</code> consecutive digits in the resulting representation, at
- * most one is non-zero.
- * @param k The integer of which the Window NAF is computed.
- * @return The Window NAF of the given width, such that the following holds:
- * <code>k = &sum;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
- * </code>, where the <code>k<sub>i</sub></code> denote the elements of the
- * returned <code>byte[]</code>.
- */
- public byte[] windowNaf(byte width, BigInteger k)
- {
- // The window NAF is at most 1 element longer than the binary
- // representation of the integer k. byte can be used instead of short or
- // int unless the window width is larger than 8. For larger width use
- // short or int. However, a width of more than 8 is not efficient for
- // m = log2(q) smaller than 2305 Bits. Note: Values for m larger than
- // 1000 Bits are currently not used in practice.
- byte[] wnaf = new byte[k.bitLength() + 1];
-
- // 2^width as short and BigInteger
- short pow2wB = (short)(1 << width);
- BigInteger pow2wBI = BigInteger.valueOf(pow2wB);
-
- int i = 0;
-
- // The actual length of the WNAF
- int length = 0;
-
- // while k >= 1
- while (k.signum() > 0)
- {
- // if k is odd
- if (k.testBit(0))
- {
- // k mod 2^width
- BigInteger remainder = k.mod(pow2wBI);
-
- // if remainder > 2^(width - 1) - 1
- if (remainder.testBit(width - 1))
- {
- wnaf[i] = (byte)(remainder.intValue() - pow2wB);
- }
- else
- {
- wnaf[i] = (byte)remainder.intValue();
- }
- // wnaf[i] is now in [-2^(width-1), 2^(width-1)-1]
-
- k = k.subtract(BigInteger.valueOf(wnaf[i]));
- length = i;
- }
- else
- {
- wnaf[i] = 0;
- }
-
- // k = k/2
- k = k.shiftRight(1);
- i++;
- }
-
- length++;
-
- // Reduce the WNAF array to its actual length
- byte[] wnafShort = new byte[length];
- System.arraycopy(wnaf, 0, wnafShort, 0, length);
- return wnafShort;
- }
-
- /**
- * Multiplies <code>this</code> by an integer <code>k</code> using the
- * Window NAF method.
- * @param k The integer by which <code>this</code> is multiplied.
- * @return A new <code>ECPoint</code> which equals <code>this</code>
- * multiplied by <code>k</code>.
- */
- public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
- {
- WNafPreCompInfo wnafPreCompInfo;
-
- if ((preCompInfo != null) && (preCompInfo instanceof WNafPreCompInfo))
- {
- wnafPreCompInfo = (WNafPreCompInfo)preCompInfo;
- }
- else
- {
- // Ignore empty PreCompInfo or PreCompInfo of incorrect type
- wnafPreCompInfo = new WNafPreCompInfo();
- }
-
- // floor(log2(k))
- int m = k.bitLength();
-
- // width of the Window NAF
- byte width;
-
- // Required length of precomputation array
- int reqPreCompLen;
-
- // Determine optimal width and corresponding length of precomputation
- // array based on literature values
- if (m < 13)
- {
- width = 2;
- reqPreCompLen = 1;
- }
- else
- {
- if (m < 41)
- {
- width = 3;
- reqPreCompLen = 2;
- }
- else
- {
- if (m < 121)
- {
- width = 4;
- reqPreCompLen = 4;
- }
- else
- {
- if (m < 337)
- {
- width = 5;
- reqPreCompLen = 8;
- }
- else
- {
- if (m < 897)
- {
- width = 6;
- reqPreCompLen = 16;
- }
- else
- {
- if (m < 2305)
- {
- width = 7;
- reqPreCompLen = 32;
- }
- else
- {
- width = 8;
- reqPreCompLen = 127;
- }
- }
- }
- }
- }
- }
-
- // The length of the precomputation array
- int preCompLen = 1;
-
- ECPoint[] preComp = wnafPreCompInfo.getPreComp();
- ECPoint twiceP = wnafPreCompInfo.getTwiceP();
-
- // Check if the precomputed ECPoints already exist
- if (preComp == null)
- {
- // Precomputation must be performed from scratch, create an empty
- // precomputation array of desired length
- preComp = new ECPoint[]{ p };
- }
- else
- {
- // Take the already precomputed ECPoints to start with
- preCompLen = preComp.length;
- }
-
- if (twiceP == null)
- {
- // Compute twice(p)
- twiceP = p.twice();
- }
-
- if (preCompLen < reqPreCompLen)
- {
- // Precomputation array must be made bigger, copy existing preComp
- // array into the larger new preComp array
- ECPoint[] oldPreComp = preComp;
- preComp = new ECPoint[reqPreCompLen];
- System.arraycopy(oldPreComp, 0, preComp, 0, preCompLen);
-
- for (int i = preCompLen; i < reqPreCompLen; i++)
- {
- // Compute the new ECPoints for the precomputation array.
- // The values 1, 3, 5, ..., 2^(width-1)-1 times p are
- // computed
- preComp[i] = twiceP.add(preComp[i - 1]);
- }
- }
-
- // Compute the Window NAF of the desired width
- byte[] wnaf = windowNaf(width, k);
- int l = wnaf.length;
-
- // Apply the Window NAF to p using the precomputed ECPoint values.
- ECPoint q = p.getCurve().getInfinity();
- for (int i = l - 1; i >= 0; i--)
- {
- q = q.twice();
-
- if (wnaf[i] != 0)
- {
- if (wnaf[i] > 0)
- {
- q = q.add(preComp[(wnaf[i] - 1)/2]);
- }
- else
- {
- // wnaf[i] < 0
- q = q.subtract(preComp[(-wnaf[i] - 1)/2]);
- }
- }
- }
-
- // Set PreCompInfo in ECPoint, such that it is available for next
- // multiplication.
- wnafPreCompInfo.setPreComp(preComp);
- wnafPreCompInfo.setTwiceP(twiceP);
- p.setPreCompInfo(wnafPreCompInfo);
- return q;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java
index fc0d5fe..d142ab7 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java
@@ -4,21 +4,23 @@ package org.bouncycastle.math.ec;
* Class holding precomputation data for the WNAF (Window Non-Adjacent Form)
* algorithm.
*/
-class WNafPreCompInfo implements PreCompInfo
+public class WNafPreCompInfo implements PreCompInfo
{
/**
- * Array holding the precomputed <code>ECPoint</code>s used for the Window
- * NAF multiplication in <code>
- * {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply()
- * WNafMultiplier.multiply()}</code>.
+ * Array holding the precomputed <code>ECPoint</code>s used for a Window
+ * NAF multiplication.
*/
private ECPoint[] preComp = null;
/**
+ * Array holding the negations of the precomputed <code>ECPoint</code>s used
+ * for a Window NAF multiplication.
+ */
+ private ECPoint[] preCompNeg = null;
+
+ /**
* Holds an <code>ECPoint</code> representing twice(this). Used for the
- * Window NAF multiplication in <code>
- * {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply()
- * WNafMultiplier.multiply()}</code>.
+ * Window NAF multiplication to create or extend the precomputed values.
*/
private ECPoint twiceP = null;
@@ -27,18 +29,28 @@ class WNafPreCompInfo implements PreCompInfo
return preComp;
}
+ protected ECPoint[] getPreCompNeg()
+ {
+ return preCompNeg;
+ }
+
protected void setPreComp(ECPoint[] preComp)
{
this.preComp = preComp;
}
+ protected void setPreCompNeg(ECPoint[] preCompNeg)
+ {
+ this.preCompNeg = preCompNeg;
+ }
+
protected ECPoint getTwiceP()
{
return twiceP;
}
- protected void setTwiceP(ECPoint twiceThis)
+ protected void setTwiceP(ECPoint twiceP)
{
- this.twiceP = twiceThis;
+ this.twiceP = twiceP;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
new file mode 100644
index 0000000..6465d66
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
@@ -0,0 +1,393 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+public abstract class WNafUtil
+{
+ private static int[] DEFAULT_WINDOW_SIZE_CUTOFFS = new int[]{ 13, 41, 121, 337, 897, 2305 };
+
+ public static int[] generateCompactNaf(BigInteger k)
+ {
+ if ((k.bitLength() >>> 16) != 0)
+ {
+ throw new IllegalArgumentException("'k' must have bitlength < 2^16");
+ }
+
+ BigInteger _3k = k.shiftLeft(1).add(k);
+
+ int digits = _3k.bitLength() - 1;
+ int[] naf = new int[(digits + 1) >> 1];
+
+ int length = 0, zeroes = 0;
+ for (int i = 1; i <= digits; ++i)
+ {
+ boolean _3kBit = _3k.testBit(i);
+ boolean kBit = k.testBit(i);
+
+ if (_3kBit == kBit)
+ {
+ ++zeroes;
+ }
+ else
+ {
+ int digit = kBit ? -1 : 1;
+ naf[length++] = (digit << 16) | zeroes;
+ zeroes = 0;
+ }
+ }
+
+ if (naf.length > length)
+ {
+ naf = trim(naf, length);
+ }
+
+ return naf;
+ }
+
+ public static int[] generateCompactWindowNaf(int width, BigInteger k)
+ {
+ if (width == 2)
+ {
+ return generateCompactNaf(k);
+ }
+
+ if (width < 2 || width > 16)
+ {
+ throw new IllegalArgumentException("'width' must be in the range [2, 16]");
+ }
+ if ((k.bitLength() >>> 16) != 0)
+ {
+ throw new IllegalArgumentException("'k' must have bitlength < 2^16");
+ }
+
+ int[] wnaf = new int[k.bitLength() / width + 1];
+
+ // 2^width and a mask and sign bit set accordingly
+ int pow2 = 1 << width;
+ int mask = pow2 - 1;
+ int sign = pow2 >>> 1;
+
+ boolean carry = false;
+ int length = 0, pos = 0;
+
+ while (pos <= k.bitLength())
+ {
+ if (k.testBit(pos) == carry)
+ {
+ ++pos;
+ continue;
+ }
+
+ k = k.shiftRight(pos);
+
+ int digit = k.intValue() & mask;
+ if (carry)
+ {
+ ++digit;
+ }
+
+ carry = (digit & sign) != 0;
+ if (carry)
+ {
+ digit -= pow2;
+ }
+
+ int zeroes = length > 0 ? pos - 1 : pos;
+ wnaf[length++] = (digit << 16) | zeroes;
+ pos = width;
+ }
+
+ // Reduce the WNAF array to its actual length
+ if (wnaf.length > length)
+ {
+ wnaf = trim(wnaf, length);
+ }
+
+ return wnaf;
+ }
+
+ public static byte[] generateJSF(BigInteger g, BigInteger h)
+ {
+ int digits = Math.max(g.bitLength(), h.bitLength()) + 1;
+ byte[] jsf = new byte[digits];
+
+ BigInteger k0 = g, k1 = h;
+ int j = 0, d0 = 0, d1 = 0;
+
+ while (k0.signum() > 0 || k1.signum() > 0 || d0 > 0 || d1 > 0)
+ {
+ int n0 = (k0.intValue() + d0) & 7, n1 = (k1.intValue() + d1) & 7;
+
+ int u0 = n0 & 1;
+ if (u0 != 0)
+ {
+ u0 -= (n0 & 2);
+ if ((n0 + u0) == 4 && (n1 & 3) == 2)
+ {
+ u0 = -u0;
+ }
+ }
+
+ int u1 = n1 & 1;
+ if (u1 != 0)
+ {
+ u1 -= (n1 & 2);
+ if ((n1 + u1) == 4 && (n0 & 3) == 2)
+ {
+ u1 = -u1;
+ }
+ }
+
+ if ((d0 << 1) == 1 + u0)
+ {
+ d0 = 1 - d0;
+ }
+ if ((d1 << 1) == 1 + u1)
+ {
+ d1 = 1 - d1;
+ }
+
+ k0 = k0.shiftRight(1);
+ k1 = k1.shiftRight(1);
+
+ jsf[j++] = (byte)((u0 << 4) | (u1 & 0xF));
+ }
+
+ // Reduce the JSF array to its actual length
+ if (jsf.length > j)
+ {
+ jsf = trim(jsf, j);
+ }
+
+ return jsf;
+ }
+
+ public static byte[] generateNaf(BigInteger k)
+ {
+ BigInteger _3k = k.shiftLeft(1).add(k);
+
+ int digits = _3k.bitLength() - 1;
+ byte[] naf = new byte[digits];
+
+ for (int i = 1; i <= digits; ++i)
+ {
+ boolean _3kBit = _3k.testBit(i);
+ boolean kBit = k.testBit(i);
+
+ naf[i - 1] = (byte)(_3kBit == kBit ? 0 : kBit ? -1 : 1);
+ }
+
+ return naf;
+ }
+
+ /**
+ * Computes the Window NAF (non-adjacent Form) of an integer.
+ * @param width The width <code>w</code> of the Window NAF. The width is
+ * defined as the minimal number <code>w</code>, such that for any
+ * <code>w</code> consecutive digits in the resulting representation, at
+ * most one is non-zero.
+ * @param k The integer of which the Window NAF is computed.
+ * @return The Window NAF of the given width, such that the following holds:
+ * <code>k = &sum;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
+ * </code>, where the <code>k<sub>i</sub></code> denote the elements of the
+ * returned <code>byte[]</code>.
+ */
+ public static byte[] generateWindowNaf(int width, BigInteger k)
+ {
+ if (width == 2)
+ {
+ return generateNaf(k);
+ }
+
+ if (width < 2 || width > 8)
+ {
+ throw new IllegalArgumentException("'width' must be in the range [2, 8]");
+ }
+
+ byte[] wnaf = new byte[k.bitLength() + 1];
+
+ // 2^width and a mask and sign bit set accordingly
+ int pow2 = 1 << width;
+ int mask = pow2 - 1;
+ int sign = pow2 >>> 1;
+
+ boolean carry = false;
+ int length = 0, pos = 0;
+
+ while (pos <= k.bitLength())
+ {
+ if (k.testBit(pos) == carry)
+ {
+ ++pos;
+ continue;
+ }
+
+ k = k.shiftRight(pos);
+
+ int digit = k.intValue() & mask;
+ if (carry)
+ {
+ ++digit;
+ }
+
+ carry = (digit & sign) != 0;
+ if (carry)
+ {
+ digit -= pow2;
+ }
+
+ length += (length > 0) ? pos - 1 : pos;
+ wnaf[length++] = (byte)digit;
+ pos = width;
+ }
+
+ // Reduce the WNAF array to its actual length
+ if (wnaf.length > length)
+ {
+ wnaf = trim(wnaf, length);
+ }
+
+ return wnaf;
+ }
+
+ public static WNafPreCompInfo getWNafPreCompInfo(PreCompInfo preCompInfo)
+ {
+ if ((preCompInfo != null) && (preCompInfo instanceof WNafPreCompInfo))
+ {
+ return (WNafPreCompInfo)preCompInfo;
+ }
+
+ return new WNafPreCompInfo();
+ }
+
+ /**
+ * Determine window width to use for a scalar multiplication of the given size.
+ *
+ * @param bits the bit-length of the scalar to multiply by
+ * @return the window size to use
+ */
+ public static int getWindowSize(int bits)
+ {
+ return getWindowSize(bits, DEFAULT_WINDOW_SIZE_CUTOFFS);
+ }
+
+ /**
+ * Determine window width to use for a scalar multiplication of the given size.
+ *
+ * @param bits the bit-length of the scalar to multiply by
+ * @param windowSizeCutoffs a monotonically increasing list of bit sizes at which to increment the window width
+ * @return the window size to use
+ */
+ public static int getWindowSize(int bits, int[] windowSizeCutoffs)
+ {
+ int w = 0;
+ for (; w < windowSizeCutoffs.length; ++w)
+ {
+ if (bits < windowSizeCutoffs[w])
+ {
+ break;
+ }
+ }
+ return w + 2;
+ }
+
+ public static WNafPreCompInfo precompute(ECPoint p, int width, boolean includeNegated)
+ {
+ ECCurve c = p.getCurve();
+ WNafPreCompInfo wnafPreCompInfo = getWNafPreCompInfo(c.getPreCompInfo(p));
+
+ ECPoint[] preComp = wnafPreCompInfo.getPreComp();
+ if (preComp == null)
+ {
+ preComp = new ECPoint[]{ p };
+ }
+
+ int preCompLen = preComp.length;
+ int reqPreCompLen = 1 << Math.max(0, width - 2);
+
+ if (preCompLen < reqPreCompLen)
+ {
+ ECPoint twiceP = wnafPreCompInfo.getTwiceP();
+ if (twiceP == null)
+ {
+ twiceP = preComp[0].twice().normalize();
+ wnafPreCompInfo.setTwiceP(twiceP);
+ }
+
+ preComp = resizeTable(preComp, reqPreCompLen);
+
+ /*
+ * TODO Okeya/Sakurai paper has precomputation trick and "Montgomery's Trick" to speed this up.
+ * Also, co-Z arithmetic could avoid the subsequent normalization too.
+ */
+ for (int i = preCompLen; i < reqPreCompLen; i++)
+ {
+ /*
+ * Compute the new ECPoints for the precomputation array. The values 1, 3, 5, ...,
+ * 2^(width-1)-1 times p are computed
+ */
+ preComp[i] = twiceP.add(preComp[i - 1]);
+ }
+
+ /*
+ * Having oft-used operands in affine form makes operations faster.
+ */
+ c.normalizeAll(preComp);
+ }
+
+ wnafPreCompInfo.setPreComp(preComp);
+
+ if (includeNegated)
+ {
+ ECPoint[] preCompNeg = wnafPreCompInfo.getPreCompNeg();
+
+ int pos;
+ if (preCompNeg == null)
+ {
+ pos = 0;
+ preCompNeg = new ECPoint[reqPreCompLen];
+ }
+ else
+ {
+ pos = preCompNeg.length;
+ if (pos < reqPreCompLen)
+ {
+ preCompNeg = resizeTable(preCompNeg, reqPreCompLen);
+ }
+ }
+
+ while (pos < reqPreCompLen)
+ {
+ preCompNeg[pos] = preComp[pos].negate();
+ ++pos;
+ }
+
+ wnafPreCompInfo.setPreCompNeg(preCompNeg);
+ }
+
+ c.setPreCompInfo(p, wnafPreCompInfo);
+
+ return wnafPreCompInfo;
+ }
+
+ private static byte[] trim(byte[] a, int length)
+ {
+ byte[] result = new byte[length];
+ System.arraycopy(a, 0, result, 0, result.length);
+ return result;
+ }
+
+ private static int[] trim(int[] a, int length)
+ {
+ int[] result = new int[length];
+ System.arraycopy(a, 0, result, 0, result.length);
+ return result;
+ }
+
+ private static ECPoint[] resizeTable(ECPoint[] a, int length)
+ {
+ ECPoint[] result = new ECPoint[length];
+ System.arraycopy(a, 0, result, 0, a.length);
+ return result;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java
index 2353979..7bd30ec 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java
@@ -6,7 +6,7 @@ import java.math.BigInteger;
* Class implementing the WTNAF (Window
* <code>&tau;</code>-adic Non-Adjacent Form) algorithm.
*/
-class WTauNafMultiplier implements ECMultiplier
+public class WTauNafMultiplier extends AbstractECMultiplier
{
/**
* Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
@@ -16,7 +16,7 @@ class WTauNafMultiplier implements ECMultiplier
* @param k The integer by which to multiply <code>k</code>.
* @return <code>p</code> multiplied by <code>k</code>.
*/
- public ECPoint multiply(ECPoint point, BigInteger k, PreCompInfo preCompInfo)
+ protected ECPoint multiplyPositive(ECPoint point, BigInteger k)
{
if (!(point instanceof ECPoint.F2m))
{
@@ -25,8 +25,7 @@ class WTauNafMultiplier implements ECMultiplier
}
ECPoint.F2m p = (ECPoint.F2m)point;
-
- ECCurve.F2m curve = (ECCurve.F2m) p.getCurve();
+ ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
int m = curve.getM();
byte a = curve.getA().toBigInteger().byteValue();
byte mu = curve.getMu();
@@ -34,7 +33,7 @@ class WTauNafMultiplier implements ECMultiplier
ZTauElement rho = Tnaf.partModReduction(k, m, a, s, mu, (byte)10);
- return multiplyWTnaf(p, rho, preCompInfo, a, mu);
+ return multiplyWTnaf(p, rho, curve.getPreCompInfo(p), a, mu);
}
/**
@@ -88,7 +87,7 @@ class WTauNafMultiplier implements ECMultiplier
if ((preCompInfo == null) || !(preCompInfo instanceof WTauNafPreCompInfo))
{
pu = Tnaf.getPreComp(p, a);
- p.setPreCompInfo(new WTauNafPreCompInfo(pu));
+ curve.setPreCompInfo(p, new WTauNafPreCompInfo(pu));
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
index 457320e..3f7677c 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
@@ -11,7 +11,7 @@ public final class Arrays
{
// static class, hide constructor
}
-
+
public static boolean areEqual(
boolean[] a,
boolean[] b)
@@ -199,36 +199,62 @@ public final class Arrays
return true;
}
- public static boolean areEqual(
- BigInteger[] a,
- BigInteger[] b)
+ public static boolean areEqual(Object[] a, Object[] b)
{
if (a == b)
{
return true;
}
-
if (a == null || b == null)
{
return false;
}
-
if (a.length != b.length)
{
return false;
}
-
for (int i = 0; i != a.length; i++)
{
- if (!a[i].equals(b[i]))
+ Object objA = a[i], objB = b[i];
+ if (objA == null)
+ {
+ if (objB != null)
+ {
+ return false;
+ }
+ }
+ else if (!objA.equals(objB))
{
return false;
}
}
-
return true;
}
+ public static boolean contains(short[] a, short n)
+ {
+ for (int i = 0; i < a.length; ++i)
+ {
+ if (a[i] == n)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean contains(int[] a, int n)
+ {
+ for (int i = 0; i < a.length; ++i)
+ {
+ if (a[i] == n)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
public static void fill(
byte[] array,
byte value)
@@ -391,7 +417,7 @@ public final class Arrays
return hc;
}
- public static int hashCode(BigInteger[] data)
+ public static int hashCode(Object[] data)
{
if (data == null)
{
@@ -423,6 +449,20 @@ public final class Arrays
return copy;
}
+ public static byte[] clone(byte[] data, byte[] existing)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ if ((existing == null) || (existing.length != data.length))
+ {
+ return clone(data);
+ }
+ System.arraycopy(data, 0, existing, 0, existing.length);
+ return existing;
+ }
+
public static byte[][] clone(byte[][] data)
{
if (data == null)
@@ -470,6 +510,33 @@ public final class Arrays
return copy;
}
+ public static long[] clone(long[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ long[] copy = new long[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+
+ public static long[] clone(long[] data, long[] existing)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ if ((existing == null) || (existing.length != data.length))
+ {
+ return clone(data);
+ }
+ System.arraycopy(data, 0, existing, 0, existing.length);
+ return existing;
+ }
+
public static short[] clone(short[] data)
{
if (data == null)
@@ -576,6 +643,17 @@ public final class Arrays
return tmp;
}
+ /**
+ * Make a copy of a range of bytes from the passed in data array. The range can
+ * extend beyond the end of the input array, in which case the return array will
+ * be padded with zeroes.
+ *
+ * @param data the array from which the data is to be copied.
+ * @param from the start index at which the copying should take place.
+ * @param to the final index of the range (exclusive).
+ *
+ * @return a new byte array containing the range given.
+ */
public static byte[] copyOfRange(byte[] data, int from, int to)
{
int newLength = getLength(from, to);
@@ -660,6 +738,34 @@ public final class Arrays
return newLength;
}
+ public static byte[] append(byte[] a, byte b)
+ {
+ if (a == null)
+ {
+ return new byte[]{ b };
+ }
+
+ int length = a.length;
+ byte[] result = new byte[length + 1];
+ System.arraycopy(a, 0, result, 0, length);
+ result[length] = b;
+ return result;
+ }
+
+ public static int[] append(int[] a, int b)
+ {
+ if (a == null)
+ {
+ return new int[]{ b };
+ }
+
+ int length = a.length;
+ int[] result = new int[length + 1];
+ System.arraycopy(a, 0, result, 0, length);
+ result[length] = b;
+ return result;
+ }
+
public static byte[] concatenate(byte[] a, byte[] b)
{
if (a != null && b != null)
@@ -733,4 +839,18 @@ public final class Arrays
return concatenate(b, c, d);
}
}
+
+ public static byte[] prepend(byte[] a, byte b)
+ {
+ if (a == null)
+ {
+ return new byte[]{ b };
+ }
+
+ int length = a.length;
+ byte[] result = new byte[length + 1];
+ System.arraycopy(a, 0, result, 1, length);
+ result[0] = b;
+ return result;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java b/bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java
index e2fe590..f7f7e68 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java
@@ -40,43 +40,25 @@ public final class BigIntegers
* @param value value to be converted.
* @return a byte array without a leading zero byte if present in the signed encoding.
*/
- public static byte[] asUnsignedByteArray(
- int length,
- BigInteger value)
+ public static byte[] asUnsignedByteArray(int length, BigInteger value)
{
byte[] bytes = value.toByteArray();
-
- if (bytes[0] == 0)
+ if (bytes.length == length)
{
- if (bytes.length - 1 > length)
- {
- throw new IllegalArgumentException("standard length exceeded for value");
- }
-
- byte[] tmp = new byte[length];
-
- System.arraycopy(bytes, 1, tmp, tmp.length - (bytes.length - 1), bytes.length - 1);
-
- return tmp;
+ return bytes;
}
- else
- {
- if (bytes.length == length)
- {
- return bytes;
- }
-
- if (bytes.length > length)
- {
- throw new IllegalArgumentException("standard length exceeded for value");
- }
- byte[] tmp = new byte[length];
+ int start = bytes[0] == 0 ? 1 : 0;
+ int count = bytes.length - start;
- System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length);
-
- return tmp;
+ if (count > length)
+ {
+ throw new IllegalArgumentException("standard length exceeded for value");
}
+
+ byte[] tmp = new byte[length];
+ System.arraycopy(bytes, start, tmp, tmp.length - count, count);
+ return tmp;
}
/**
@@ -120,4 +102,20 @@ public final class BigIntegers
// fall back to a faster (restricted) method
return new BigInteger(max.subtract(min).bitLength() - 1, random).add(min);
}
+
+ public static BigInteger fromUnsignedByteArray(byte[] buf)
+ {
+ return new BigInteger(1, buf);
+ }
+
+ public static BigInteger fromUnsignedByteArray(byte[] buf, int off, int length)
+ {
+ byte[] mag = buf;
+ if (off != 0 || length != buf.length)
+ {
+ mag = new byte[length];
+ System.arraycopy(buf, off, mag, 0, length);
+ }
+ return new BigInteger(1, mag);
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509Store.java b/bcprov/src/main/java/org/bouncycastle/x509/X509Store.java
deleted file mode 100644
index 1bfc00f..0000000
--- a/bcprov/src/main/java/org/bouncycastle/x509/X509Store.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.bouncycastle.x509;
-
-import org.bouncycastle.util.Selector;
-import org.bouncycastle.util.Store;
-
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
-import java.util.Collection;
-
-public class X509Store
- implements Store
-{
- public static X509Store getInstance(String type, X509StoreParameters parameters)
- throws NoSuchStoreException
- {
- try
- {
- X509Util.Implementation impl = X509Util.getImplementation("X509Store", type);
-
- return createStore(impl, parameters);
- }
- catch (NoSuchAlgorithmException e)
- {
- throw new NoSuchStoreException(e.getMessage());
- }
- }
-
- public static X509Store getInstance(String type, X509StoreParameters parameters, String provider)
- throws NoSuchStoreException, NoSuchProviderException
- {
- return getInstance(type, parameters, X509Util.getProvider(provider));
- }
-
- public static X509Store getInstance(String type, X509StoreParameters parameters, Provider provider)
- throws NoSuchStoreException
- {
- try
- {
- X509Util.Implementation impl = X509Util.getImplementation("X509Store", type, provider);
-
- return createStore(impl, parameters);
- }
- catch (NoSuchAlgorithmException e)
- {
- throw new NoSuchStoreException(e.getMessage());
- }
- }
-
- private static X509Store createStore(X509Util.Implementation impl, X509StoreParameters parameters)
- {
- X509StoreSpi spi = (X509StoreSpi)impl.getEngine();
-
- spi.engineInit(parameters);
-
- return new X509Store(impl.getProvider(), spi);
- }
-
- private Provider _provider;
- private X509StoreSpi _spi;
-
- private X509Store(
- Provider provider,
- X509StoreSpi spi)
- {
- _provider = provider;
- _spi = spi;
- }
-
- public Provider getProvider()
- {
- return _provider;
- }
-
- public Collection getMatches(Selector selector)
- {
- return _spi.engineGetMatches(selector);
- }
-}