Skip to content

Commit 3303aca

Browse files
committed
Koblitz curve perf. opts.
1 parent 68c4f42 commit 3303aca

File tree

2 files changed

+54
-110
lines changed

2 files changed

+54
-110
lines changed

core/src/main/java/org/bouncycastle/math/ec/Tnaf.java

Lines changed: 52 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ class Tnaf
2727
*/
2828
public static final byte WIDTH = 4;
2929

30-
/**
31-
* 2<sup>4</sup>
32-
*/
33-
public static final byte POW_2_WIDTH = 16;
34-
3530
/**
3631
* The <code>&alpha;<sub>u</sub></code>'s for <code>a=0</code> as an array
3732
* of <code>ZTauElement</code>s.
@@ -451,10 +446,7 @@ public static BigInteger[] getLucas(byte mu, int k, boolean doV)
451446
throw new IllegalArgumentException("mu must be 1 or -1");
452447
}
453448

454-
BigInteger u0;
455-
BigInteger u1;
456-
BigInteger u2;
457-
449+
BigInteger u0, u1, u2;
458450
if (doV)
459451
{
460452
u0 = ECConstants.TWO;
@@ -469,26 +461,18 @@ public static BigInteger[] getLucas(byte mu, int k, boolean doV)
469461
for (int i = 1; i < k; i++)
470462
{
471463
// u2 = mu*u1 - 2*u0;
472-
BigInteger s = null;
473-
if (mu == 1)
464+
BigInteger s = u1;
465+
if (mu < 0)
474466
{
475-
s = u1;
467+
s = s.negate();
476468
}
477-
else
478-
{
479-
// mu == -1
480-
s = u1.negate();
481-
}
482-
469+
483470
u2 = s.subtract(u0.shiftLeft(1));
484471
u0 = u1;
485472
u1 = u2;
486-
// System.out.println(i + ": " + u2);
487-
// System.out.println();
488473
}
489474

490-
BigInteger[] retVal = {u0, u1};
491-
return retVal;
475+
return new BigInteger[]{ u0, u1 };
492476
}
493477

494478
/**
@@ -519,11 +503,7 @@ public static BigInteger getTw(byte mu, int w)
519503
BigInteger[] us = getLucas(mu, w, false);
520504
BigInteger twoToW = ECConstants.ZERO.setBit(w);
521505
BigInteger u1invert = us[1].modInverse(twoToW);
522-
BigInteger tw;
523-
tw = ECConstants.TWO.multiply(us[0]).multiply(u1invert).mod(twoToW);
524-
// System.out.println("mu = " + mu);
525-
// System.out.println("tw = " + tw);
526-
return tw;
506+
return us[0].shiftLeft(1).multiply(u1invert).mod(twoToW);
527507
}
528508
}
529509

@@ -542,22 +522,7 @@ public static BigInteger[] getSi(ECCurve.AbstractF2m curve)
542522
throw new IllegalArgumentException("si is defined for Koblitz curves only");
543523
}
544524

545-
int m = curve.getFieldSize();
546-
int a = curve.getA().toBigInteger().intValue();
547-
byte mu = getMu(a);
548-
int shifts = getShiftsForCofactor(curve.getCofactor());
549-
int index = m + 3 - a;
550-
BigInteger[] ui = getLucas(mu, index, false);
551-
if (mu == 1)
552-
{
553-
ui[0] = ui[0].negate();
554-
ui[1] = ui[1].negate();
555-
}
556-
557-
BigInteger dividend0 = ECConstants.ONE.add(ui[1]).shiftRight(shifts);
558-
BigInteger dividend1 = ECConstants.ONE.add(ui[0]).shiftRight(shifts).negate();
559-
560-
return new BigInteger[] { dividend0, dividend1 };
525+
return getSi(curve.getFieldSize(), curve.getA().toBigInteger().intValue(), curve.getCofactor());
561526
}
562527

563528
public static BigInteger[] getSi(int fieldSize, int curveA, BigInteger cofactor)
@@ -608,9 +573,11 @@ protected static int getShiftsForCofactor(BigInteger h)
608573
* modular reduction.
609574
* @return <code>&rho; := k partmod (&tau;<sup>m</sup> - 1)/(&tau; - 1)</code>
610575
*/
611-
public static ZTauElement partModReduction(BigInteger k, int m, byte a,
612-
BigInteger[] s, byte mu, byte c)
576+
public static ZTauElement partModReduction(ECCurve.AbstractF2m curve, BigInteger k, byte a, byte mu, byte c)
613577
{
578+
int m = curve.getFieldSize();
579+
BigInteger[] s = curve.getSi();
580+
614581
// d0 = s[0] + mu*s[1]; mu is either 1 or -1
615582
BigInteger d0;
616583
if (mu == 1)
@@ -622,20 +589,29 @@ public static ZTauElement partModReduction(BigInteger k, int m, byte a,
622589
d0 = s[0].subtract(s[1]);
623590
}
624591

625-
BigInteger[] v = getLucas(mu, m, true);
626-
BigInteger vm = v[1];
592+
BigInteger vm;
593+
if (curve.isKoblitz())
594+
{
595+
/*
596+
* Jerome A. Solinas, "Improved Algorithms for Arithmetic on Anomalous Binary Curves", (21).
597+
*/
598+
vm = ECConstants.ONE.shiftLeft(m).add(ECConstants.ONE).subtract(
599+
curve.getOrder().multiply(curve.getCofactor()));
600+
}
601+
else
602+
{
603+
BigInteger[] v = getLucas(mu, m, true);
604+
vm = v[1];
605+
}
627606

628-
SimpleBigDecimal lambda0 = approximateDivisionByN(
629-
k, s[0], vm, a, m, c);
630-
631-
SimpleBigDecimal lambda1 = approximateDivisionByN(
632-
k, s[1], vm, a, m, c);
607+
SimpleBigDecimal lambda0 = approximateDivisionByN(k, s[0], vm, a, m, c);
608+
SimpleBigDecimal lambda1 = approximateDivisionByN(k, s[1], vm, a, m, c);
633609

634610
ZTauElement q = round(lambda0, lambda1, mu);
635611

636612
// r0 = n - d0*q0 - 2*s1*q1
637613
BigInteger r0 = k.subtract(d0.multiply(q.u)).subtract(
638-
BigInteger.valueOf(2).multiply(s[1]).multiply(q.v));
614+
s[1].multiply(q.v).shiftLeft(1));
639615

