static SRP() { // initialize N { NHex = //512bit //"D4C7F8A2B32C11B8FBA9581EC4BA4F1B04215642EF7355E37C0FC0443EF756EA2C6B8EEB755A1C723027663CAA265EF785B8FF6A9B35227A52D86633DBDFCA43"; //256bit "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3".ToLowerInvariant(); N = new BigInteger(NHex, 16); _nbits = N.bitCount(); Nminus1 = N - 1; // if (!N.isProbablePrime(80)) // { // throw new Exception("Warning: N is not prime"); // } // // if (!(Nminus1 / 2).isProbablePrime(80)) // { // throw new Exception("Warning: (N-1)/2 is not prime"); // } } // initialize g { gHex = "2"; g = new BigInteger(gHex, 16); } // initialize k = H(N || g) { BigInteger ktmp = new BigInteger(HHex( (((NHex.Length & 1) == 0) ? "" : "0") + NHex + new string('0', NHex.Length - gHex.Length) + gHex ), 16); k = (ktmp < N) ? ktmp : (ktmp % N); kHex = k.ToString(16).ToLowerInvariant().TrimStart('0'); } // initialize a, A { a = new BigInteger(); a.genRandomBits(36); A = g.modPow(a, N); while (A.modInverse(N) == 0) { a = new BigInteger(); a.genRandomBits(36); A = g.modPow(a, N); } Ahex = A.ToString(16).ToLowerInvariant().TrimStart('0'); } }
//*********************************************************************** // Performs the calculation of the kth term in the Lucas Sequence. // For details of the algorithm, see reference [9]. // // k must be odd. i.e LSB == 1 //*********************************************************************** private static BigInteger[] LucasSequenceHelper(BigInteger P, BigInteger Q, BigInteger k, BigInteger n, BigInteger constant, int s) { BigInteger[] result = new BigInteger[3]; if ((k.data[0] & 0x00000001) == 0) throw (new ArgumentException("Argument k must be odd.")); int numbits = k.bitCount(); uint mask = (uint)0x1 << ((numbits & 0x1F) - 1); // v = v0, v1 = v1, u1 = u1, Q_k = Q^0 BigInteger v = 2 % n, Q_k = 1 % n, v1 = P % n, u1 = Q_k; bool flag = true; for (int i = k.dataLength - 1; i >= 0; i--) // iterate on the binary expansion of k { //Console.WriteLine("round"); while (mask != 0) { if (i == 0 && mask == 0x00000001) // last bit break; if ((k.data[i] & mask) != 0) // bit is set { // index doubling with addition u1 = (u1 * v1) % n; v = ((v * v1) - (P * Q_k)) % n; v1 = n.BarrettReduction(v1 * v1, n, constant); v1 = (v1 - ((Q_k * Q) << 1)) % n; if (flag) flag = false; else Q_k = n.BarrettReduction(Q_k * Q_k, n, constant); Q_k = (Q_k * Q) % n; } else { // index doubling u1 = ((u1 * v) - Q_k) % n; v1 = ((v * v1) - (P * Q_k)) % n; v = n.BarrettReduction(v * v, n, constant); v = (v - (Q_k << 1)) % n; if (flag) { Q_k = Q % n; flag = false; } else Q_k = n.BarrettReduction(Q_k * Q_k, n, constant); } mask >>= 1; } mask = 0x80000000; } // at this point u1 = u(n+1) and v = v(n) // since the last bit always 1, we need to transform u1 to u(2n+1) and v to v(2n+1) u1 = ((u1 * v) - Q_k) % n; v = ((v * v1) - (P * Q_k)) % n; if (flag) flag = false; else Q_k = n.BarrettReduction(Q_k * Q_k, n, constant); Q_k = (Q_k * Q) % n; for (int i = 0; i < s; i++) { // index doubling u1 = (u1 * v) % n; v = ((v * v) - (Q_k << 1)) % n; if (flag) { Q_k = Q % n; flag = false; } else Q_k = n.BarrettReduction(Q_k * Q_k, n, constant); } result[0] = u1; result[1] = v; result[2] = Q_k; return result; }
//*********************************************************************** // Modulo Exponentiation //*********************************************************************** public BigInteger modPow(BigInteger exp, BigInteger n) { if ((exp.data[maxLength - 1] & 0x80000000) != 0) throw (new ArithmeticException("Positive exponents only.")); BigInteger resultNum = 1; BigInteger tempNum; bool thisNegative = false; if ((this.data[maxLength - 1] & 0x80000000) != 0) // negative this { tempNum = -this % n; thisNegative = true; } else tempNum = this % n; // ensures (tempNum * tempNum) < b^(2k) if ((n.data[maxLength - 1] & 0x80000000) != 0) // negative n n = -n; // calculate constant = b^(2k) / m BigInteger constant = new BigInteger(); int i = n.dataLength << 1; constant.data[i] = 0x00000001; constant.dataLength = i + 1; constant = constant / n; int totalBits = exp.bitCount(); int count = 0; // perform squaring and multiply exponentiation for (int pos = 0; pos < exp.dataLength; pos++) { uint mask = 0x01; //Console.WriteLine("pos = " + pos); for (int index = 0; index < 32; index++) { if ((exp.data[pos] & mask) != 0) resultNum = BarrettReduction(resultNum * tempNum, n, constant); mask <<= 1; tempNum = BarrettReduction(tempNum * tempNum, n, constant); if (tempNum.dataLength == 1 && tempNum.data[0] == 1) { if (thisNegative && (exp.data[0] & 0x1) != 0) //odd exp return -resultNum; return resultNum; } count++; if (count == totalBits) break; } } if (thisNegative && (exp.data[0] & 0x1) != 0) //odd exp return -resultNum; return resultNum; }