16e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrompackage org.bouncycastle.math.ec; 26e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 36e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.math.BigInteger; 46e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 56e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom/** 66e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * Class implementing the WNAF (Window Non-Adjacent Form) multiplication 76e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * algorithm. 86e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom */ 96e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromclass WNafMultiplier implements ECMultiplier 106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom{ 116e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom /** 126e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * Computes the Window NAF (non-adjacent Form) of an integer. 136e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * @param width The width <code>w</code> of the Window NAF. The width is 146e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * defined as the minimal number <code>w</code>, such that for any 156e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * <code>w</code> consecutive digits in the resulting representation, at 166e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * most one is non-zero. 176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * @param k The integer of which the Window NAF is computed. 186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * @return The Window NAF of the given width, such that the following holds: 196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * <code>k = ∑<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup> 206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * </code>, where the <code>k<sub>i</sub></code> denote the elements of the 216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * returned <code>byte[]</code>. 226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom */ 236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom public byte[] windowNaf(byte width, BigInteger k) 246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // The window NAF is at most 1 element longer than the binary 266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // representation of the integer k. byte can be used instead of short or 276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // int unless the window width is larger than 8. For larger width use 286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // short or int. However, a width of more than 8 is not efficient for 296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // m = log2(q) smaller than 2305 Bits. Note: Values for m larger than 306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // 1000 Bits are currently not used in practice. 316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom byte[] wnaf = new byte[k.bitLength() + 1]; 326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 336e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // 2^width as short and BigInteger 346e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom short pow2wB = (short)(1 << width); 356e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom BigInteger pow2wBI = BigInteger.valueOf(pow2wB); 366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom int i = 0; 386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // The actual length of the WNAF 406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom int length = 0; 416e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 426e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // while k >= 1 436e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom while (k.signum() > 0) 446e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 456e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // if k is odd 466e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (k.testBit(0)) 476e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 486e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // k mod 2^width 496e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom BigInteger remainder = k.mod(pow2wBI); 506e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 516e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // if remainder > 2^(width - 1) - 1 526e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (remainder.testBit(width - 1)) 536e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 546e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom wnaf[i] = (byte)(remainder.intValue() - pow2wB); 556e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 566e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else 576e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 586e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom wnaf[i] = (byte)remainder.intValue(); 596e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 606e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // wnaf[i] is now in [-2^(width-1), 2^(width-1)-1] 616e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 626e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom k = k.subtract(BigInteger.valueOf(wnaf[i])); 636e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom length = i; 646e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 656e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else 666e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 676e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom wnaf[i] = 0; 686e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 696e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 706e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // k = k/2 716e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom k = k.shiftRight(1); 726e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom i++; 736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom length++; 766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // Reduce the WNAF array to its actual length 786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom byte[] wnafShort = new byte[length]; 796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom System.arraycopy(wnaf, 0, wnafShort, 0, length); 806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom return wnafShort; 816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom /** 846e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * Multiplies <code>this</code> by an integer <code>k</code> using the 856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * Window NAF method. 866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * @param k The integer by which <code>this</code> is multiplied. 876e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * @return A new <code>ECPoint</code> which equals <code>this</code> 886e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * multiplied by <code>k</code>. 896e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom */ 906e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) 916e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 926e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom WNafPreCompInfo wnafPreCompInfo; 936e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 946e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if ((preCompInfo != null) && (preCompInfo instanceof WNafPreCompInfo)) 956e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 966e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom wnafPreCompInfo = (WNafPreCompInfo)preCompInfo; 976e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 986e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else 996e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1006e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // Ignore empty PreCompInfo or PreCompInfo of incorrect type 1016e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom wnafPreCompInfo = new WNafPreCompInfo(); 1026e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1036e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 1046e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // floor(log2(k)) 1056e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom int m = k.bitLength(); 1066e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 1076e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // width of the Window NAF 1086e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom byte width; 1096e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 1106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // Required length of precomputation array 1116e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom int reqPreCompLen; 1126e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 1136e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // Determine optimal width and corresponding length of precomputation 1146e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // array based on literature values 1156e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (m < 13) 1166e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom width = 2; 1186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom reqPreCompLen = 1; 1196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else 1216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (m < 41) 1236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom width = 3; 1256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom reqPreCompLen = 2; 1266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else 1286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (m < 121) 1306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom width = 4; 1326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom reqPreCompLen = 4; 1336e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1346e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else 1356e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (m < 337) 1376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom width = 5; 1396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom reqPreCompLen = 8; 1406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1416e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else 1426e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1436e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (m < 897) 1446e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1456e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom width = 6; 1466e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom reqPreCompLen = 16; 1476e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1486e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else 1496e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1506e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (m < 2305) 1516e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1526e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom width = 7; 1536e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom reqPreCompLen = 32; 1546e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1556e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else 1566e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1576e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom width = 8; 1586e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom reqPreCompLen = 127; 1596e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1606e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1616e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1626e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1636e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1646e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1656e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 1666e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // The length of the precomputation array 1676e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom int preCompLen = 1; 1686e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 1696e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom ECPoint[] preComp = wnafPreCompInfo.getPreComp(); 1706e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom ECPoint twiceP = wnafPreCompInfo.getTwiceP(); 1716e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 1726e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // Check if the precomputed ECPoints already exist 1736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (preComp == null) 1746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // Precomputation must be performed from scratch, create an empty 1766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // precomputation array of desired length 1776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom preComp = new ECPoint[]{ p }; 1786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else 1806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // Take the already precomputed ECPoints to start with 1826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom preCompLen = preComp.length; 1836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1846e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 1856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (twiceP == null) 1866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1876e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // Compute twice(p) 1886e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom twiceP = p.twice(); 1896e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1906e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 1916e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (preCompLen < reqPreCompLen) 1926e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1936e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // Precomputation array must be made bigger, copy existing preComp 1946e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // array into the larger new preComp array 1956e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom ECPoint[] oldPreComp = preComp; 1966e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom preComp = new ECPoint[reqPreCompLen]; 1976e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom System.arraycopy(oldPreComp, 0, preComp, 0, preCompLen); 1986e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 1996e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom for (int i = preCompLen; i < reqPreCompLen; i++) 2006e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 2016e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // Compute the new ECPoints for the precomputation array. 2026e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // The values 1, 3, 5, ..., 2^(width-1)-1 times p are 2036e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // computed 2046e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom preComp[i] = twiceP.add(preComp[i - 1]); 2056e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 2066e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 2076e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 2086e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // Compute the Window NAF of the desired width 2096e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom byte[] wnaf = windowNaf(width, k); 2106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom int l = wnaf.length; 2116e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 2126e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // Apply the Window NAF to p using the precomputed ECPoint values. 2136e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom ECPoint q = p.getCurve().getInfinity(); 2146e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom for (int i = l - 1; i >= 0; i--) 2156e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 2166e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom q = q.twice(); 2176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 2186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (wnaf[i] != 0) 2196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 2206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (wnaf[i] > 0) 2216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 2226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom q = q.add(preComp[(wnaf[i] - 1)/2]); 2236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 2246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else 2256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 2266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // wnaf[i] < 0 2276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom q = q.subtract(preComp[(-wnaf[i] - 1)/2]); 2286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 2296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 2306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 2316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 2326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // Set PreCompInfo in ECPoint, such that it is available for next 2336e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom // multiplication. 2346e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom wnafPreCompInfo.setPreComp(preComp); 2356e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom wnafPreCompInfo.setTwiceP(twiceP); 2366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom p.setPreCompInfo(wnafPreCompInfo); 2376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom return q; 2386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 2396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 2406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom} 241