640616
// r1 = s1*q0 - s0*q1
641617
BigInteger r1 = s[1].multiply(q.u).subtract(s[0].multiply(q.v));
@@ -654,11 +630,10 @@ public static ZTauElement partModReduction(BigInteger k, int m, byte a,
654630
public static ECPoint.AbstractF2m multiplyRTnaf(ECPoint.AbstractF2m p, BigInteger k)
655631
{
656632
ECCurve.AbstractF2m curve = (ECCurve.AbstractF2m) p.getCurve();
657-
int m = curve.getFieldSize();
658633
int a = curve.getA().toBigInteger().intValue();
659634
byte mu = getMu(a);
660-
BigInteger[] s = curve.getSi();
661-
ZTauElement rho = partModReduction(k, m, (byte)a, s, mu, (byte)10);
635+
636+
ZTauElement rho = partModReduction(curve, k, (byte)a, mu, (byte)10);
662637

663638
return multiplyTnaf(p, rho);
664639
}
@@ -678,9 +653,7 @@ public static ECPoint.AbstractF2m multiplyTnaf(ECPoint.AbstractF2m p, ZTauElemen
678653
byte mu = getMu(curve.getA());
679654
byte[] u = tauAdicNaf(mu, lambda);
680655

681-
ECPoint.AbstractF2m q = multiplyFromTnaf(p, u);
682-
683-
return q;
656+
return multiplyFromTnaf(p, u);
684657
}
685658

686659
/**
@@ -732,10 +705,9 @@ public static ECPoint.AbstractF2m multiplyFromTnaf(ECPoint.AbstractF2m p, byte[]
732705
* @return The <code>[&tau;]</code>-adic window NAF of
733706
* <code>&lambda;</code>.
734707
*/
735-
public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda,
736-
byte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha)
708+
public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda, int width, int tw, ZTauElement[] alpha)
737709
{
738-
if (!((mu == 1) || (mu == -1)))
710+
if (!(mu == 1 || mu == -1))
739711
{
740712
throw new IllegalArgumentException("mu must be 1 or -1");
741713
}
@@ -751,74 +723,49 @@ public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda,
751723
// The array holding the TNAF
752724
byte[] u = new byte[maxLength];
753725

726+
int pow2Width = 1 << width;
727+
754728
// 2^(width - 1)
755-
BigInteger pow2wMin1 = pow2w.shiftRight(1);
729+
int pow2wMin1 = pow2Width >>> 1;
756730

757731
// Split lambda into two BigIntegers to simplify calculations
758732
BigInteger r0 = lambda.u;
759733
BigInteger r1 = lambda.v;
760734
int i = 0;
761735

762736
// while lambda <> (0, 0)
763-
while (!((r0.equals(ECConstants.ZERO))&&(r1.equals(ECConstants.ZERO))))
737+
while ((r0.signum() | r1.signum()) != 0)
764738
{
765-
// if r0 is odd
766739
if (r0.testBit(0))
767740
{
768-
// uUnMod = r0 + r1*tw mod 2^width
769-
BigInteger uUnMod
770-
= r0.add(r1.multiply(tw)).mod(pow2w);
771-
772-
byte uLocal;
773-
// if uUnMod >= 2^(width - 1)
774-
if (uUnMod.compareTo(pow2wMin1) >= 0)
775-
{
776-
uLocal = (byte) uUnMod.subtract(pow2w).intValue();
777-
}
778-
else
779-
{
780-
uLocal = (byte) uUnMod.intValue();
781-
}
782-
// uLocal is now in [-2^(width-1), 2^(width-1)-1]
741+
int uUnMod = (r0.intValue() + (r1.intValue() * tw)) & (pow2Width - 1);
783742

784-
u[i] = uLocal;
785-
boolean s = true;
786-
if (uLocal < 0)
743+
if (uUnMod >= pow2wMin1)
787744
{
788-
s = false;
789-
uLocal = (byte)-uLocal;
790-
}
791-
// uLocal is now >= 0
792-
793-
if (s)
794-
{
795-
r0 = r0.subtract(alpha[uLocal].u);
796-
r1 = r1.subtract(alpha[uLocal].v);
745+
u[i] = (byte)(uUnMod - pow2Width);
746+
r0 = r0.add(alpha[pow2Width - uUnMod].u);
747+
r1 = r1.add(alpha[pow2Width - uUnMod].v);
797748
}
798749
else
799750
{
800-
r0 = r0.add(alpha[uLocal].u);
801-
r1 = r1.add(alpha[uLocal].v);
751+
u[i] = (byte)uUnMod;
752+
r0 = r0.subtract(alpha[uUnMod].u);
753+
r1 = r1.subtract(alpha[uUnMod].v);
802754
}
803755
}
804-
else
805-
{
806-
u[i] = 0;
807-
}
808756

809-
BigInteger t = r0;
757+
++i;
810758

759+
BigInteger t = r0.shiftRight(1);
811760
if (mu == 1)
812761
{
813-
r0 = r1.add(r0.shiftRight(1));
762+
r0 = r1.add(t);
814763
}
815-
else
764+
else // mu == -1
816765
{
817-
// mu == -1
818-
r0 = r1.subtract(r0.shiftRight(1));
766+
r0 = r1.subtract(t);
819767
}
820-
r1 = t.shiftRight(1).negate();
821-
i++;
768+
r1 = t.negate();
822769
}
823770
return u;
824771
}

