diff options
author | Sergio Giro <sgiro@google.com> | 2016-02-10 22:30:59 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2016-02-10 22:30:59 +0000 |
commit | 237f783910c9057e92cfd08b9c25e55d9b640ce6 (patch) | |
tree | 2cba8cee6020669038b6603397dbc80dd73aa9ce /bcprov/src/main/java/org/bouncycastle/crypto | |
parent | 013d8784e65adfe3af81f7ff010eddc17c0c332e (diff) | |
parent | f437e150ec9a1d9a61c68cca47bfb9ccaf7252b1 (diff) | |
download | bouncycastle-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')
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? |