summaryrefslogtreecommitdiff
path: root/bcprov/src/main/java/org/bouncycastle/crypto
diff options
context:
space:
mode:
authorSergio Giro <sgiro@google.com>2016-02-10 22:30:59 +0000
committerandroid-build-merger <android-build-merger@google.com>2016-02-10 22:30:59 +0000
commit237f783910c9057e92cfd08b9c25e55d9b640ce6 (patch)
tree2cba8cee6020669038b6603397dbc80dd73aa9ce /bcprov/src/main/java/org/bouncycastle/crypto
parent013d8784e65adfe3af81f7ff010eddc17c0c332e (diff)
parentf437e150ec9a1d9a61c68cca47bfb9ccaf7252b1 (diff)
downloadbouncycastle-237f783910c9057e92cfd08b9c25e55d9b640ce6.tar.gz
Merge "bouncycastle: upgrade to version 1.54"
am: f437e150ec * commit 'f437e150ec9a1d9a61c68cca47bfb9ccaf7252b1': bouncycastle: Android tree with upstream code for version 1.54. bouncycastle: Android tree with upstream code for version 1.54
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/crypto')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java37
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java504
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java32
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java167
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java156
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java120
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java132
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java36
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java177
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/DESedeParameters.java49
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/KDFParameters.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/RC2Parameters.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java59
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java22
22 files changed, 1207 insertions, 381 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
index 39f59da8..8ab2cdc5 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
@@ -115,7 +115,14 @@ public class BufferedBlockCipher
if (pgpCFB)
{
- leftOver = total % buf.length - (cipher.getBlockSize() + 2);
+ if (forEncryption)
+ {
+ leftOver = total % buf.length - (cipher.getBlockSize() + 2);
+ }
+ else
+ {
+ leftOver = total % buf.length;
+ }
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java
index 29692bad..011e97c5 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java
@@ -70,39 +70,44 @@ public abstract class GeneralDigest
int inOff,
int len)
{
+ len = Math.max(0, len);
+
//
// fill the current word
//
- while ((xBufOff != 0) && (len > 0))
+ int i = 0;
+ if (xBufOff != 0)
{
- update(in[inOff]);
-
- inOff++;
- len--;
+ while (i < len)
+ {
+ xBuf[xBufOff++] = in[inOff + i++];
+ if (xBufOff == 4)
+ {
+ processWord(xBuf, 0);
+ xBufOff = 0;
+ break;
+ }
+ }
}
//
// process whole words.
//
- while (len > xBuf.length)
+ int limit = ((len - i) & ~3) + i;
+ for (; i < limit; i += 4)
{
- processWord(in, inOff);
-
- inOff += xBuf.length;
- len -= xBuf.length;
- byteCount += xBuf.length;
+ processWord(in, inOff + i);
}
//
// load in the remainder.
//
- while (len > 0)
+ while (i < len)
{
- update(in[inOff]);
-
- inOff++;
- len--;
+ xBuf[xBufOff++] = in[inOff + i++];
}
+
+ byteCount += len;
}
public void finish()
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java b/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java
index 3b4b2e6e..e3c596d9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java
@@ -3,15 +3,21 @@ package org.bouncycastle.crypto.ec;
import java.math.BigInteger;
import java.util.Enumeration;
import java.util.Hashtable;
+import java.util.Vector;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ECParametersHolder;
+import org.bouncycastle.asn1.x9.X9ECPoint;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
// BEGIN android-removed
// import org.bouncycastle.math.ec.custom.djb.Curve25519;
+// import org.bouncycastle.math.ec.custom.sec.SecP128R1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecP160K1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecP160R1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecP160R2Curve;
// END android-removed
import org.bouncycastle.math.ec.custom.sec.SecP192K1Curve;
import org.bouncycastle.math.ec.custom.sec.SecP192R1Curve;
@@ -21,6 +27,26 @@ import org.bouncycastle.math.ec.custom.sec.SecP256K1Curve;
import org.bouncycastle.math.ec.custom.sec.SecP256R1Curve;
import org.bouncycastle.math.ec.custom.sec.SecP384R1Curve;
import org.bouncycastle.math.ec.custom.sec.SecP521R1Curve;
+// BEGIN android-removed
+// import org.bouncycastle.math.ec.custom.sec.SecT113R1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT113R2Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT131R1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT131R2Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT163K1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT163R1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT163R2Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT193R1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT193R2Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT233K1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT233R1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT239K1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT283K1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT283R1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT409K1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT409R1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT571K1Curve;
+// import org.bouncycastle.math.ec.custom.sec.SecT571R1Curve;
+// END android-removed
import org.bouncycastle.math.ec.endo.GLVTypeBEndomorphism;
import org.bouncycastle.math.ec.endo.GLVTypeBParameters;
import org.bouncycastle.util.Strings;
@@ -44,24 +70,100 @@ public class CustomNamedCurves
// */
// static X9ECParametersHolder curve25519 = new X9ECParametersHolder()
// {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = null;
+ // ECCurve curve = configureCurve(new Curve25519());
+ //
+ // /*
+ // * NOTE: Curve25519 was specified in Montgomery form. Rewriting in Weierstrass form
+ // * involves substitution of variables, so the base-point x coordinate is 9 + (486662 / 3).
+ // *
+ // * The Curve25519 paper doesn't say which of the two possible y values the base
+ // * point has. The choice here is guided by language in the Ed25519 paper.
+ // *
+ // * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14)
+ // */
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A"
+ // + "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"));
+ //
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+ //
+ // /*
+ // * secp128r1
+ // */
+ // static X9ECParametersHolder secp128r1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("000E0D4D696E6768756151750CC03A4473D03679");
+ // ECCurve curve = configureCurve(new SecP128R1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "161FF7528B899B2D0C28607CA52C5B86"
+ // + "CF5AC8395BAFEB13C02DA292DDED7A83"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+ //
+ // /*
+ // * secp160k1
+ // */
+ // static X9ECParametersHolder secp160k1 = new X9ECParametersHolder()
+ // {
// protected X9ECParameters createParameters()
// {
// byte[] S = null;
- // ECCurve curve = configureCurve(new Curve25519());
+ // GLVTypeBParameters glv = new GLVTypeBParameters(
+ // new BigInteger("9ba48cba5ebcb9b6bd33b92830b2a2e0e192f10a", 16),
+ // new BigInteger("c39c6c3b3a36d7701b9c71a1f5804ae5d0003f4", 16),
+ // new BigInteger[]{
+ // new BigInteger("9162fbe73984472a0a9e", 16),
+ // new BigInteger("-96341f1138933bc2f505", 16) },
+ // new BigInteger[]{
+ // new BigInteger("127971af8721782ecffa3", 16),
+ // new BigInteger("9162fbe73984472a0a9e", 16) },
+ // new BigInteger("9162fbe73984472a0a9d0590", 16),
+ // new BigInteger("96341f1138933bc2f503fd44", 16),
+ // 176);
+ // ECCurve curve = configureCurveGLV(new SecP160K1Curve(), glv);
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
+ // + "938CF935318FDCED6BC28286531733C3F03C4FEE"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
//
- // /*
- // * NOTE: Curve25519 was specified in Montgomery form. Rewriting in Weierstrass form
- // * involves substitution of variables, so the base-point x coordinate is 9 + (486662 / 3).
- // *
- // * The Curve25519 paper doesn't say which of the two possible y values the base
- // * point has. The choice here is guided by language in the Ed25519 paper.
- // *
- // * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14)
- // */
- // ECPoint G = curve.decodePoint(Hex.decode("04"
- // + "2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A"
- // + "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"));
+ // /*
+ // * secp160r1
+ // */
+ // static X9ECParametersHolder secp160r1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("1053CDE42C14D696E67687561517533BF3F83345");
+ // ECCurve curve = configureCurve(new SecP160R1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "4A96B5688EF573284664698968C38BB913CBFC82"
+ // + "23A628553168947D59DCC912042351377AC5FB32"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
//
+ // /*
+ // * secp160r2
+ // */
+ // static X9ECParametersHolder secp160r2 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("B99B99B099B323E02709A4D696E6768756151751");
+ // ECCurve curve = configureCurve(new SecP160R2Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "52DCB034293A117E1F4FF11B30F7199D3144CE6D"
+ // + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E"));
// return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
// }
// };
@@ -88,7 +190,7 @@ public class CustomNamedCurves
new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
208);
ECCurve curve = configureCurveGLV(new SecP192K1Curve(), glv);
- ECPoint G = curve.decodePoint(Hex.decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
+ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
@@ -104,7 +206,7 @@ public class CustomNamedCurves
{
byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
ECCurve curve = configureCurve(new SecP192R1Curve());
- ECPoint G = curve.decodePoint(Hex.decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
+ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
@@ -132,7 +234,7 @@ public class CustomNamedCurves
new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
240);
ECCurve curve = configureCurveGLV(new SecP224K1Curve(), glv);
- ECPoint G = curve.decodePoint(Hex.decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
+ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
@@ -148,7 +250,7 @@ public class CustomNamedCurves
{
byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
ECCurve curve = configureCurve(new SecP224R1Curve());
- ECPoint G = curve.decodePoint(Hex.decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
+ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
@@ -176,7 +278,7 @@ public class CustomNamedCurves
new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
272);
ECCurve curve = configureCurveGLV(new SecP256K1Curve(), glv);
- ECPoint G = curve.decodePoint(Hex.decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
+ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
@@ -192,7 +294,7 @@ public class CustomNamedCurves
{
byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90");
ECCurve curve = configureCurve(new SecP256R1Curve());
- ECPoint G = curve.decodePoint(Hex.decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
+ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
@@ -208,7 +310,7 @@ public class CustomNamedCurves
{
byte[] S = Hex.decode("A335926AA319A27A1D00896A6773A4827ACDAC73");
ECCurve curve = configureCurve(new SecP384R1Curve());
- ECPoint G = curve.decodePoint(Hex.decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
+ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
@@ -224,36 +326,338 @@ public class CustomNamedCurves
{
byte[] S = Hex.decode("D09E8800291CB85396CC6717393284AAA0DA64BA");
ECCurve curve = configureCurve(new SecP521R1Curve());
- ECPoint G = curve.decodePoint(Hex.decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
+ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
}
};
+ // BEGIN android-removed
+ // /*
+ // * sect113r1
+ // */
+ // static X9ECParametersHolder sect113r1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("10E723AB14D696E6768756151756FEBF8FCB49A9");
+ // ECCurve curve = configureCurve(new SecT113R1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "009D73616F35F4AB1407D73562C10F"
+ // + "00A52830277958EE84D1315ED31886"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect113r2
+ // */
+ // static X9ECParametersHolder sect113r2 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("10C0FB15760860DEF1EEF4D696E676875615175D");
+ // ECCurve curve = configureCurve(new SecT113R2Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "01A57A6A7B26CA5EF52FCDB8164797"
+ // + "00B3ADC94ED1FE674C06E695BABA1D"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect131r1
+ // */
+ // static X9ECParametersHolder sect131r1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("4D696E676875615175985BD3ADBADA21B43A97E2");
+ // ECCurve curve = configureCurve(new SecT131R1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "0081BAF91FDF9833C40F9C181343638399"
+ // + "078C6E7EA38C001F73C8134B1B4EF9E150"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect131r2
+ // */
+ // static X9ECParametersHolder sect131r2 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("985BD3ADBAD4D696E676875615175A21B43A97E3");
+ // ECCurve curve = configureCurve(new SecT131R2Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "0356DCD8F2F95031AD652D23951BB366A8"
+ // + "0648F06D867940A5366D9E265DE9EB240F"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect163k1
+ // */
+ // static X9ECParametersHolder sect163k1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = null;
+ // ECCurve curve = configureCurve(new SecT163K1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"
+ // + "0289070FB05D38FF58321F2E800536D538CCDAA3D9"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect163r1
+ // */
+ // static X9ECParametersHolder sect163r1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("24B7B137C8A14D696E6768756151756FD0DA2E5C");
+ // ECCurve curve = configureCurve(new SecT163R1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "0369979697AB43897789566789567F787A7876A654"
+ // + "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect163r2
+ // */
+ // static X9ECParametersHolder sect163r2 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("85E25BFE5C86226CDB12016F7553F9D0E693A268");
+ // ECCurve curve = configureCurve(new SecT163R2Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "03F0EBA16286A2D57EA0991168D4994637E8343E36"
+ // + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect193r1
+ // */
+ // static X9ECParametersHolder sect193r1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("103FAEC74D696E676875615175777FC5B191EF30");
+ // ECCurve curve = configureCurve(new SecT193R1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"
+ // + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect193r2
+ // */
+ // static X9ECParametersHolder sect193r2 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("10B7B4D696E676875615175137C8A16FD0DA2211");
+ // ECCurve curve = configureCurve(new SecT193R2Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"
+ // + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect233k1
+ // */
+ // static X9ECParametersHolder sect233k1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = null;
+ // ECCurve curve = configureCurve(new SecT233K1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"
+ // + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect233r1
+ // */
+ // static X9ECParametersHolder sect233r1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("74D59FF07F6B413D0EA14B344B20A2DB049B50C3");
+ // ECCurve curve = configureCurve(new SecT233R1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"
+ // + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect239k1
+ // */
+ // static X9ECParametersHolder sect239k1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = null;
+ // ECCurve curve = configureCurve(new SecT239K1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"
+ // + "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect283k1
+ // */
+ // static X9ECParametersHolder sect283k1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = null;
+ // ECCurve curve = configureCurve(new SecT283K1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"
+ // + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect283r1
+ // */
+ // static X9ECParametersHolder sect283r1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("77E2B07370EB0F832A6DD5B62DFC88CD06BB84BE");
+ // ECCurve curve = configureCurve(new SecT283R1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"
+ // + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect409k1
+ // */
+ // static X9ECParametersHolder sect409k1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = null;
+ // ECCurve curve = configureCurve(new SecT409K1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"
+ // + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect409r1
+ // */
+ // static X9ECParametersHolder sect409r1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("4099B5A457F9D69F79213D094C4BCD4D4262210B");
+ // ECCurve curve = configureCurve(new SecT409R1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"
+ // + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect571k1
+ // */
+ // static X9ECParametersHolder sect571k1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = null;
+ // ECCurve curve = configureCurve(new SecT571K1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"
+ // + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+
+ // /*
+ // * sect571r1
+ // */
+ // static X9ECParametersHolder sect571r1 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = Hex.decode("2AA058F73A0E33AB486B0F610410C53A7F132310");
+ // ECCurve curve = configureCurve(new SecT571R1Curve());
+ // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ // + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"
+ // + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B"));
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+ // END android-removed
+
+
static final Hashtable nameToCurve = new Hashtable();
static final Hashtable nameToOID = new Hashtable();
static final Hashtable oidToCurve = new Hashtable();
static final Hashtable oidToName = new Hashtable();
+ static final Vector names = new Vector();
static void defineCurve(String name, X9ECParametersHolder holder)
{
+ names.addElement(name);
+ name = Strings.toLowerCase(name);
nameToCurve.put(name, holder);
}
static void defineCurveWithOID(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder)
{
- nameToCurve.put(name, holder);
- nameToOID.put(name, oid);
+ names.addElement(name);
oidToName.put(oid, name);
oidToCurve.put(oid, holder);
+ name = Strings.toLowerCase(name);
+ nameToOID.put(name, oid);
+ nameToCurve.put(name, holder);
}
- static void defineCurveAlias(String alias, ASN1ObjectIdentifier oid)
+ static void defineCurveAlias(String name, ASN1ObjectIdentifier oid)
{
- alias = Strings.toLowerCase(alias);
- nameToOID.put(alias, oid);
- nameToCurve.put(alias, oidToCurve.get(oid));
+ Object curve = oidToCurve.get(oid);
+ if (curve == null)
+ {
+ throw new IllegalStateException();
+ }
+
+ name = Strings.toLowerCase(name);
+ nameToOID.put(name, oid);
+ nameToCurve.put(name, curve);
}
static
@@ -262,6 +666,17 @@ public class CustomNamedCurves
// defineCurve("curve25519", curve25519);
// END android-removed
+// defineCurveWithOID("secp112r1", SECObjectIdentifiers.secp112r1, secp112r1);
+// defineCurveWithOID("secp112r2", SECObjectIdentifiers.secp112r2, secp112r2);
+ // BEGIN android-removed
+ // defineCurveWithOID("secp128r1", SECObjectIdentifiers.secp128r1, secp128r1);
+ // END android-removed
+// defineCurveWithOID("secp128r2", SECObjectIdentifiers.secp128r2, secp128r2);
+ // BEGIN android-removed
+ // defineCurveWithOID("secp160k1", SECObjectIdentifiers.secp160k1, secp160k1);
+ // defineCurveWithOID("secp160r1", SECObjectIdentifiers.secp160r1, secp160r1);
+ // defineCurveWithOID("secp160r2", SECObjectIdentifiers.secp160r2, secp160r2);
+ // END android-removed
defineCurveWithOID("secp192k1", SECObjectIdentifiers.secp192k1, secp192k1);
defineCurveWithOID("secp192r1", SECObjectIdentifiers.secp192r1, secp192r1);
defineCurveWithOID("secp224k1", SECObjectIdentifiers.secp224k1, secp224k1);
@@ -271,6 +686,39 @@ public class CustomNamedCurves
defineCurveWithOID("secp384r1", SECObjectIdentifiers.secp384r1, secp384r1);
defineCurveWithOID("secp521r1", SECObjectIdentifiers.secp521r1, secp521r1);
+ // BEGIN android-removed
+ // defineCurveWithOID("sect113r1", SECObjectIdentifiers.sect113r1, sect113r1);
+ // defineCurveWithOID("sect113r2", SECObjectIdentifiers.sect113r2, sect113r2);
+ // defineCurveWithOID("sect131r1", SECObjectIdentifiers.sect131r1, sect131r1);
+ // defineCurveWithOID("sect131r2", SECObjectIdentifiers.sect131r2, sect131r2);
+ // defineCurveWithOID("sect163k1", SECObjectIdentifiers.sect163k1, sect163k1);
+ // defineCurveWithOID("sect163r1", SECObjectIdentifiers.sect163r1, sect163r1);
+ // defineCurveWithOID("sect163r2", SECObjectIdentifiers.sect163r2, sect163r2);
+ // defineCurveWithOID("sect193r1", SECObjectIdentifiers.sect193r1, sect193r1);
+ // defineCurveWithOID("sect193r2", SECObjectIdentifiers.sect193r2, sect193r2);
+ // defineCurveWithOID("sect233k1", SECObjectIdentifiers.sect233k1, sect233k1);
+ // defineCurveWithOID("sect233r1", SECObjectIdentifiers.sect233r1, sect233r1);
+ // defineCurveWithOID("sect239k1", SECObjectIdentifiers.sect239k1, sect239k1);
+ // defineCurveWithOID("sect283k1", SECObjectIdentifiers.sect283k1, sect283k1);
+ // defineCurveWithOID("sect283r1", SECObjectIdentifiers.sect283r1, sect283r1);
+ // defineCurveWithOID("sect409k1", SECObjectIdentifiers.sect409k1, sect409k1);
+ // defineCurveWithOID("sect409r1", SECObjectIdentifiers.sect409r1, sect409r1);
+ // defineCurveWithOID("sect571k1", SECObjectIdentifiers.sect571k1, sect571k1);
+ // defineCurveWithOID("sect571r1", SECObjectIdentifiers.sect571r1, sect571r1);
+
+ // defineCurveAlias("B-163", SECObjectIdentifiers.sect163r2);
+ // defineCurveAlias("B-233", SECObjectIdentifiers.sect233r1);
+ // defineCurveAlias("B-283", SECObjectIdentifiers.sect283r1);
+ // defineCurveAlias("B-409", SECObjectIdentifiers.sect409r1);
+ // defineCurveAlias("B-571", SECObjectIdentifiers.sect571r1);
+
+ // defineCurveAlias("K-163", SECObjectIdentifiers.sect163k1);
+ // defineCurveAlias("K-233", SECObjectIdentifiers.sect233k1);
+ // defineCurveAlias("K-283", SECObjectIdentifiers.sect283k1);
+ // defineCurveAlias("K-409", SECObjectIdentifiers.sect409k1);
+ // defineCurveAlias("K-571", SECObjectIdentifiers.sect571k1);
+ // END android-removed
+
defineCurveAlias("P-192", SECObjectIdentifiers.secp192r1);
defineCurveAlias("P-224", SECObjectIdentifiers.secp224r1);
defineCurveAlias("P-256", SECObjectIdentifiers.secp256r1);
@@ -321,6 +769,6 @@ public class CustomNamedCurves
*/
public static Enumeration getNames()
{
- return nameToCurve.keys();
+ return names.elements();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
index 7ba71c73..71ca7f7d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
@@ -18,15 +18,20 @@ public class PKCS1Encoding
implements AsymmetricBlockCipher
{
/**
+ * @deprecated use NOT_STRICT_LENGTH_ENABLED_PROPERTY
+ */
+ public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.bouncycastle.pkcs1.strict";
+
+ /**
* some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
- * work with one of these set the system property org.bouncycastle.pkcs1.strict to false.
+ * work with one of these set the system property org.bouncycastle.pkcs1.not_strict to true.
* <p>
- * The system property is checked during construction of the encoding object, it is set to
- * true by default.
+ * The system property is checked during construction of the encoding object, it is set to
+ * false by default.
* </p>
*/
- public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.bouncycastle.pkcs1.strict";
-
+ public static final String NOT_STRICT_LENGTH_ENABLED_PROPERTY = "org.bouncycastle.pkcs1.not_strict";
+
private static final int HEADER_LENGTH = 10;
private SecureRandom random;
@@ -97,6 +102,18 @@ public class PKCS1Encoding
return System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY);
}
});
+ String notStrict = (String)AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return System.getProperty(NOT_STRICT_LENGTH_ENABLED_PROPERTY);
+ }
+ });
+
+ if (notStrict != null)
+ {
+ return !notStrict.equals("true");
+ }
return strict == null || strict.equals("true");
}
@@ -121,8 +138,11 @@ public class PKCS1Encoding
}
else
{
- this.random = new SecureRandom();
kParam = (AsymmetricKeyParameter)param;
+ if (!kParam.isPrivate() && forEncryption)
+ {
+ this.random = new SecureRandom();
+ }
}
engine.init(forEncryption, param);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
index a0fd0840..924dff35 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
@@ -5,6 +5,7 @@ import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.util.Pack;
/**
* an implementation of the AES (Rijndael), from FIPS-197.
@@ -230,12 +231,22 @@ private static final int[] Tinv0 =
private static final int m1 = 0x80808080;
private static final int m2 = 0x7f7f7f7f;
private static final int m3 = 0x0000001b;
+ private static final int m4 = 0xC0C0C0C0;
+ private static final int m5 = 0x3f3f3f3f;
private static int FFmulX(int x)
{
return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
}
+ private static int FFmulX2(int x)
+ {
+ int t0 = (x & m5) << 2;
+ int t1 = (x & m4);
+ t1 ^= (t1 >>> 1);
+ return t0 ^ (t1 >>> 2) ^ (t1 >>> 5);
+ }
+
/*
The following defines provide alternative definitions of FFmulX that might
give improved performance if a fast 32-bit multiply is not available.
@@ -248,12 +259,13 @@ private static final int[] Tinv0 =
private static int inv_mcol(int x)
{
- int f2 = FFmulX(x);
- int f4 = FFmulX(f2);
- int f8 = FFmulX(f4);
- int f9 = x ^ f8;
-
- return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
+ int t0, t1;
+ t0 = x;
+ t1 = t0 ^ shift(t0, 8);
+ t0 ^= FFmulX(t1);
+ t1 ^= FFmulX2(t0);
+ t0 ^= t1 ^ shift(t1, 16);
+ return t0;
}
private static int subWord(int x)
@@ -267,59 +279,128 @@ private static final int[] Tinv0 =
* AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
* This code is written assuming those are the only possible values
*/
- private int[][] generateWorkingKey(
- byte[] key,
- boolean forEncryption)
+ private int[][] generateWorkingKey(byte[] key, boolean forEncryption)
{
- int KC = key.length / 4; // key length in words
- int t;
-
- if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length))
+ int keyLen = key.length;
+ if (keyLen < 16 || keyLen > 32 || (keyLen & 7) != 0)
{
throw new IllegalArgumentException("Key length not 128/192/256 bits.");
}
+ int KC = keyLen >>> 2;
ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
int[][] W = new int[ROUNDS+1][4]; // 4 words in a block
-
- //
- // copy the key into the round key array
- //
-
- t = 0;
- int i = 0;
- while (i < key.length)
+
+ switch (KC)
+ {
+ case 4:
+ {
+ int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0;
+ int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1;
+ int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2;
+ int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3;
+
+ for (int i = 1; i <= 10; ++i)
{
- W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24);
- i+=4;
- t++;
+ int u = subWord(shift(t3, 8)) ^ rcon[i - 1];
+ t0 ^= u; W[i][0] = t0;
+ t1 ^= t0; W[i][1] = t1;
+ t2 ^= t1; W[i][2] = t2;
+ t3 ^= t2; W[i][3] = t3;
}
-
- //
- // while not enough round key material calculated
- // calculate new values
- //
- int k = (ROUNDS + 1) << 2;
- for (i = KC; (i < k); i++)
+
+ break;
+ }
+ case 6:
+ {
+ int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0;
+ int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1;
+ int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2;
+ int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3;
+ int t4 = Pack.littleEndianToInt(key, 16); W[1][0] = t4;
+ int t5 = Pack.littleEndianToInt(key, 20); W[1][1] = t5;
+
+ int rcon = 1;
+ int u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1;
+ t0 ^= u; W[1][2] = t0;
+ t1 ^= t0; W[1][3] = t1;
+ t2 ^= t1; W[2][0] = t2;
+ t3 ^= t2; W[2][1] = t3;
+ t4 ^= t3; W[2][2] = t4;
+ t5 ^= t4; W[2][3] = t5;
+
+ for (int i = 3; i < 12; i += 3)
{
- int temp = W[(i-1)>>2][(i-1)&3];
- if ((i % KC) == 0)
- {
- temp = subWord(shift(temp, 8)) ^ rcon[(i / KC)-1];
- }
- else if ((KC > 6) && ((i % KC) == 4))
- {
- temp = subWord(temp);
- }
-
- W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
+ u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1;
+ t0 ^= u; W[i ][0] = t0;
+ t1 ^= t0; W[i ][1] = t1;
+ t2 ^= t1; W[i ][2] = t2;
+ t3 ^= t2; W[i ][3] = t3;
+ t4 ^= t3; W[i + 1][0] = t4;
+ t5 ^= t4; W[i + 1][1] = t5;
+ u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1;
+ t0 ^= u; W[i + 1][2] = t0;
+ t1 ^= t0; W[i + 1][3] = t1;
+ t2 ^= t1; W[i + 2][0] = t2;
+ t3 ^= t2; W[i + 2][1] = t3;
+ t4 ^= t3; W[i + 2][2] = t4;
+ t5 ^= t4; W[i + 2][3] = t5;
}
+ u = subWord(shift(t5, 8)) ^ rcon;
+ t0 ^= u; W[12][0] = t0;
+ t1 ^= t0; W[12][1] = t1;
+ t2 ^= t1; W[12][2] = t2;
+ t3 ^= t2; W[12][3] = t3;
+
+ break;
+ }
+ case 8:
+ {
+ int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0;
+ int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1;
+ int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2;
+ int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3;
+ int t4 = Pack.littleEndianToInt(key, 16); W[1][0] = t4;
+ int t5 = Pack.littleEndianToInt(key, 20); W[1][1] = t5;
+ int t6 = Pack.littleEndianToInt(key, 24); W[1][2] = t6;
+ int t7 = Pack.littleEndianToInt(key, 28); W[1][3] = t7;
+
+ int u, rcon = 1;
+
+ for (int i = 2; i < 14; i += 2)
+ {
+ u = subWord(shift(t7, 8)) ^ rcon; rcon <<= 1;
+ t0 ^= u; W[i ][0] = t0;
+ t1 ^= t0; W[i ][1] = t1;
+ t2 ^= t1; W[i ][2] = t2;
+ t3 ^= t2; W[i ][3] = t3;
+ u = subWord(t3);
+ t4 ^= u; W[i + 1][0] = t4;
+ t5 ^= t4; W[i + 1][1] = t5;
+ t6 ^= t5; W[i + 1][2] = t6;
+ t7 ^= t6; W[i + 1][3] = t7;
+ }
+
+ u = subWord(shift(t7, 8)) ^ rcon;
+ t0 ^= u; W[14][0] = t0;
+ t1 ^= t0; W[14][1] = t1;
+ t2 ^= t1; W[14][2] = t2;
+ t3 ^= t2; W[14][3] = t3;
+
+ break;
+ }
+ default:
+ {
+ throw new IllegalStateException("Should never get here");
+ }
+ }
+
if (!forEncryption)
{
for (int j = 1; j < ROUNDS; j++)
{
- for (i = 0; i < 4; i++)
+ for (int i = 0; i < 4; i++)
{
W[j][i] = inv_mcol(W[j][i]);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java
index e2b00d3a..11e1bce8 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java
@@ -557,12 +557,22 @@ public class AESFastEngine
private static final int m1 = 0x80808080;
private static final int m2 = 0x7f7f7f7f;
private static final int m3 = 0x0000001b;
+ private static final int m4 = 0xC0C0C0C0;
+ private static final int m5 = 0x3f3f3f3f;
private static int FFmulX(int x)
{
return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
}
+ private static int FFmulX2(int x)
+ {
+ int t0 = (x & m5) << 2;
+ int t1 = (x & m4);
+ t1 ^= (t1 >>> 1);
+ return t0 ^ (t1 >>> 2) ^ (t1 >>> 5);
+ }
+
/*
The following defines provide alternative definitions of FFmulX that might
give improved performance if a fast 32-bit multiply is not available.
@@ -575,12 +585,13 @@ public class AESFastEngine
private static int inv_mcol(int x)
{
- int f2 = FFmulX(x);
- int f4 = FFmulX(f2);
- int f8 = FFmulX(f4);
- int f9 = x ^ f8;
-
- return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
+ int t0, t1;
+ t0 = x;
+ t1 = t0 ^ shift(t0, 8);
+ t0 ^= FFmulX(t1);
+ t1 ^= FFmulX2(t0);
+ t0 ^= t1 ^ shift(t1, 16);
+ return t0;
}
private static int subWord(int x)
@@ -596,59 +607,128 @@ public class AESFastEngine
* AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
* This code is written assuming those are the only possible values
*/
- private int[][] generateWorkingKey(
- byte[] key,
- boolean forEncryption)
+ private int[][] generateWorkingKey(byte[] key, boolean forEncryption)
{
- int KC = key.length / 4; // key length in words
- int t;
-
- if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length))
+ int keyLen = key.length;
+ if (keyLen < 16 || keyLen > 32 || (keyLen & 7) != 0)
{
throw new IllegalArgumentException("Key length not 128/192/256 bits.");
}
+ int KC = keyLen >>> 2;
ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
int[][] W = new int[ROUNDS+1][4]; // 4 words in a block
-
- //
- // copy the key into the round key array
- //
-
- t = 0;
- int i = 0;
- while (i < key.length)
+
+ switch (KC)
+ {
+ case 4:
{
- W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24);
- i+=4;
- t++;
+ int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0;
+ int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1;
+ int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2;
+ int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3;
+
+ for (int i = 1; i <= 10; ++i)
+ {
+ int u = subWord(shift(t3, 8)) ^ rcon[i - 1];
+ t0 ^= u; W[i][0] = t0;
+ t1 ^= t0; W[i][1] = t1;
+ t2 ^= t1; W[i][2] = t2;
+ t3 ^= t2; W[i][3] = t3;
+ }
+
+ break;
}
-
- //
- // while not enough round key material calculated
- // calculate new values
- //
- int k = (ROUNDS + 1) << 2;
- for (i = KC; (i < k); i++)
+ case 6:
{
- int temp = W[(i - 1) >> 2][(i - 1) & 3];
- if ((i % KC) == 0)
+ int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0;
+ int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1;
+ int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2;
+ int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3;
+ int t4 = Pack.littleEndianToInt(key, 16); W[1][0] = t4;
+ int t5 = Pack.littleEndianToInt(key, 20); W[1][1] = t5;
+
+ int rcon = 1;
+ int u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1;
+ t0 ^= u; W[1][2] = t0;
+ t1 ^= t0; W[1][3] = t1;
+ t2 ^= t1; W[2][0] = t2;
+ t3 ^= t2; W[2][1] = t3;
+ t4 ^= t3; W[2][2] = t4;
+ t5 ^= t4; W[2][3] = t5;
+
+ for (int i = 3; i < 12; i += 3)
{
- temp = subWord(shift(temp, 8)) ^ rcon[(i / KC) - 1];
+ u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1;
+ t0 ^= u; W[i ][0] = t0;
+ t1 ^= t0; W[i ][1] = t1;
+ t2 ^= t1; W[i ][2] = t2;
+ t3 ^= t2; W[i ][3] = t3;
+ t4 ^= t3; W[i + 1][0] = t4;
+ t5 ^= t4; W[i + 1][1] = t5;
+ u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1;
+ t0 ^= u; W[i + 1][2] = t0;
+ t1 ^= t0; W[i + 1][3] = t1;
+ t2 ^= t1; W[i + 2][0] = t2;
+ t3 ^= t2; W[i + 2][1] = t3;
+ t4 ^= t3; W[i + 2][2] = t4;
+ t5 ^= t4; W[i + 2][3] = t5;
}
- else if ((KC > 6) && ((i % KC) == 4))
+
+ u = subWord(shift(t5, 8)) ^ rcon;
+ t0 ^= u; W[12][0] = t0;
+ t1 ^= t0; W[12][1] = t1;
+ t2 ^= t1; W[12][2] = t2;
+ t3 ^= t2; W[12][3] = t3;
+
+ break;
+ }
+ case 8:
+ {
+ int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0;
+ int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1;
+ int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2;
+ int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3;
+ int t4 = Pack.littleEndianToInt(key, 16); W[1][0] = t4;
+ int t5 = Pack.littleEndianToInt(key, 20); W[1][1] = t5;
+ int t6 = Pack.littleEndianToInt(key, 24); W[1][2] = t6;
+ int t7 = Pack.littleEndianToInt(key, 28); W[1][3] = t7;
+
+ int u, rcon = 1;
+
+ for (int i = 2; i < 14; i += 2)
{
- temp = subWord(temp);
+ u = subWord(shift(t7, 8)) ^ rcon; rcon <<= 1;
+ t0 ^= u; W[i ][0] = t0;
+ t1 ^= t0; W[i ][1] = t1;
+ t2 ^= t1; W[i ][2] = t2;
+ t3 ^= t2; W[i ][3] = t3;
+ u = subWord(t3);
+ t4 ^= u; W[i + 1][0] = t4;
+ t5 ^= t4; W[i + 1][1] = t5;
+ t6 ^= t5; W[i + 1][2] = t6;
+ t7 ^= t6; W[i + 1][3] = t7;
}
- W[i >> 2][i & 3] = W[(i - KC) >> 2][(i - KC) & 3] ^ temp;
+ u = subWord(shift(t7, 8)) ^ rcon;
+ t0 ^= u; W[14][0] = t0;
+ t1 ^= t0; W[14][1] = t1;
+ t2 ^= t1; W[14][2] = t2;
+ t3 ^= t2; W[14][3] = t3;
+
+ break;
+ }
+ default:
+ {
+ throw new IllegalStateException("Should never get here");
+ }
}
if (!forEncryption)
{
for (int j = 1; j < ROUNDS; j++)
{
- for (i = 0; i < 4; i++)
+ for (int i = 0; i < 4; i++)
{
W[j][i] = inv_mcol(W[j][i]);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
index 197b151b..ba75c8d7 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
@@ -17,12 +17,11 @@ import org.bouncycastle.util.Arrays;
/**
* Wrap keys according to
- * <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-smime-key-wrap-01.txt">
- * draft-ietf-smime-key-wrap-01.txt</A>.
+ * <A HREF="https://www.ietf.org/rfc/rfc3217.txt">
+ * RFC 3217</A>.
* <p>
* Note:
* <ul>
- * <li>this is based on a draft, and as such is subject to change - don't use this class for anything requiring long term storage.
* <li>if you are using this to wrap triple-des keys you need to set the
* parity bits on the key and, if it's a two-key triple-des key, pad it
* yourself.
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 c9765bf8..d74e2b3c 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java
@@ -110,6 +110,11 @@ public class RSABlindedEngine
BigInteger rInv = r.modInverse(m);
result = blindedResult.multiply(rInv).mod(m);
+ // defence against Arjen Lenstra’s CRT attack
+ if (!input.equals(result.modPow(e, m)))
+ {
+ throw new IllegalStateException("RSA engine faulty decryption/signing detected");
+ }
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java
index 3cab983d..19a2ecfd 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java
@@ -6,6 +6,8 @@ import org.bouncycastle.crypto.params.DESedeParameters;
public class DESedeKeyGenerator
extends DESKeyGenerator
{
+ private static final int MAX_IT = 20;
+
/**
* initialise the key generator - if strength is set to zero
* the key generated will be 192 bits in size, otherwise
@@ -42,6 +44,7 @@ public class DESedeKeyGenerator
public byte[] generateKey()
{
byte[] newKey = new byte[strength];
+ int count = 0;
do
{
@@ -49,7 +52,12 @@ public class DESedeKeyGenerator
DESedeParameters.setOddParity(newKey);
}
- while (DESedeParameters.isWeakKey(newKey, 0, newKey.length));
+ while (++count < MAX_IT && (DESedeParameters.isWeakKey(newKey, 0, newKey.length) || !DESedeParameters.isRealEDEKey(newKey, 0)));
+
+ if (DESedeParameters.isWeakKey(newKey, 0, newKey.length) || !DESedeParameters.isRealEDEKey(newKey, 0))
+ {
+ throw new IllegalStateException("Unable to generate DES-EDE key");
+ }
return newKey;
}
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 36b41cc7..61b4bea9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
@@ -19,17 +19,17 @@ import org.bouncycastle.util.encoders.Hex;
*/
public class DSAParametersGenerator
{
- private Digest digest;
- private int L, N;
- private int certainty;
- private SecureRandom random;
-
private static final BigInteger ZERO = BigInteger.valueOf(0);
private static final BigInteger ONE = BigInteger.valueOf(1);
private static final BigInteger TWO = BigInteger.valueOf(2);
- private boolean use186_3;
- private int usageIndex;
+ private Digest digest;
+ private int L, N;
+ private int certainty;
+ private int iterations;
+ private SecureRandom random;
+ private boolean use186_3;
+ private int usageIndex;
public DSAParametersGenerator()
{
@@ -55,11 +55,13 @@ public class DSAParametersGenerator
int certainty,
SecureRandom random)
{
- this.use186_3 = false;
this.L = size;
this.N = getDefaultN(size);
this.certainty = certainty;
+ this.iterations = Math.max(getMinimumIterations(L), (certainty + 1) / 2);
this.random = random;
+ this.use186_3 = false;
+ this.usageIndex = -1;
}
/**
@@ -73,13 +75,7 @@ public class DSAParametersGenerator
public void init(
DSAParameterGenerationParameters params)
{
- // TODO Should we enforce the minimum 'certainty' values as per C.3 Table C.1?
- this.use186_3 = true;
- this.L = params.getL();
- this.N = params.getN();
- this.certainty = params.getCertainty();
- this.random = params.getRandom();
- this.usageIndex = params.getUsageIndex();
+ int L = params.getL(), N = params.getN();
if ((L < 1024 || L > 3072) || L % 1024 != 0)
{
@@ -102,6 +98,14 @@ public class DSAParametersGenerator
{
throw new IllegalStateException("Digest output size too small for value of N");
}
+
+ this.L = L;
+ this.N = N;
+ this.certainty = params.getCertainty();
+ this.iterations = Math.max(getMinimumIterations(L), (certainty + 1) / 2);
+ this.random = params.getRandom();
+ this.use186_3 = true;
+ this.usageIndex = params.getUsageIndex();
}
/**
@@ -137,10 +141,10 @@ public class DSAParametersGenerator
{
random.nextBytes(seed);
- hash(digest, seed, part1);
+ hash(digest, seed, part1, 0);
System.arraycopy(seed, 0, part2, 0, seed.length);
inc(part2);
- hash(digest, part2, part2);
+ hash(digest, part2, part2, 0);
for (int i = 0; i != u.length; i++)
{
@@ -152,7 +156,7 @@ public class DSAParametersGenerator
BigInteger q = new BigInteger(1, u);
- if (!q.isProbablePrime(certainty))
+ if (!isProbablePrime(q))
{
continue;
}
@@ -162,18 +166,20 @@ public class DSAParametersGenerator
for (int counter = 0; counter < 4096; ++counter)
{
- for (int k = 0; k < n; k++)
{
- inc(offset);
- hash(digest, offset, part1);
- System.arraycopy(part1, 0, w, w.length - (k + 1) * part1.length, part1.length);
- }
+ for (int k = 1; k <= n; k++)
+ {
+ inc(offset);
+ hash(digest, offset, w, w.length - k * part1.length);
+ }
- inc(offset);
- hash(digest, offset, part1);
- System.arraycopy(part1, part1.length - ((w.length - (n) * part1.length)), w, 0, w.length - n * part1.length);
+ int remaining = w.length - (n * part1.length);
+ inc(offset);
+ hash(digest, offset, part1, 0);
+ System.arraycopy(part1, part1.length - remaining, w, 0, remaining);
- w[0] |= (byte)0x80;
+ w[0] |= (byte)0x80;
+ }
BigInteger x = new BigInteger(1, w);
@@ -186,7 +192,7 @@ public class DSAParametersGenerator
continue;
}
- if (p.isProbablePrime(certainty))
+ if (isProbablePrime(p))
{
BigInteger g = calculateGenerator_FIPS186_2(p, q, random);
@@ -238,6 +244,7 @@ public class DSAParametersGenerator
// 4. b = L - 1 - (n * outlen).
int b = (L - 1) % outlen;
+ byte[] w = new byte[L / 8];
byte[] output = new byte[d.getDigestSize()];
for (;;)
{
@@ -245,16 +252,15 @@ public class DSAParametersGenerator
random.nextBytes(seed);
// 6. U = Hash (domain_parameter_seed) mod 2^(N–1).
- hash(d, seed, output);
+ hash(d, seed, output, 0);
BigInteger U = new BigInteger(1, output).mod(ONE.shiftLeft(N - 1));
// 7. q = 2^(N–1) + U + 1 – ( U mod 2).
- BigInteger q = ONE.shiftLeft(N - 1).add(U).add(ONE).subtract(U.mod(TWO));
+ BigInteger q = U.setBit(0).setBit(N - 1);
// 8. Test whether or not q is prime as specified in Appendix C.3.
- // TODO Review C.3 for primality checking
- if (!q.isProbablePrime(certainty))
+ if (!isProbablePrime(q))
{
// 9. If q is not a prime, then go to step 5.
continue;
@@ -271,24 +277,23 @@ public class DSAParametersGenerator
// 11.1 For j = 0 to n do
// Vj = Hash ((domain_parameter_seed + offset + j) mod 2^seedlen).
// 11.2 W = V0 + (V1 ∗ 2^outlen) + ... + (V^(n–1) ∗ 2^((n–1) ∗ outlen)) + ((Vn mod 2^b) ∗ 2^(n ∗ outlen)).
- // TODO Assemble w as a byte array
- BigInteger W = ZERO;
- for (int j = 0, exp = 0; j <= n; ++j, exp += outlen)
{
- inc(offset);
- hash(d, offset, output);
-
- BigInteger Vj = new BigInteger(1, output);
- if (j == n)
+ for (int j = 1; j <= n; ++j)
{
- Vj = Vj.mod(ONE.shiftLeft(b));
+ inc(offset);
+ hash(d, offset, w, w.length - j * output.length);
}
- W = W.add(Vj.shiftLeft(exp));
+ int remaining = w.length - (n * output.length);
+ inc(offset);
+ hash(d, offset, output, 0);
+ System.arraycopy(output, output.length - remaining, w, 0, remaining);
+
+// 11.3 X = W + 2^(L–1). Comment: 0 ≤ W < 2^(L–1); hence, 2^(L–1) ≤ X < 2^L.
+ w[0] |= (byte)0x80;
}
-// 11.3 X = W + 2^(L–1). Comment: 0 ≤ W < 2L–1; hence, 2L–1 ≤ X < 2L.
- BigInteger X = W.add(ONE.shiftLeft(L - 1));
+ BigInteger X = new BigInteger(1, w);
// 11.4 c = X mod 2q.
BigInteger c = X.mod(q.shiftLeft(1));
@@ -296,15 +301,14 @@ public class DSAParametersGenerator
// 11.5 p = X - (c - 1). Comment: p ≡ 1 (mod 2q).
BigInteger p = X.subtract(c.subtract(ONE));
-// 11.6 If (p < 2^(L - 1)), then go to step 11.9
+// 11.6 If (p < 2^(L-1)), then go to step 11.9
if (p.bitLength() != L)
{
continue;
}
// 11.7 Test whether or not p is prime as specified in Appendix C.3.
- // TODO Review C.3 for primality checking
- if (p.isProbablePrime(certainty))
+ if (isProbablePrime(p))
{
// 11.8 If p is determined to be prime, then return VALID and the values of p, q and
// (optionally) the values of domain_parameter_seed and counter.
@@ -331,6 +335,16 @@ public class DSAParametersGenerator
}
}
+ private boolean isProbablePrime(BigInteger x)
+ {
+ /*
+ * TODO Use Primes class for FIPS 186-4 C.3 primality checking - but it breaks existing
+ * tests using FixedSecureRandom
+ */
+// return !Primes.hasAnySmallFactors(x) && Primes.isMRProbablePrime(x, random, iterations);
+ return x.isProbablePrime(certainty);
+ }
+
private static BigInteger calculateGenerator_FIPS186_3_Unverifiable(BigInteger p, BigInteger q,
SecureRandom r)
{
@@ -354,7 +368,7 @@ public class DSAParametersGenerator
for (int count = 1; count < (1 << 16); ++count)
{
inc(U);
- hash(d, U, w);
+ hash(d, U, w, 0);
BigInteger W = new BigInteger(1, w);
BigInteger g = W.modPow(e, p);
if (g.compareTo(TWO) >= 0)
@@ -366,10 +380,10 @@ public class DSAParametersGenerator
return null;
}
- private static void hash(Digest d, byte[] input, byte[] output)
+ private static void hash(Digest d, byte[] input, byte[] output, int outputPos)
{
d.update(input, 0, input.length);
- d.doFinal(output, 0);
+ d.doFinal(output, outputPos);
}
private static int getDefaultN(int L)
@@ -377,6 +391,12 @@ public class DSAParametersGenerator
return L > 1024 ? 256 : 160;
}
+ private static int getMinimumIterations(int L)
+ {
+ // Values based on FIPS 186-4 C.3 Table C.1
+ return L <= 1024 ? 40 : (48 + 8 * ((L - 1) / 1024));
+ }
+
private static void inc(byte[] buf)
{
for (int i = buf.length - 1; i >= 0; --i)
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 4f46a38d..c7660719 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
@@ -56,12 +56,6 @@ public class ECKeyPairGenerator
continue;
}
- /*
- * Require a minimum weight of the NAF representation, since low-weight primes may be
- * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
- *
- * See "The number field sieve for integers of low weight", Oliver Schirokauer.
- */
if (WNafUtil.getNafWeight(d) < minWeight)
{
continue;
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 082a1c8a..9a2239e2 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
@@ -10,6 +10,7 @@ import org.bouncycastle.crypto.digests.AndroidDigestFactory;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.util.Arrays;
/**
* Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 2.
@@ -116,7 +117,7 @@ public class PKCS5S2ParametersGenerator
{
keySize = keySize / 8;
- byte[] dKey = generateDerivedKey(keySize);
+ byte[] dKey = Arrays.copyOfRange(generateDerivedKey(keySize), 0, keySize);
return new KeyParameter(dKey, 0, keySize);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
index 7277045e..f23f654b 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
@@ -8,6 +8,7 @@ import org.bouncycastle.crypto.KeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.bouncycastle.math.Primes;
import org.bouncycastle.math.ec.WNafUtil;
/**
@@ -19,10 +20,12 @@ public class RSAKeyPairGenerator
private static final BigInteger ONE = BigInteger.valueOf(1);
private RSAKeyGenerationParameters param;
+ private int iterations;
public void init(KeyGenerationParameters param)
{
this.param = (RSAKeyGenerationParameters)param;
+ this.iterations = getNumberOfIterations(this.param.getStrength(), this.param.getCertainty());
}
public AsymmetricCipherKeyPair generateKeyPair()
@@ -30,36 +33,46 @@ public class RSAKeyPairGenerator
AsymmetricCipherKeyPair result = null;
boolean done = false;
- while (!done)
+ //
+ // p and q values should have a length of half the strength in bits
+ //
+ int strength = param.getStrength();
+ int pbitlength = (strength + 1) / 2;
+ int qbitlength = strength - pbitlength;
+ int mindiffbits = (strength / 2) - 100;
+
+ if (mindiffbits < strength / 3)
{
- BigInteger p, q, n, d, e, pSub1, qSub1, phi, lcm, dLowerBound;
+ mindiffbits = strength / 3;
+ }
- //
- // p and q values should have a length of half the strength in bits
- //
- int strength = param.getStrength();
- int pbitlength = (strength + 1) / 2;
- int qbitlength = strength - pbitlength;
- int mindiffbits = strength / 3;
- int minWeight = strength >> 2;
+ int minWeight = strength >> 2;
- e = param.getPublicExponent();
+ // d lower bound is 2^(strength / 2)
+ BigInteger dLowerBound = BigInteger.valueOf(2).pow(strength / 2);
+ // squared bound (sqrt(2)*2^(nlen/2-1))^2
+ BigInteger squaredBound = ONE.shiftLeft(strength - 1);
+ // 2^(nlen/2 - 100)
+ BigInteger minDiff = ONE.shiftLeft(mindiffbits);
- // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes)
- // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm")
+ while (!done)
+ {
+ BigInteger p, q, n, d, e, pSub1, qSub1, gcd, lcm;
- p = chooseRandomPrime(pbitlength, e);
+ e = param.getPublicExponent();
+
+ p = chooseRandomPrime(pbitlength, e, squaredBound);
//
// generate a modulus of the required length
//
- for (;;)
+ for (; ; )
{
- q = chooseRandomPrime(qbitlength, e);
+ q = chooseRandomPrime(qbitlength, e, squaredBound);
// p and q should not be too close together (or equal!)
BigInteger diff = q.subtract(p).abs();
- if (diff.bitLength() < mindiffbits)
+ if (diff.bitLength() < mindiffbits || diff.compareTo(minDiff) <= 0)
{
continue;
}
@@ -80,14 +93,14 @@ public class RSAKeyPairGenerator
}
/*
- * Require a minimum weight of the NAF representation, since low-weight composites may
+ * Require a minimum weight of the NAF representation, since low-weight composites may
* be weak against a version of the number-field-sieve for factoring.
*
* See "The number field sieve for integers of low weight", Oliver Schirokauer.
*/
if (WNafUtil.getNafWeight(n) < minWeight)
{
- p = chooseRandomPrime(pbitlength, e);
+ p = chooseRandomPrime(pbitlength, e, squaredBound);
continue;
}
@@ -96,26 +109,22 @@ public class RSAKeyPairGenerator
if (p.compareTo(q) < 0)
{
- phi = p;
+ gcd = p;
p = q;
- q = phi;
+ q = gcd;
}
pSub1 = p.subtract(ONE);
qSub1 = q.subtract(ONE);
- phi = pSub1.multiply(qSub1);
- lcm = phi.divide(pSub1.gcd(qSub1));
+ gcd = pSub1.gcd(qSub1);
+ lcm = pSub1.divide(gcd).multiply(qSub1);
//
// calculate the private exponent
//
d = e.modInverse(lcm);
- // if d is less than or equal to dLowerBound, we need to start over
- // also, for backward compatibility, if d is not the same as
- // e.modInverse(phi), we need to start over
-
- if (d.bitLength() <= qbitlength || !d.equals(e.modInverse(phi)))
+ if (d.compareTo(dLowerBound) <= 0)
{
continue;
}
@@ -143,33 +152,80 @@ public class RSAKeyPairGenerator
/**
* Choose a random prime value for use with RSA
- *
+ *
* @param bitlength the bit-length of the returned prime
- * @param e the RSA public exponent
- * @return a prime p, with (p-1) relatively prime to e
+ * @param e the RSA public exponent
+ * @return A prime p, with (p-1) relatively prime to e
*/
- protected BigInteger chooseRandomPrime(int bitlength, BigInteger e)
+ protected BigInteger chooseRandomPrime(int bitlength, BigInteger e, BigInteger sqrdBound)
{
- for (;;)
+ for (int i = 0; i != 5 * bitlength; i++)
{
BigInteger p = new BigInteger(bitlength, 1, param.getRandom());
-
+
if (p.mod(e).equals(ONE))
{
continue;
}
-
- if (!p.isProbablePrime(param.getCertainty()))
+
+ if (p.multiply(p).compareTo(sqrdBound) < 0)
+ {
+ continue;
+ }
+
+ if (!isProbablePrime(p))
{
continue;
}
- if (!e.gcd(p.subtract(ONE)).equals(ONE))
+ if (!e.gcd(p.subtract(ONE)).equals(ONE))
{
continue;
}
-
+
return p;
}
+
+ throw new IllegalStateException("unable to generate prime number for RSA key");
+ }
+
+ protected boolean isProbablePrime(BigInteger x)
+ {
+ /*
+ * Primes class for FIPS 186-4 C.3 primality checking
+ */
+ return !Primes.hasAnySmallFactors(x) && Primes.isMRProbablePrime(x, param.getRandom(), iterations);
+ }
+
+ private static int getNumberOfIterations(int bits, int certainty)
+ {
+ /*
+ * NOTE: We enforce a minimum 'certainty' of 100 for bits >= 1024 (else 80). Where the
+ * certainty is higher than the FIPS 186-4 tables (C.2/C.3) cater to, extra iterations
+ * are added at the "worst case rate" for the excess.
+ */
+ if (bits >= 1536)
+ {
+ return certainty <= 100 ? 3
+ : certainty <= 128 ? 4
+ : 4 + (certainty - 128 + 1) / 2;
+ }
+ else if (bits >= 1024)
+ {
+ return certainty <= 100 ? 4
+ : certainty <= 112 ? 5
+ : 5 + (certainty - 112 + 1) / 2;
+ }
+ else if (bits >= 512)
+ {
+ return certainty <= 80 ? 5
+ : certainty <= 100 ? 7
+ : 7 + (certainty - 100 + 1) / 2;
+ }
+ else
+ {
+ return certainty <= 80 ? 40
+ : 40 + (certainty - 80 + 1) / 2;
+ }
}
}
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 7f870ca2..088c7283 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
@@ -87,7 +87,7 @@ public class CCMBlockCipher
}
else
{
- throw new IllegalArgumentException("invalid parameters passed to CCM");
+ throw new IllegalArgumentException("invalid parameters passed to CCM: " + params.getClass().getName());
}
// NOTE: Very basic support for key re-use, but no performance gain from it
@@ -277,7 +277,9 @@ public class CCMBlockCipher
calculateMac(in, inOff, inLen, macBlock);
- ctrCipher.processBlock(macBlock, 0, macBlock, 0); // S0
+ byte[] encMac = new byte[blockSize];
+
+ ctrCipher.processBlock(macBlock, 0, encMac, 0); // S0
while (inIndex < (inOff + inLen - blockSize)) // S1...
{
@@ -294,7 +296,7 @@ public class CCMBlockCipher
System.arraycopy(block, 0, output, outIndex, inLen + inOff - inIndex);
- System.arraycopy(macBlock, 0, output, outOff + inLen, macSize);
+ System.arraycopy(encMac, 0, output, outOff + inLen, macSize);
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
index 9e8c3c30..ed89ef7d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
@@ -362,21 +362,30 @@ public class GCMBlockCipher
}
int extra = bufOff;
- if (!forEncryption)
+
+ if (forEncryption)
+ {
+ if (out.length < (outOff + extra + macSize))
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
+ }
+ else
{
if (extra < macSize)
{
throw new InvalidCipherTextException("data too short");
}
extra -= macSize;
- }
- if (extra > 0)
- {
if (out.length < (outOff + extra))
{
throw new OutputLengthException("Output buffer too short");
}
+ }
+
+ if (extra > 0)
+ {
gCTRPartial(bufBlock, 0, extra, out, outOff);
}
@@ -442,10 +451,6 @@ public class GCMBlockCipher
if (forEncryption)
{
- if (out.length < (outOff + extra + macSize))
- {
- throw new OutputLengthException("Output buffer too short");
- }
// Append T to the message
System.arraycopy(macBlock, 0, out, outOff + bufOff, macSize);
resultLen += macSize;
@@ -550,16 +555,11 @@ public class GCMBlockCipher
private byte[] getNextCounterBlock()
{
- for (int i = 15; i >= 12; --i)
- {
- byte b = (byte)((counter[i] + 1) & 0xff);
- counter[i] = b;
-
- if (b != 0)
- {
- break;
- }
- }
+ int c = 1;
+ c += counter[15] & 0xFF; counter[15] = (byte)c; c >>>= 8;
+ c += counter[14] & 0xFF; counter[14] = (byte)c; c >>>= 8;
+ c += counter[13] & 0xFF; counter[13] = (byte)c; c >>>= 8;
+ c += counter[12] & 0xFF; counter[12] = (byte)c;
byte[] tmp = new byte[BLOCK_SIZE];
// TODO Sure would be nice if ciphers could operate on int[]
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
index fbc8bf45..ae4256f6 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
@@ -6,6 +6,7 @@ import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.SkippingStreamCipher;
import org.bouncycastle.crypto.StreamBlockCipher;
import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Pack;
/**
@@ -18,7 +19,7 @@ public class SICBlockCipher
{
private final BlockCipher cipher;
private final int blockSize;
-
+
private byte[] IV;
private byte[] counter;
private byte[] counterOut;
@@ -49,8 +50,19 @@ public class SICBlockCipher
if (params instanceof ParametersWithIV)
{
ParametersWithIV ivParam = (ParametersWithIV)params;
- byte[] iv = ivParam.getIV();
- System.arraycopy(iv, 0, IV, 0, IV.length);
+ this.IV = Arrays.clone(ivParam.getIV());
+
+ if (blockSize < IV.length)
+ {
+ throw new IllegalArgumentException("CTR/SIC mode requires IV no greater than: " + blockSize + " bytes.");
+ }
+
+ int maxCounterSize = (8 > blockSize / 2) ? blockSize / 2 : 8;
+
+ if (blockSize - IV.length > maxCounterSize)
+ {
+ throw new IllegalArgumentException("CTR/SIC mode requires IV of at least: " + (blockSize - maxCounterSize) + " bytes.");
+ }
// if null it's an IV changed only.
if (ivParam.getParameters() != null)
@@ -62,7 +74,7 @@ public class SICBlockCipher
}
else
{
- throw new IllegalArgumentException("SIC mode requires ParametersWithIV");
+ throw new IllegalArgumentException("CTR/SIC mode requires ParametersWithIV");
}
}
@@ -100,94 +112,63 @@ public class SICBlockCipher
{
byteCount = 0;
- incrementCounter();
+ incrementCounterAt(0);
+
+ checkCounter();
}
return rv;
}
- private void incrementCounterPow2(int pow2Div8)
+ private void checkCounter()
{
- // increment counter by 1 << 8 * pow2Div8
- for (int i = counter.length - (1 + pow2Div8); i >= 0 && ++counter[i] == 0; i--)
- {
- ; // do nothing - pre-increment and test for 0 in counter does the job.
- }
- }
-
- private void incrementCounter(int offSet)
- {
- byte old = counter[counter.length - 1];
-
- counter[counter.length - 1] += offSet;
-
- if (old != 0 && counter[counter.length - 1] < old)
+ // if the IV is the same as the blocksize we assume the user knows what they are doing
+ if (IV.length < blockSize)
{
- incrementCounterPow2(1);
+ for (int i = 0; i != IV.length; i++)
+ {
+ if (counter[i] != IV[i])
+ {
+ throw new IllegalStateException("Counter in CTR/SIC mode out of range.");
+ }
+ }
}
}
- private void incrementCounter()
+ private void incrementCounterAt(int pos)
{
- // increment counter by 1.
- for (int i = counter.length - 1; i >= 0 && ++counter[i] == 0; i--)
+ int i = counter.length - pos;
+ while (--i >= 0)
{
- ; // do nothing - pre-increment and test for 0 in counter does the job.
+ if (++counter[i] != 0)
+ {
+ break;
+ }
}
}
- private void decrementCounterPow2(int pow2Div8)
+ private void incrementCounter(int offSet)
{
- if (counter[pow2Div8] == 0)
- {
- boolean nonZero = false;
-
- for (int i = counter.length - (1 + pow2Div8); i > 0; i--)
- {
- if (counter[i] != 0)
- {
- nonZero = true;
- }
- }
+ byte old = counter[counter.length - 1];
- if (!nonZero)
- {
- throw new IllegalStateException("attempt to reduce counter past zero.");
- }
- }
+ counter[counter.length - 1] += offSet;
- // decrement counter by 1.
- for (int i = counter.length - (1 + pow2Div8); i >= 0 && --counter[i] == -1; i--)
+ if (old != 0 && counter[counter.length - 1] < old)
{
- ;
+ incrementCounterAt(1);
}
}
- private void decrementCounter()
+ private void decrementCounterAt(int pos)
{
- if (counter[0] == 0)
+ int i = counter.length - pos;
+ while (--i >= 0)
{
- boolean nonZero = false;
-
- for (int i = counter.length - 1; i > 0; i--)
- {
- if (counter[i] != 0)
- {
- nonZero = true;
- }
- }
-
- if (!nonZero)
+ if (--counter[i] != -1)
{
- throw new IllegalStateException("attempt to reduce counter past zero.");
+ return;
}
}
-
- // decrement counter by 1.
- for (int i = counter.length - 1; i >= 0 && --counter[i] == -1; i--)
- {
- ;
- }
}
private void adjustCounter(long n)
@@ -196,62 +177,45 @@ public class SICBlockCipher
{
long numBlocks = (n + byteCount) / blockSize;
- if (numBlocks > 255)
+ long rem = numBlocks;
+ if (rem > 255)
{
- long gap = numBlocks;
-
for (int i = 5; i >= 1; i--)
{
long diff = 1L << (8 * i);
-
- while (gap >= diff)
+ while (rem >= diff)
{
- incrementCounterPow2(i);
-
- gap -= diff;
+ incrementCounterAt(i);
+ rem -= diff;
}
}
-
- incrementCounter((int)gap);
- }
- else
- {
- incrementCounter((int)numBlocks);
}
+ incrementCounter((int)rem);
+
byteCount = (int)((n + byteCount) - (blockSize * numBlocks));
}
else
{
long numBlocks = (-n - byteCount) / blockSize;
- if (numBlocks > 255)
+ long rem = numBlocks;
+ if (rem > 255)
{
- long gap = numBlocks;
-
for (int i = 5; i >= 1; i--)
{
long diff = 1L << (8 * i);
-
- while (gap > diff)
+ while (rem > diff)
{
- decrementCounterPow2(i);
-
- gap -= diff;
+ decrementCounterAt(i);
+ rem -= diff;
}
}
-
- for (long i = 0; i != gap; i++)
- {
- decrementCounter();
- }
}
- else
+
+ for (long i = 0; i != rem; i++)
{
- for (long i = 0; i != numBlocks; i++)
- {
- decrementCounter();
- }
+ decrementCounterAt(0);
}
int gap = (int)(byteCount + n + (blockSize * numBlocks));
@@ -262,7 +226,7 @@ public class SICBlockCipher
}
else
{
- decrementCounter();
+ decrementCounterAt(0);
byteCount = blockSize + gap;
}
}
@@ -270,7 +234,8 @@ public class SICBlockCipher
public void reset()
{
- System.arraycopy(IV, 0, counter, 0, counter.length);
+ Arrays.fill(counter, (byte)0);
+ System.arraycopy(IV, 0, counter, 0, IV.length);
cipher.reset();
this.byteCount = 0;
}
@@ -279,6 +244,8 @@ public class SICBlockCipher
{
adjustCounter(numberOfBytes);
+ checkCounter();
+
cipher.processBlock(counter, 0, counterOut, 0);
return numberOfBytes;
@@ -293,13 +260,21 @@ public class SICBlockCipher
public long getPosition()
{
- byte[] res = new byte[IV.length];
+ byte[] res = new byte[counter.length];
System.arraycopy(counter, 0, res, 0, res.length);
for (int i = res.length - 1; i >= 1; i--)
{
- int v = (res[i] & 0xff) - (IV[i] & 0xff);
+ int v;
+ if (i < IV.length)
+ {
+ v = (res[i] & 0xff) - (IV[i] & 0xff);
+ }
+ else
+ {
+ v = (res[i] & 0xff);
+ }
if (v < 0)
{
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 58f40788..f08f71f3 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
@@ -123,9 +123,9 @@ public abstract class GCMUtil
r13 ^= (r03 & m1);
int m2 = (r03 << 31) >> 8;
- r03 = (r03 >>> 1) | (r02 << 63);
- r02 = (r02 >>> 1) | (r01 << 63);
- r01 = (r01 >>> 1) | (r00 << 63);
+ r03 = (r03 >>> 1) | (r02 << 31);
+ r02 = (r02 >>> 1) | (r01 << 31);
+ r01 = (r01 >>> 1) | (r00 << 31);
r00 = (r00 >>> 1) ^ (m2 & E1);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/DESedeParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/DESedeParameters.java
index 3a4bbfca..5b2d0d46 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/DESedeParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/DESedeParameters.java
@@ -54,4 +54,53 @@ public class DESedeParameters
{
return isWeakKey(key, offset, key.length - offset);
}
+
+ /**
+ * return true if the passed in key is a real 2/3 part DES-EDE key.
+ *
+ * @param key bytes making up the key
+ * @param offset offset into the byte array the key starts at
+ */
+ public static boolean isRealEDEKey(byte[] key, int offset)
+ {
+ return key.length == 16 ? isReal2Key(key, offset) : isReal3Key(key, offset);
+ }
+
+ /**
+ * return true if the passed in key is a real 2 part DES-EDE key.
+ *
+ * @param key bytes making up the key
+ * @param offset offset into the byte array the key starts at
+ */
+ public static boolean isReal2Key(byte[] key, int offset)
+ {
+ boolean isValid = false;
+ for (int i = offset; i != offset + 8; i++)
+ {
+ if (key[i] != key[i + 8])
+ {
+ isValid = true;
+ }
+ }
+
+ return isValid;
+ }
+
+ /**
+ * return true if the passed in key is a real 3 part DES-EDE key.
+ *
+ * @param key bytes making up the key
+ * @param offset offset into the byte array the key starts at
+ */
+ public static boolean isReal3Key(byte[] key, int offset)
+ {
+ boolean diff12 = false, diff13 = false, diff23 = false;
+ for (int i = offset; i != offset + 8; i++)
+ {
+ diff12 |= (key[i] != key[i + 8]);
+ diff13 |= (key[i] != key[i + 16]);
+ diff23 |= (key[i + 8] != key[i + 16]);
+ }
+ return diff12 && diff13 && diff23;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFParameters.java
new file mode 100644
index 00000000..f3bac647
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFParameters.java
@@ -0,0 +1,31 @@
+package org.bouncycastle.crypto.params;
+
+import org.bouncycastle.crypto.DerivationParameters;
+
+/**
+ * parameters for Key derivation functions for IEEE P1363a
+ */
+public class KDFParameters
+ implements DerivationParameters
+{
+ byte[] iv;
+ byte[] shared;
+
+ public KDFParameters(
+ byte[] shared,
+ byte[] iv)
+ {
+ this.shared = shared;
+ this.iv = iv;
+ }
+
+ public byte[] getSharedSecret()
+ {
+ return shared;
+ }
+
+ public byte[] getIV()
+ {
+ return iv;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/RC2Parameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/RC2Parameters.java
index dc33ec5b..ea98de2c 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/RC2Parameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/RC2Parameters.java
@@ -1,11 +1,8 @@
package org.bouncycastle.crypto.params;
-import org.bouncycastle.crypto.CipherParameters;
-
public class RC2Parameters
- implements CipherParameters
+ extends KeyParameter
{
- private byte[] key;
private int bits;
public RC2Parameters(
@@ -18,15 +15,8 @@ public class RC2Parameters
byte[] key,
int bits)
{
- this.key = new byte[key.length];
+ super(key);
this.bits = bits;
-
- System.arraycopy(key, 0, this.key, 0, key.length);
- }
-
- public byte[] getKey()
- {
- return key;
}
public int getEffectiveKeyBits()
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 5fce1121..adb2558a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
@@ -12,6 +12,8 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECConstants;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
@@ -159,7 +161,7 @@ public class ECDSASigner
ECPoint G = ec.getG();
ECPoint Q = ((ECPublicKeyParameters)key).getQ();
- ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2).normalize();
+ ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2);
// components must be bogus.
if (point.isInfinity())
@@ -167,8 +169,44 @@ public class ECDSASigner
return false;
}
- BigInteger v = point.getAffineXCoord().toBigInteger().mod(n);
+ /*
+ * If possible, avoid normalizing the point (to save a modular inversion in the curve field).
+ *
+ * There are ~cofactor elements of the curve field that reduce (modulo the group order) to 'r'.
+ * If the cofactor is known and small, we generate those possible field values and project each
+ * of them to the same "denominator" (depending on the particular projective coordinates in use)
+ * as the calculated point.X. If any of the projected values matches point.X, then we have:
+ * (point.X / Denominator mod p) mod n == r
+ * as required, and verification succeeds.
+ *
+ * Based on an original idea by Gregory Maxwell (https://github.com/gmaxwell), as implemented in
+ * the libsecp256k1 project (https://github.com/bitcoin/secp256k1).
+ */
+ ECCurve curve = point.getCurve();
+ if (curve != null)
+ {
+ BigInteger cofactor = curve.getCofactor();
+ if (cofactor != null && cofactor.compareTo(EIGHT) <= 0)
+ {
+ ECFieldElement D = getDenominator(curve.getCoordinateSystem(), point);
+ if (D != null && !D.isZero())
+ {
+ ECFieldElement X = point.getXCoord();
+ while (curve.isValidFieldElement(r))
+ {
+ ECFieldElement R = curve.fromBigInteger(r).multiply(D);
+ if (R.equals(X))
+ {
+ return true;
+ }
+ r = r.add(n);
+ }
+ return false;
+ }
+ }
+ }
+ BigInteger v = point.normalize().getAffineXCoord().toBigInteger().mod(n);
return v.equals(r);
}
@@ -190,6 +228,23 @@ public class ECDSASigner
return new FixedPointCombMultiplier();
}
+ protected ECFieldElement getDenominator(int coordinateSystem, ECPoint p)
+ {
+ switch (coordinateSystem)
+ {
+ case ECCurve.COORD_HOMOGENEOUS:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ case ECCurve.COORD_SKEWED:
+ return p.getZCoord(0);
+ case ECCurve.COORD_JACOBIAN:
+ case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ return p.getZCoord(0).square();
+ default:
+ return null;
+ }
+ }
+
protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
{
return !needed ? null : (provided != null) ? provided : new SecureRandom();
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 2b333213..042c68ef 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
@@ -22,10 +22,10 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
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.DomainParameters;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
+import org.bouncycastle.asn1.x9.ValidationParams;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ECPoint;
@@ -98,26 +98,26 @@ public class PublicKeyFactory
{
DHPublicKey dhPublicKey = DHPublicKey.getInstance(keyInfo.parsePublicKey());
- BigInteger y = dhPublicKey.getY().getValue();
+ BigInteger y = dhPublicKey.getY();
- DHDomainParameters dhParams = DHDomainParameters.getInstance(algId.getParameters());
+ DomainParameters dhParams = DomainParameters.getInstance(algId.getParameters());
- BigInteger p = dhParams.getP().getValue();
- BigInteger g = dhParams.getG().getValue();
- BigInteger q = dhParams.getQ().getValue();
+ BigInteger p = dhParams.getP();
+ BigInteger g = dhParams.getG();
+ BigInteger q = dhParams.getQ();
BigInteger j = null;
if (dhParams.getJ() != null)
{
- j = dhParams.getJ().getValue();
+ j = dhParams.getJ();
}
DHValidationParameters validation = null;
- DHValidationParms dhValidationParms = dhParams.getValidationParms();
+ ValidationParams dhValidationParms = dhParams.getValidationParams();
if (dhValidationParms != null)
{
- byte[] seed = dhValidationParms.getSeed().getBytes();
- BigInteger pgenCounter = dhValidationParms.getPgenCounter().getValue();
+ byte[] seed = dhValidationParms.getSeed();
+ BigInteger pgenCounter = dhValidationParms.getPgenCounter();
// TODO Check pgenCounter size?