core/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,10 @@ protected ECPoint multiplyPositive(ECPoint point, BigInteger k)
2929

3030
ECPoint.AbstractF2m p = (ECPoint.AbstractF2m)point;
3131
ECCurve.AbstractF2m curve = (ECCurve.AbstractF2m)p.getCurve();
32-
int m = curve.getFieldSize();
3332
byte a = curve.getA().toBigInteger().byteValue();
3433
byte mu = Tnaf.getMu(a);
35-
BigInteger[] s = curve.getSi();
3634

37-
ZTauElement rho = Tnaf.partModReduction(k, m, a, s, mu, (byte)10);
35+
ZTauElement rho = Tnaf.partModReduction(curve, k, a, mu, (byte)10);
3836

3937
return multiplyWTnaf(p, rho, a, mu);
4038
}
@@ -55,8 +53,7 @@ private ECPoint.AbstractF2m multiplyWTnaf(ECPoint.AbstractF2m p, ZTauElement lam
5553

5654
BigInteger tw = Tnaf.getTw(mu, Tnaf.WIDTH);
5755

58-
byte[]u = Tnaf.tauAdicWNaf(mu, lambda, Tnaf.WIDTH,
59-
BigInteger.valueOf(Tnaf.POW_2_WIDTH), tw, alpha);
56+
byte[] u = Tnaf.tauAdicWNaf(mu, lambda, Tnaf.WIDTH, tw.intValue(), alpha);
6057

6158
return multiplyFromWTnaf(p, u);
6259
}

0 commit comments

Comments
 (0)