diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2013-09-26 10:58:25 +0400 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2013-09-26 10:58:25 +0400 |
commit | 38d23e8f9a09b3566e64cef693e8010cee0d8b50 (patch) | |
tree | 3cf2ecec6d40a0b588e1975b3f679d6334e130ea /core/src/main/java/org/bouncycastle/math | |
parent | 26eddcac79c0923ded7d31f76e6d420b59d0eac5 (diff) |
EC multipliers now extend a base class AbstractECMultiplier that takes
care of negatives, zeroes, and infinity points
Access to EC points' precomputation info is now via their curve
Diffstat (limited to 'core/src/main/java/org/bouncycastle/math')
15 files changed, 110 insertions, 117 deletions
diff --git a/core/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java new file mode 100644 index 00000000..69ab7972 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java @@ -0,0 +1,20 @@ +package org.bouncycastle.math.ec; + +import java.math.BigInteger; + +public abstract class AbstractECMultiplier implements ECMultiplier +{ + public ECPoint multiply(ECPoint p, BigInteger k) + { + int sign = k.signum(); + if (sign == 0 || p.isInfinity()) + { + return p.getCurve().getInfinity(); + } + + ECPoint positive = multiplyPositive(p, k.abs()); + return sign > 0 ? positive : positive.negate(); + } + + protected abstract ECPoint multiplyPositive(ECPoint p, BigInteger k); +} diff --git a/core/src/main/java/org/bouncycastle/math/ec/DoubleAddMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/DoubleAddMultiplier.java index 80f1d78d..657a03f9 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/DoubleAddMultiplier.java +++ b/core/src/main/java/org/bouncycastle/math/ec/DoubleAddMultiplier.java @@ -2,22 +2,24 @@ package org.bouncycastle.math.ec; import java.math.BigInteger; -public class DoubleAddMultiplier implements ECMultiplier +public class DoubleAddMultiplier extends AbstractECMultiplier { /** * Joye's double-add algorithm. */ - public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) + protected ECPoint multiplyPositive(ECPoint p, BigInteger k) { ECPoint[] R = new ECPoint[]{ p.getCurve().getInfinity(), p }; + BigInteger bits = k; int n = k.bitLength(); for (int i = 0; i < n; ++i) { - int b = k.testBit(i) ? 1 : 0; + int b = bits.testBit(i) ? 1 : 0; int bp = 1 - b; R[bp] = R[bp].twicePlus(R[b]); } + return R[0]; } } diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java b/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java index d5140749..791a1e7c 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java +++ b/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java @@ -86,6 +86,28 @@ public abstract class ECCurve */ public abstract ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression); + public PreCompInfo getPreCompInfo(ECPoint p) + { + checkPoint(p); + return p.preCompInfo; + } + + /** + * Sets the <code>PreCompInfo</code> for a point on this curve. Used by + * <code>ECMultiplier</code>s to save the precomputation for this <code>ECPoint</code> for use + * by subsequent multiplication. + * + * @param point + * The <code>ECPoint</code> to store precomputations for. + * @param preCompInfo + * The values precomputed by the <code>ECMultiplier</code>. + */ + public void setPreCompInfo(ECPoint point, PreCompInfo preCompInfo) + { + checkPoint(point); + point.preCompInfo = preCompInfo; + } + public ECPoint importPoint(ECPoint p) { if (this == p.getCurve()) @@ -209,6 +231,14 @@ public abstract class ECCurve return p; } + protected void checkPoint(ECPoint point) + { + if (null == point || (this != point.getCurve())) + { + throw new IllegalArgumentException("'point' must be non-null and on this curve"); + } + } + protected void checkPoints(ECPoint[] points) { if (points == null) @@ -218,11 +248,7 @@ public abstract class ECCurve for (int i = 0; i < points.length; ++i) { - ECPoint point = points[i]; - if (null == point || (this != point.getCurve())) - { - throw new IllegalArgumentException("elements of 'points' must be non-null points on this curve instance"); - } + checkPoint(points[i]); } } diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java index ef4e9fd1..da1013a7 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java +++ b/core/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java @@ -12,8 +12,8 @@ public interface ECMultiplier * Multiplies the <code>ECPoint p</code> by <code>k</code>, i.e. * <code>p</code> is added <code>k</code> times to itself. * @param p The <code>ECPoint</code> to be multiplied. - * @param k The factor by which <code>p</code> i multiplied. + * @param k The factor by which <code>p</code> is multiplied. * @return <code>p</code> multiplied by <code>k</code>. */ - ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo); + ECPoint multiply(ECPoint p, BigInteger k); } diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java b/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java index 02be3c2f..3f70114b 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java +++ b/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java @@ -219,18 +219,6 @@ public abstract class ECPoint return x.hashCode() ^ y.hashCode() ^ Arrays.hashCode(zs); } - /** - * Sets the <code>PreCompInfo</code>. Used by <code>ECMultiplier</code>s - * to save the precomputation for this <code>ECPoint</code> to store the - * precomputation result for use by subsequent multiplication. - * @param preCompInfo The values precomputed by the - * <code>ECMultiplier</code>. - */ - void setPreCompInfo(PreCompInfo preCompInfo) - { - this.preCompInfo = preCompInfo; - } - public byte[] getEncoded() { return getEncoded(withCompression); @@ -311,22 +299,7 @@ public abstract class ECPoint */ public ECPoint multiply(BigInteger k) { - if (k.signum() < 0) - { - throw new IllegalArgumentException("The multiplicator cannot be negative"); - } - - if (this.isInfinity()) - { - return this; - } - - if (k.signum() == 0) - { - return getCurve().getInfinity(); - } - - return getCurve().getMultiplier().multiply(this, k, preCompInfo); + return getCurve().getMultiplier().multiply(this, k); } /** diff --git a/core/src/main/java/org/bouncycastle/math/ec/MixedNafR2LMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/MixedNafR2LMultiplier.java index 82f5ef11..fc466a09 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/MixedNafR2LMultiplier.java +++ b/core/src/main/java/org/bouncycastle/math/ec/MixedNafR2LMultiplier.java @@ -6,7 +6,7 @@ import java.math.BigInteger; * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (right-to-left) using * mixed coordinates. */ -public class MixedNafR2LMultiplier implements ECMultiplier +public class MixedNafR2LMultiplier extends AbstractECMultiplier { protected int additionCoord, doublingCoord; @@ -25,19 +25,12 @@ public class MixedNafR2LMultiplier implements ECMultiplier this.doublingCoord = doublingCoord; } - public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) + protected ECPoint multiplyPositive(ECPoint p, BigInteger k) { - if (k.signum() < 0) - { - throw new IllegalArgumentException("'k' cannot be negative"); - } - if (k.signum() == 0) - { - return p.getCurve().getInfinity(); - } + ECCurve curveOrig = p.getCurve(); - ECCurve curveAdd = configureCurve(p.getCurve(), additionCoord); - ECCurve curveDouble = configureCurve(p.getCurve(), doublingCoord); + ECCurve curveAdd = configureCurve(curveOrig, additionCoord); + ECCurve curveDouble = configureCurve(curveOrig, doublingCoord); ECPoint Ra = curveAdd.getInfinity(); ECPoint Td = curveDouble.importPoint(p); @@ -64,7 +57,7 @@ public class MixedNafR2LMultiplier implements ECMultiplier zeroes = 1; } - return p.getCurve().importPoint(Ra); + return curveOrig.importPoint(Ra); } protected ECCurve configureCurve(ECCurve c, int coord) diff --git a/core/src/main/java/org/bouncycastle/math/ec/MontgomeryLadderMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/MontgomeryLadderMultiplier.java index 71036d18..cd969b50 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/MontgomeryLadderMultiplier.java +++ b/core/src/main/java/org/bouncycastle/math/ec/MontgomeryLadderMultiplier.java @@ -2,12 +2,12 @@ package org.bouncycastle.math.ec; import java.math.BigInteger; -public class MontgomeryLadderMultiplier implements ECMultiplier +public class MontgomeryLadderMultiplier extends AbstractECMultiplier { /** * Montgomery ladder. */ - public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) + protected ECPoint multiplyPositive(ECPoint p, BigInteger k) { ECPoint[] R = new ECPoint[]{ p.getCurve().getInfinity(), p }; diff --git a/core/src/main/java/org/bouncycastle/math/ec/NafL2RMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/NafL2RMultiplier.java index 8ccb8e93..9ffe8449 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/NafL2RMultiplier.java +++ b/core/src/main/java/org/bouncycastle/math/ec/NafL2RMultiplier.java @@ -5,28 +5,18 @@ import java.math.BigInteger; /** * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (left-to-right). */ -public class NafL2RMultiplier implements ECMultiplier +public class NafL2RMultiplier extends AbstractECMultiplier { /** * D.3.2 pg 101 * @see org.bouncycastle.math.ec.ECMultiplier#multiply(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger) */ - public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) + protected ECPoint multiplyPositive(ECPoint p, BigInteger k) { - if (k.signum() < 0) - { - throw new IllegalArgumentException("'k' cannot be negative"); - } - if (k.signum() == 0) - { - return p.getCurve().getInfinity(); - } - int[] naf = WNafUtil.generateCompactNaf(k); - p = p.normalize(); + ECPoint addP = p.normalize(), subP = addP.negate(); - ECPoint negP = p.negate(); ECPoint R = p.getCurve().getInfinity(); int i = naf.length; @@ -35,7 +25,7 @@ public class NafL2RMultiplier implements ECMultiplier int ni = naf[i]; int digit = ni >> 16, zeroes = ni & 0xFFFF; - R = R.twicePlus(digit > 0 ? p : negP); + R = R.twicePlus(digit < 0 ? subP : addP); R = R.timesPow2(zeroes); } diff --git a/core/src/main/java/org/bouncycastle/math/ec/NafR2LMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/NafR2LMultiplier.java index f75d1e2e..6a9474cf 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/NafR2LMultiplier.java +++ b/core/src/main/java/org/bouncycastle/math/ec/NafR2LMultiplier.java @@ -5,26 +5,15 @@ import java.math.BigInteger; /** * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (right-to-left). */ -public class NafR2LMultiplier implements ECMultiplier +public class NafR2LMultiplier extends AbstractECMultiplier { - public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) + protected ECPoint multiplyPositive(ECPoint p, BigInteger k) { - if (k.signum() < 0) - { - throw new IllegalArgumentException("'k' cannot be negative"); - } - if (k.signum() == 0) - { - return p.getCurve().getInfinity(); - } - - p = p.normalize(); + int[] naf = WNafUtil.generateCompactNaf(k); - ECPoint R0 = p.getCurve().getInfinity(), R1 = p; + ECPoint R0 = p.getCurve().getInfinity(), R1 = p.normalize(); - int[] naf = WNafUtil.generateCompactNaf(k); int zeroes = 0; - for (int i = 0; i < naf.length; ++i) { int ni = naf[i]; diff --git a/core/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java index 67c69460..3601856c 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java +++ b/core/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java @@ -2,7 +2,7 @@ package org.bouncycastle.math.ec; import java.math.BigInteger; -public class ReferenceMultiplier implements ECMultiplier +public class ReferenceMultiplier extends AbstractECMultiplier { /** * Simple shift-and-add multiplication. Serves as reference implementation @@ -13,7 +13,7 @@ public class ReferenceMultiplier implements ECMultiplier * @param k The factor by which to multiply. * @return The result of the point multiplication <code>k * p</code>. */ - public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) + protected ECPoint multiplyPositive(ECPoint p, BigInteger k) { ECPoint q = p.getCurve().getInfinity(); int t = k.bitLength(); diff --git a/core/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java index d25228ba..ae1c3a02 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java +++ b/core/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java @@ -6,7 +6,7 @@ import java.math.BigInteger; * Class implementing the WNAF (Window Non-Adjacent Form) multiplication * algorithm. */ -public class WNafL2RMultiplier implements ECMultiplier +public class WNafL2RMultiplier extends AbstractECMultiplier { /** * Multiplies <code>this</code> by an integer <code>k</code> using the @@ -15,28 +15,19 @@ public class WNafL2RMultiplier implements ECMultiplier * @return A new <code>ECPoint</code> which equals <code>this</code> * multiplied by <code>k</code>. */ - public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) + protected ECPoint multiplyPositive(ECPoint p, BigInteger k) { - if (k.signum() < 0) - { - throw new IllegalArgumentException("'k' cannot be negative"); - } - if (k.signum() == 0) - { - return p.getCurve().getInfinity(); - } + ECPoint R = p.getCurve().getInfinity(); // Clamp the window width in the range [2, 8] int width = Math.max(2, Math.min(8, getWindowSize(k.bitLength()))); - WNafPreCompInfo wnafPreCompInfo = WNafUtil.precompute(p, preCompInfo, width, true); + WNafPreCompInfo wnafPreCompInfo = WNafUtil.precompute(p, width, true); ECPoint[] preComp = wnafPreCompInfo.getPreComp(); ECPoint[] preCompNeg = wnafPreCompInfo.getPreCompNeg(); int[] wnaf = WNafUtil.generateCompactWindowNaf(width, k); - ECPoint R = p.getCurve().getInfinity(); - int i = wnaf.length; while (--i >= 0) { diff --git a/core/src/main/java/org/bouncycastle/math/ec/WNafUtil.java b/core/src/main/java/org/bouncycastle/math/ec/WNafUtil.java index cbc2aa00..0c7b2175 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/WNafUtil.java +++ b/core/src/main/java/org/bouncycastle/math/ec/WNafUtil.java @@ -226,9 +226,10 @@ public abstract class WNafUtil return w + 2; } - public static WNafPreCompInfo precompute(ECPoint p, PreCompInfo preCompInfo, int width, boolean includeNegated) + public static WNafPreCompInfo precompute(ECPoint p, int width, boolean includeNegated) { - WNafPreCompInfo wnafPreCompInfo = getWNafPreCompInfo(preCompInfo); + ECCurve c = p.getCurve(); + WNafPreCompInfo wnafPreCompInfo = getWNafPreCompInfo(c.getPreCompInfo(p)); ECPoint[] preComp = wnafPreCompInfo.getPreComp(); if (preComp == null) @@ -244,7 +245,7 @@ public abstract class WNafUtil ECPoint twiceP = wnafPreCompInfo.getTwiceP(); if (twiceP == null) { - twiceP = p.twice().normalize(); + twiceP = preComp[0].twice().normalize(); wnafPreCompInfo.setTwiceP(twiceP); } @@ -294,7 +295,7 @@ public abstract class WNafUtil wnafPreCompInfo.setPreCompNeg(preCompNeg); } - p.setPreCompInfo(wnafPreCompInfo); + c.setPreCompInfo(p, wnafPreCompInfo); return wnafPreCompInfo; } diff --git a/core/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java index deec7f79..7bd30ecd 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java +++ b/core/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java @@ -6,7 +6,7 @@ import java.math.BigInteger; * Class implementing the WTNAF (Window * <code>τ</code>-adic Non-Adjacent Form) algorithm. */ -public class WTauNafMultiplier implements ECMultiplier +public class WTauNafMultiplier extends AbstractECMultiplier { /** * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} @@ -16,7 +16,7 @@ public class WTauNafMultiplier implements ECMultiplier * @param k The integer by which to multiply <code>k</code>. * @return <code>p</code> multiplied by <code>k</code>. */ - public ECPoint multiply(ECPoint point, BigInteger k, PreCompInfo preCompInfo) + protected ECPoint multiplyPositive(ECPoint point, BigInteger k) { if (!(point instanceof ECPoint.F2m)) { @@ -25,8 +25,7 @@ public class WTauNafMultiplier implements ECMultiplier } ECPoint.F2m p = (ECPoint.F2m)point; - - ECCurve.F2m curve = (ECCurve.F2m) p.getCurve(); + ECCurve.F2m curve = (ECCurve.F2m)p.getCurve(); int m = curve.getM(); byte a = curve.getA().toBigInteger().byteValue(); byte mu = curve.getMu(); @@ -34,7 +33,7 @@ public class WTauNafMultiplier implements ECMultiplier ZTauElement rho = Tnaf.partModReduction(k, m, a, s, mu, (byte)10); - return multiplyWTnaf(p, rho, preCompInfo, a, mu); + return multiplyWTnaf(p, rho, curve.getPreCompInfo(p), a, mu); } /** @@ -88,7 +87,7 @@ public class WTauNafMultiplier implements ECMultiplier if ((preCompInfo == null) || !(preCompInfo instanceof WTauNafPreCompInfo)) { pu = Tnaf.getPreComp(p, a); - p.setPreCompInfo(new WTauNafPreCompInfo(pu)); + curve.setPreCompInfo(p, new WTauNafPreCompInfo(pu)); } else { diff --git a/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitL2RMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitL2RMultiplier.java index add4cca7..b478dc70 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitL2RMultiplier.java +++ b/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitL2RMultiplier.java @@ -2,23 +2,28 @@ package org.bouncycastle.math.ec; import java.math.BigInteger; -public class ZSignedDigitL2RMultiplier implements ECMultiplier +public class ZSignedDigitL2RMultiplier extends AbstractECMultiplier { /** * 'Zeroless' Signed Digit Left-to-Right. */ - public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) + protected ECPoint multiplyPositive(ECPoint p, BigInteger k) { - p = p.normalize(); - ECPoint R0 = p, negP = p.negate(); + ECPoint addP = p.normalize(), subP = addP.negate(); + ECPoint R0 = addP; + + int n = k.bitLength(); int s = k.getLowestSetBit(); - int i = k.bitLength(); + + int i = n; while (--i > s) { - R0 = R0.twicePlus(k.testBit(i) ? p : negP); + R0 = R0.twicePlus(k.testBit(i) ? addP : subP); } + R0 = R0.timesPow2(s); + return R0; } } diff --git a/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitR2LMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitR2LMultiplier.java index 29f7ed60..baa702f8 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitR2LMultiplier.java +++ b/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitR2LMultiplier.java @@ -2,25 +2,29 @@ package org.bouncycastle.math.ec; import java.math.BigInteger; -public class ZSignedDigitR2LMultiplier implements ECMultiplier +public class ZSignedDigitR2LMultiplier extends AbstractECMultiplier { /** * 'Zeroless' Signed Digit Right-to-Left. */ - public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) + protected ECPoint multiplyPositive(ECPoint p, BigInteger k) { ECPoint R0 = p.getCurve().getInfinity(), R1 = p; int n = k.bitLength(); - int i = k.getLowestSetBit(); + int s = k.getLowestSetBit(); - R1 = R1.timesPow2(i); + R1 = R1.timesPow2(s); + + int i = s; while (++i < n) { R0 = R0.add(k.testBit(i) ? R1 : R1.negate()); R1 = R1.twice(); } + R0 = R0.add(R1); + return R0; } } |