- * Returns true if this BigInteger is probably prime,
- * false if it's definitely composite. If
- * certainty is <= 0, true is
- * returned.
- *
true the
- * probability that this BigInteger is prime exceeds
- * (1 - 1/2certainty). The execution time
- * of this method is proportional to the value of this parameter.
- * @return true if this BigInteger is probably prime,
- * false if it's definitely composite.
- */
- public boolean isProbablePrime(int certainty) {
- if (certainty < 1)
- return true;
-
- /**
- * We'll use the Rabin-Miller algorithm for doing a probabilistic
- * primality test. It is fast, easy and has faster decreasing odds of a
- * composite passing than with other tests. This means that this method
- * will actually have a probability much greater than the 1 -
- * .5^certainty specified in the JCL (p. 117), but I don't think anyone
- * will complain about better performance with greater certainty.
- *
- * The Rabin-Miller algorithm can be found on pp. 259-261 of "Applied
- * Cryptography, Second Edition" by Bruce Schneier.
- */
-
- // First rule out small prime factors
- BigIntegerCrypto rem = new BigIntegerCrypto();
- int i;
- for (i = 0; i < primes.length; i++) {
- if (words == null && ival == primes[i])
- return true;
-
- divide(this, smallFixNums[primes[i] - minFixNum], null, rem,
- TRUNCATE);
- if (rem.canonicalize().isZero())
- return false;
- }
-
- // Now perform the Rabin-Miller test.
-
- // Set b to the number of times 2 evenly divides (this - 1).
- // I.e. 2^b is the largest power of 2 that divides (this - 1).
- BigIntegerCrypto pMinus1 = add(this, -1);
- int b = pMinus1.getLowestSetBit();
-
- // Set m such that this = 1 + 2^b * m.
- BigIntegerCrypto m = pMinus1.divide(valueOf(2L).pow(b));
-
- // The HAC (Handbook of Applied Cryptography), Alfred Menezes & al. Note
- // 4.49 (controlling the error probability) gives the number of trials
- // for an error probability of 1/2**80, given the number of bits in the
- // number to test. we shall use these numbers as is if/when 'certainty'
- // is less or equal to 80, and twice as much if it's greater.
- int bits = this.bitLength();
- for (i = 0; i < k.length; i++)
- if (bits <= k[i])
- break;
- int trials = t[i];
- if (certainty > 80)
- trials *= 2;
- BigIntegerCrypto z;
- for (int t = 0; t < trials; t++) {
- // The HAC (Handbook of Applied Cryptography), Alfred Menezes & al.
- // Remark 4.28 states: "...A strategy that is sometimes employed
- // is to fix the bases a to be the first few primes instead of
- // choosing them at random.
- z = smallFixNums[primes[t] - minFixNum].modPow(m, this);
- if (z.isOne() || z.equals(pMinus1))
- continue; // Passes the test; may be prime.
-
- for (i = 0; i < b;) {
- if (z.isOne()) {
- return false;
- }
- i++;
- if (z.equals(pMinus1))
- break; // Passes the test; may be prime.
-
- z = z.modPow(valueOf(2), this);
- }
-
- if (i == b && !z.equals(pMinus1)) {
- return false;
- }
- }
- return true;
- }
-
- private void setInvert() {
- if (words == null)
- ival = ~ival;
- else {
- for (int i = ival; --i >= 0;)
- words[i] = ~words[i];
- }
- }
-
- private void setShiftLeft(BigIntegerCrypto x, int count) {
- int[] xwords;
- int xlen;
- if (x.words == null) {
- if (count < 32) {
- set((long) x.ival << count);
- return;
- }
- xwords = new int[1];
- xwords[0] = x.ival;
- xlen = 1;
- } else {
- xwords = x.words;
- xlen = x.ival;
- }
- int word_count = count >> 5;
- count &= 31;
- int new_len = xlen + word_count;
- if (count == 0) {
- realloc(new_len);
- for (int i = xlen; --i >= 0;)
- words[i + word_count] = xwords[i];
- } else {
- new_len++;
- realloc(new_len);
- int shift_out = MPN.lshift(words, word_count, xwords, xlen, count);
- count = 32 - count;
- words[new_len - 1] = (shift_out << count) >> count; // sign-extend.
- }
- ival = new_len;
- for (int i = word_count; --i >= 0;)
- words[i] = 0;
- }
-
- private void setShiftRight(BigIntegerCrypto x, int count) {
- if (x.words == null)
- set(count < 32 ? x.ival >> count : x.ival < 0 ? -1 : 0);
- else if (count == 0)
- set(x);
- else {
- boolean neg = x.isNegative();
- int word_count = count >> 5;
- count &= 31;
- int d_len = x.ival - word_count;
- if (d_len <= 0)
- set(neg ? -1 : 0);
- else {
- if (words == null || words.length < d_len)
- realloc(d_len);
- MPN.rshift0(words, x.words, word_count, d_len, count);
- ival = d_len;
- if (neg)
- words[d_len - 1] |= -2 << (31 - count);
- }
- }
- }
-
- private void setShift(BigIntegerCrypto x, int count) {
- if (count > 0)
- setShiftLeft(x, count);
- else
- setShiftRight(x, -count);
- }
-
- private static BigIntegerCrypto shift(BigIntegerCrypto x, int count) {
- if (x.words == null) {
- if (count <= 0)
- return valueOf(count > -32 ? x.ival >> (-count)
- : x.ival < 0 ? -1 : 0);
- if (count < 32)
- return valueOf((long) x.ival << count);
- }
- if (count == 0)
- return x;
- BigIntegerCrypto result = new BigIntegerCrypto(0);
- result.setShift(x, count);
- return result.canonicalize();
- }
-
- public BigIntegerCrypto shiftLeft(int n) {
- if (n == 0)
- return this;
-
- return shift(this, n);
- }
-
- public BigIntegerCrypto shiftRight(int n) {
- if (n == 0)
- return this;
-
- return shift(this, -n);
- }
-
- private void format(int radix, StringBuffer buffer) {
- if (words == null)
- buffer.append(Integer.toString(ival, radix));
- else if (ival <= 2)
- buffer.append(Long.toString(longValue(), radix));
- else {
- boolean neg = isNegative();
- int[] work;
- if (neg || radix != 16) {
- work = new int[ival];
- getAbsolute(work);
- } else
- work = words;
- int len = ival;
-
- if (radix == 16) {
- if (neg)
- buffer.append('-');
- int buf_start = buffer.length();
- for (int i = len; --i >= 0;) {
- int word = work[i];
- for (int j = 8; --j >= 0;) {
- int hex_digit = (word >> (4 * j)) & 0xF;
- // Suppress leading zeros:
- if (hex_digit > 0 || buffer.length() > buf_start)
- buffer.append(Character.forDigit(hex_digit, 16));
- }
- }
- } else {
- int i = buffer.length();
- for (;;) {
- int digit = MPN.divmod_1(work, work, len, radix);
- buffer.append(Character.forDigit(digit, radix));
- while (len > 0 && work[len - 1] == 0)
- len--;
- if (len == 0)
- break;
- }
- if (neg)
- buffer.append('-');
- /* Reverse buffer. */
- int j = buffer.length() - 1;
- while (i < j) {
- char tmp = buffer.charAt(i);
- buffer.setCharAt(i, buffer.charAt(j));
- buffer.setCharAt(j, tmp);
- i++;
- j--;
- }
- }
- }
- }
-
- public String toString() {
- return toString(10);
- }
-
- public String toString(int radix) {
-
- if (words == null)
- return Integer.toString(ival, radix);
- if (ival <= 2)
- return Long.toString(longValue(), radix);
- int buf_size = ival * (MPN.chars_per_word(radix) + 1);
- StringBuffer buffer = new StringBuffer(buf_size);
- format(radix, buffer);
- return buffer.toString();
- }
-
- public int intValue() {
- if (words == null)
- return ival;
- return words[0];
- }
-
- public long longValue() {
- if (words == null)
- return ival;
- if (ival == 1)
- return words[0];
- return ((long) words[1] << 32) + (words[0] & 0xffffffffL);
- }
-
- public int hashCode() {
- // FIXME: May not match hashcode of JDK.
- return words == null ? ival : (words[0] + words[ival - 1]);
- }
-
- /* Assumes x and y are both canonicalized. */
- private static boolean equals(BigIntegerCrypto x, BigIntegerCrypto y) {
-
- if (x.words == null && y.words == null)
- return x.ival == y.ival;
- if (x.words == null || y.words == null || x.ival != y.ival)
- return false;
- for (int i = x.ival; --i >= 0;) {
- if (x.words[i] != y.words[i])
- return false;
- }
- return true;
- }
-
- /* Assumes this and obj are both canonicalized. */
- public boolean equals(Object obj) {
- if (!(obj instanceof BigIntegerCrypto))
- return false;
- return equals(this, (BigIntegerCrypto) obj);
- }
-
- private static BigIntegerCrypto valueOf(byte[] digits, int byte_len,
- boolean negative, int radix) {
- int chars_per_word = MPN.chars_per_word(radix);
- int[] words = new int[byte_len / chars_per_word + 1];
- int size = MPN.set_str(words, digits, byte_len, radix);
- if (size == 0)
- return ZERO;
- if (words[size - 1] < 0)
- words[size++] = 0;
- if (negative)
- negate(words, words, size);
- return make(words, size);
- }
-
- public double doubleValue() {
- if (words == null)
- return ival;
- if (ival <= 2)
- return longValue();
- if (isNegative())
- return neg(this).roundToDouble(0, true, false);
- return roundToDouble(0, false, false);
- }
-
- public float floatValue() {
- return (float) doubleValue();
- }
-
- /**
- * Return true if any of the lowest n bits are one. (false if n is
- * negative).
- */
- private boolean checkBits(int n) {
- if (n <= 0)
- return false;
- if (words == null)
- return n > 31 || ((ival & ((1 << n) - 1)) != 0);
- int i;
- for (i = 0; i < (n >> 5); i++)
- if (words[i] != 0)
- return true;
- return (n & 31) != 0 && (words[i] & ((1 << (n & 31)) - 1)) != 0;
- }
-
- /**
- * Convert a semi-processed BigInteger to double. Number must be
- * non-negative. Multiplies by a power of two, applies sign, and converts to
- * double, with the usual java rounding.
- *
- * @param exp
- * power of two, positive or negative, by which to multiply
- * @param neg
- * true if negative
- * @param remainder
- * true if the BigInteger is the result of a truncating division
- * that had non-zero remainder. To ensure proper rounding in this
- * case, the BigInteger must have at least 54 bits.
- */
- private double roundToDouble(int exp, boolean neg, boolean remainder) {
- // Compute length.
- int il = bitLength();
-
- // Exponent when normalized to have decimal point directly after
- // leading one. This is stored excess 1023 in the exponent bit field.
- exp += il - 1;
-
- // Gross underflow. If exp == -1075, we let the rounding
- // computation determine whether it is minval or 0 (which are just
- // 0x0000 0000 0000 0001 and 0x0000 0000 0000 0000 as bit
- // patterns).
- if (exp < -1075)
- return neg ? -0.0 : 0.0;
-
- // gross overflow
- if (exp > 1023)
- return neg ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
-
- // number of bits in mantissa, including the leading one.
- // 53 unless it's denormalized
- int ml = (exp >= -1022 ? 53 : 53 + exp + 1022);
-
- // Get top ml + 1 bits. The extra one is for rounding.
- long m;
- int excess_bits = il - (ml + 1);
- if (excess_bits > 0)
- m = ((words == null) ? ival >> excess_bits : MPN.rshift_long(words,
- ival, excess_bits));
- else
- m = longValue() << (-excess_bits);
-
- // Special rounding for maxval. If the number exceeds maxval by
- // any amount, even if it's less than half a step, it overflows.
- if (exp == 1023 && ((m >> 1) == (1L << 53) - 1)) {
- if (remainder || checkBits(il - ml))
- return neg ? Double.NEGATIVE_INFINITY
- : Double.POSITIVE_INFINITY;
- else
- return neg ? -Double.MAX_VALUE : Double.MAX_VALUE;
- }
-
- // Normal round-to-even rule: round up if the bit dropped is a one, and
- // the bit above it or any of the bits below it is a one.
- if ((m & 1) == 1
- && ((m & 2) == 2 || remainder || checkBits(excess_bits))) {
- m += 2;
- // Check if we overflowed the mantissa
- if ((m & (1L << 54)) != 0) {
- exp++;
- // renormalize
- m >>= 1;
- }
- // Check if a denormalized mantissa was just rounded up to a
- // normalized one.
- else if (ml == 52 && (m & (1L << 53)) != 0)
- exp++;
- }
-
- // Discard the rounding bit
- m >>= 1;
-
- long bits_sign = neg ? (1L << 63) : 0;
- exp += 1023;
- long bits_exp = (exp <= 0) ? 0 : ((long) exp) << 52;
- long bits_mant = m & ~(1L << 52);
- return Double.longBitsToDouble(bits_sign | bits_exp | bits_mant);
- }
-
- /**
- * Copy the abolute value of this into an array of words. Assumes
- * words.length >= (this.words == null ? 1 : this.ival). Result is
- * zero-extended, but need not be a valid 2's complement number.
- */
- private void getAbsolute(int[] words) {
- int len;
- if (this.words == null) {
- len = 1;
- words[0] = this.ival;
- } else {
- len = this.ival;
- for (int i = len; --i >= 0;)
- words[i] = this.words[i];
- }
- if (words[len - 1] < 0)
- negate(words, words, len);
- for (int i = words.length; --i > len;)
- words[i] = 0;
- }
-
- /**
- * Set dest[0:len-1] to the negation of src[0:len-1]. Return true if
- * overflow (i.e. if src is -2**(32*len-1)). Ok for src==dest.
- */
- private static boolean negate(int[] dest, int[] src, int len) {
- long carry = 1;
- boolean negative = src[len - 1] < 0;
- for (int i = 0; i < len; i++) {
- carry += ((~src[i]) & 0xffffffffL);
- dest[i] = (int) carry;
- carry >>= 32;
- }
- return (negative && dest[len - 1] < 0);
- }
-
- /**
- * Destructively set this to the negative of x. It is OK if x==this.
- */
- private void setNegative(BigIntegerCrypto x) {
- int len = x.ival;
- if (x.words == null) {
- if (len == Integer.MIN_VALUE)
- set(-(long) len);
- else
- set(-len);
- return;
- }
- realloc(len + 1);
- if (negate(words, x.words, len))
- words[len++] = 0;
- ival = len;
- }
-
- /** Destructively negate this. */
- private void setNegative() {
- setNegative(this);
- }
-
- private static BigIntegerCrypto abs(BigIntegerCrypto x) {
- return x.isNegative() ? neg(x) : x;
- }
-
- public BigIntegerCrypto abs() {
- return abs(this);
- }
-
- private static BigIntegerCrypto neg(BigIntegerCrypto x) {
- if (x.words == null && x.ival != Integer.MIN_VALUE)
- return valueOf(-x.ival);
- BigIntegerCrypto result = new BigIntegerCrypto(0);
- result.setNegative(x);
- return result.canonicalize();
- }
-
- public BigIntegerCrypto negate() {
- return neg(this);
- }
-
- /**
- * Calculates ceiling(log2(this < 0 ? -this : this+1)) See Common Lisp: the
- * Language, 2nd ed, p. 361.
- */
- public int bitLength() {
- if (words == null)
- return MPN.intLength(ival);
- return MPN.intLength(words, ival);
- }
-
- public byte[] toByteArray() {
- if (signum() == 0)
- return new byte[1];
-
- // Determine number of bytes needed. The method bitlength returns
- // the size without the sign bit, so add one bit for that and then
- // add 7 more to emulate the ceil function using integer math.
- byte[] bytes = new byte[(bitLength() + 1 + 7) / 8];
- int nbytes = bytes.length;
-
- int wptr = 0;
- int word;
-
- // Deal with words array until one word or less is left to process.
- // If BigInteger is an int, then it is in ival and nbytes will be <= 4.
- while (nbytes > 4) {
- word = words[wptr++];
- for (int i = 4; i > 0; --i, word >>= 8)
- bytes[--nbytes] = (byte) word;
- }
-
- // Deal with the last few bytes. If BigInteger is an int, use ival.
- word = (words == null) ? ival : words[wptr];
- for (; nbytes > 0; word >>= 8)
- bytes[--nbytes] = (byte) word;
-
- return bytes;
- }
-
- /**
- * Return the boolean opcode (for bitOp) for swapped operands. I.e.
- * bitOp(swappedOp(op), x, y) == bitOp(op, y, x).
- */
- private static int swappedOp(int op) {
- return "\000\001\004\005\002\003\006\007\010\011\014\015\012\013\016\017"
- .charAt(op);
- }
-
- /** Do one the the 16 possible bit-wise operations of two BigIntegers. */
- private static BigIntegerCrypto bitOp(int op, BigIntegerCrypto x,
- BigIntegerCrypto y) {
- switch (op) {
- case 0:
- return ZERO;
- case 1:
- return x.and(y);
- case 3:
- return x;
- case 5:
- return y;
- case 15:
- return valueOf(-1);
- }
- BigIntegerCrypto result = new BigIntegerCrypto();
- setBitOp(result, op, x, y);
- return result.canonicalize();
- }
-
- /** Do one the the 16 possible bit-wise operations of two BigIntegers. */
- private static void setBitOp(BigIntegerCrypto result, int op,
- BigIntegerCrypto x, BigIntegerCrypto y) {
- if ((y.words != null) && (x.words == null || x.ival < y.ival)) {
- BigIntegerCrypto temp = x;
- x = y;
- y = temp;
- op = swappedOp(op);
- }
- int xi;
- int yi;
- int xlen, ylen;
- if (y.words == null) {
- yi = y.ival;
- ylen = 1;
- } else {
- yi = y.words[0];
- ylen = y.ival;
- }
- if (x.words == null) {
- xi = x.ival;
- xlen = 1;
- } else {
- xi = x.words[0];
- xlen = x.ival;
- }
- if (xlen > 1)
- result.realloc(xlen);
- int[] w = result.words;
- int i = 0;
- // Code for how to handle the remainder of x.
- // 0: Truncate to length of y.
- // 1: Copy rest of x.
- // 2: Invert rest of x.
- int finish = 0;
- int ni;
- switch (op) {
- case 0: // clr
- ni = 0;
- break;
- case 1: // and
- for (;;) {
- ni = xi & yi;
- if (i + 1 >= ylen)
- break;
- w[i++] = ni;
- xi = x.words[i];
- yi = y.words[i];
- }
- if (yi < 0)
- finish = 1;
- break;
- case 2: // andc2
- for (;;) {
- ni = xi & ~yi;
- if (i + 1 >= ylen)
- break;
- w[i++] = ni;
- xi = x.words[i];
- yi = y.words[i];
- }
- if (yi >= 0)
- finish = 1;
- break;
- case 3: // copy x
- ni = xi;
- finish = 1; // Copy rest
- break;
- case 4: // andc1
- for (;;) {
- ni = ~xi & yi;
- if (i + 1 >= ylen)
- break;
- w[i++] = ni;
- xi = x.words[i];
- yi = y.words[i];
- }
- if (yi < 0)
- finish = 2;
- break;
- case 5: // copy y
- for (;;) {
- ni = yi;
- if (i + 1 >= ylen)
- break;
- w[i++] = ni;
- xi = x.words[i];
- yi = y.words[i];
- }
- break;
- case 6: // xor
- for (;;) {
- ni = xi ^ yi;
- if (i + 1 >= ylen)
- break;
- w[i++] = ni;
- xi = x.words[i];
- yi = y.words[i];
- }
- finish = yi < 0 ? 2 : 1;
- break;
- case 7: // ior
- for (;;) {
- ni = xi | yi;
- if (i + 1 >= ylen)
- break;
- w[i++] = ni;
- xi = x.words[i];
- yi = y.words[i];
- }
- if (yi >= 0)
- finish = 1;
- break;
- case 8: // nor
- for (;;) {
- ni = ~(xi | yi);
- if (i + 1 >= ylen)
- break;
- w[i++] = ni;
- xi = x.words[i];
- yi = y.words[i];
- }
- if (yi >= 0)
- finish = 2;
- break;
- case 9: // eqv [exclusive nor]
- for (;;) {
- ni = ~(xi ^ yi);
- if (i + 1 >= ylen)
- break;
- w[i++] = ni;
- xi = x.words[i];
- yi = y.words[i];
- }
- finish = yi >= 0 ? 2 : 1;
- break;
- case 10: // c2
- for (;;) {
- ni = ~yi;
- if (i + 1 >= ylen)
- break;
- w[i++] = ni;
- xi = x.words[i];
- yi = y.words[i];
- }
- break;
- case 11: // orc2
- for (;;) {
- ni = xi | ~yi;
- if (i + 1 >= ylen)
- break;
- w[i++] = ni;
- xi = x.words[i];
- yi = y.words[i];
- }
- if (yi < 0)
- finish = 1;
- break;
- case 12: // c1
- ni = ~xi;
- finish = 2;
- break;
- case 13: // orc1
- for (;;) {
- ni = ~xi | yi;
- if (i + 1 >= ylen)
- break;
- w[i++] = ni;
- xi = x.words[i];
- yi = y.words[i];
- }
- if (yi >= 0)
- finish = 2;
- break;
- case 14: // nand
- for (;;) {
- ni = ~(xi & yi);
- if (i + 1 >= ylen)
- break;
- w[i++] = ni;
- xi = x.words[i];
- yi = y.words[i];
- }
- if (yi < 0)
- finish = 2;
- break;
- default:
- case 15: // set
- ni = -1;
- break;
- }
- // Here i==ylen-1; w[0]..w[i-1] have the correct result;
- // and ni contains the correct result for w[i+1].
- if (i + 1 == xlen)
- finish = 0;
- switch (finish) {
- case 0:
- if (i == 0 && w == null) {
- result.ival = ni;
- return;
- }
- w[i++] = ni;
- break;
- case 1:
- w[i] = ni;
- while (++i < xlen)
- w[i] = x.words[i];
- break;
- case 2:
- w[i] = ni;
- while (++i < xlen)
- w[i] = ~x.words[i];
- break;
- }
- result.ival = i;
- }
-
- /** Return the logical (bit-wise) "and" of a BigInteger and an int. */
- private static BigIntegerCrypto and(BigIntegerCrypto x, int y) {
- if (x.words == null)
- return valueOf(x.ival & y);
- if (y >= 0)
- return valueOf(x.words[0] & y);
- int len = x.ival;
- int[] words = new int[len];
- words[0] = x.words[0] & y;
- while (--len > 0)
- words[len] = x.words[len];
- return make(words, x.ival);
- }
-
- /** Return the logical (bit-wise) "and" of two BigIntegers. */
- public BigIntegerCrypto and(BigIntegerCrypto y) {
- if (y.words == null)
- return and(this, y.ival);
- else if (words == null)
- return and(y, ival);
-
- BigIntegerCrypto x = this;
- if (ival < y.ival) {
- BigIntegerCrypto temp = this;
- x = y;
- y = temp;
- }
- int i;
- int len = y.isNegative() ? x.ival : y.ival;
- int[] words = new int[len];
- for (i = 0; i < y.ival; i++)
- words[i] = x.words[i] & y.words[i];
- for (; i < len; i++)
- words[i] = x.words[i];
- return make(words, len);
- }
-
- /** Return the logical (bit-wise) "(inclusive) or" of two BigIntegers. */
- public BigIntegerCrypto or(BigIntegerCrypto y) {
- return bitOp(7, this, y);
- }
-
- /** Return the logical (bit-wise) "exclusive or" of two BigIntegers. */
- public BigIntegerCrypto xor(BigIntegerCrypto y) {
- return bitOp(6, this, y);
- }
-
- /** Return the logical (bit-wise) negation of a BigInteger. */
- public BigIntegerCrypto not() {
- return bitOp(12, this, ZERO);
- }
-
- public BigIntegerCrypto andNot(BigIntegerCrypto val) {
- return and(val.not());
- }
-
- public BigIntegerCrypto clearBit(int n) {
- if (n < 0)
- throw new ArithmeticException();
-
- return and(ONE.shiftLeft(n).not());
- }
-
- public BigIntegerCrypto setBit(int n) {
- if (n < 0)
- throw new ArithmeticException();
-
- return or(ONE.shiftLeft(n));
- }
-
- public boolean testBit(int n) {
- if (n < 0)
- throw new ArithmeticException();
-
- return !and(ONE.shiftLeft(n)).isZero();
- }
-
- public BigIntegerCrypto flipBit(int n) {
- if (n < 0)
- throw new ArithmeticException();
-
- return xor(ONE.shiftLeft(n));
- }
-
- public int getLowestSetBit() {
- if (isZero())
- return -1;
-
- if (words == null)
- return MPN.findLowestBit(ival);
- else
- return MPN.findLowestBit(words);
- }
-
- // bit4count[I] is number of '1' bits in I.
- private static final byte[] bit4_count = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2,
- 3, 2, 3, 3, 4 };
-
- private static int bitCount(int i) {
- int count = 0;
- while (i != 0) {
- count += bit4_count[i & 15];
- i >>>= 4;
- }
- return count;
- }
-
- private static int bitCount(int[] x, int len) {
- int count = 0;
- while (--len >= 0)
- count += bitCount(x[len]);
- return count;
- }
-
- /**
- * Count one bits in a BigInteger. If argument is negative, count zero bits
- * instead.
- */
- public int bitCount() {
- int i, x_len;
- int[] x_words = words;
- if (x_words == null) {
- x_len = 1;
- i = bitCount(ival);
- } else {
- x_len = ival;
- i = bitCount(x_words, x_len);
- }
- return isNegative() ? x_len * 32 - i : i;
- }
-
- private void readObject(ObjectInputStream s) throws IOException,
- ClassNotFoundException {
- s.defaultReadObject();
- if (magnitude.length == 0 || signum == 0) {
- this.ival = 0;
- this.words = null;
- } else {
- words = byteArrayToIntArray(magnitude, signum < 0 ? -1 : 0);
- Arrays.fill(magnitude, (byte)0); // crypto: clear temporary content
- BigIntegerCrypto result = make(words, words.length);
- this.ival = result.ival;
- this.words = result.words;
- }
- }
-
- private void writeObject(ObjectOutputStream s) throws IOException {
- signum = signum();
- magnitude = signum == 0 ? new byte[0] : toByteArray();
- s.defaultWriteObject();
- Arrays.fill(magnitude, (byte)0); // crypto: clear temporary content
- magnitude = null; // not needed anymore
- }
-
- // inner class(es)
- // ..........................................................
-
-}
diff --git a/src/gnu/java/bigintcrypto/test/BigIntCryptoDHTest.java b/src/gnu/java/bigintcrypto/test/BigIntCryptoDHTest.java
deleted file mode 100755
index 7f3fd0e..0000000
--- a/src/gnu/java/bigintcrypto/test/BigIntCryptoDHTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package gnu.java.bigintcrypto.test;
-
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-
-import java.security.SecureRandom;
-
-/**
- * Class to test and check required crypto algorithms.
- *
- */
-public class BigIntCryptoDHTest {
-
- // The DH prime for DH3k (3072 bit) as defined in RFC 3526
- public static final BigIntegerCrypto P3072 = new BigIntegerCrypto(
-// 1 2
-// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 24 bytes per line
- "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + // 0
- "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + // 1
- "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + // 2
- "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + // 3
- "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + // 4
- "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + // 5
- "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + // 6
- "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + // 7
- "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + // 8
- "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + // 9
- "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + // 10
- "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + // 11
- "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + // 12
- "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + // 13
- "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + // 14
- "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF", 16); // 15, total = 24 * 16 = 384
-
- // DH generator 2
- public static final BigIntegerCrypto two = BigIntegerCrypto.valueOf(2);
-
- private SecureRandom secRand = new SecureRandom();
-
-
- public void testManyPub() {
- BigIntegerCrypto x;
-
- for (int i = 0; i < 20; i++) {
-
- do {
- x = new BigIntegerCrypto(256, 0, secRand);
- } while (x.equals(BigIntegerCrypto.ZERO));
-
- two.modPow(x, P3072);
- System.out.print(i + " ");
- }
- }
-
- public static void main(String[] args) {
-
- BigIntCryptoDHTest ct = new BigIntCryptoDHTest();
- ct.testManyPub();
-
- System.out.println("Test done");
- System.exit(0);
- }
-
-}
diff --git a/src/gnu/java/bigintcrypto/test/BigIntegerCryptoTest.java b/src/gnu/java/bigintcrypto/test/BigIntegerCryptoTest.java
deleted file mode 100755
index a7b689a..0000000
--- a/src/gnu/java/bigintcrypto/test/BigIntegerCryptoTest.java
+++ /dev/null
@@ -1,555 +0,0 @@
-/**
- * Copyright (C) 2006-2008 Werner Dittmann
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see + * This class is a modified variant of the original Fortuna generator in GNU + * Classpath (see note below). The class now uses the Bouncycastle hash and + * cipher classes and provides a Bouncycastle compliant interface. + *
+ * Fortuna is a continuously-seeded pseudo-random number generator (PRNG) + * and is composed of two major pieces: the entropy accumulator and the + * generator function. The former takes in random bits and incorporates them + * into the generator's state. The latter takes this base entropy and generates + * pseudo-random bits from it. + *
+ * Here an example how to use the FortunaGenerator (pseudo code): + * + *
+ * ... + * new Random().nextBytes(firstSeed) // get some random data + * FortunaGenerator fg = new FortunaGenerator(firstSeed); + * ... + * + * fg.nextBytes(randomData) + * ... + * fg.addSeedMaterial(entropyData) + * + *+ * + * After some time the application has done its work and exits. To enable + * a fast restart of the FortunaGenerator you may store the seed status + * and initialize the FortunaGenerator with this seed the next time. For + * example: + * + *
+ * ... // use FortunaGenerator + * seedStatus = fg.getSeedStatus() + * + * // save seed status somewhere + * // exit application + * ... + * // restart application + * if (saved seed status available) + * read seed status data + * FortunaGenerator fg = new FortunaGenerator() + * fg.setSeedStatus(seed status data) + * // alternatively you can do + * FortunaGenerator = new FortunaGenerator(seed status data) + * // use FortunaGenerator + * + *+ * + * There are some things users of this class must be aware of: + *
+ * References: + *
+ * License: the Bouncycastle license applies to this file. Also notice the GNU + * Classpath license exception (see below). + *
+ * Copyright (C) 2010 Werner Dittmann (Werner.Dittmann@t-online.de)
+ * Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+ *
+ */
+
+/*
+ * Copyright note of the original Fortuna source. Not that THIS file is not
+ * longer part of GNU Classpath.
+ *
+ * Fortuna.java -- The Fortuna PRNG.
+Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+public class FortunaGenerator implements RandomGenerator {
+
+ private static final int SEED_FILE_SIZE = 64;
+ private static final int NUM_POOLS = 32;
+ private static final int MIN_POOL_SIZE = 64;
+ private final Generator generator;
+ private final Digest[] pools;
+ private long lastReseed = 0;
+ private int pool = 0;
+ private int pool0Count = 0;
+ private int reseedCount = 0;
+ private boolean initialized = false;
+
+ /** A temporary buffer to serve random bytes. */
+ private byte[] buffer;
+
+ /** The index into buffer of where the next byte will come from. */
+ protected int ndx = 0;
+
+ public FortunaGenerator() {
+ this(null);
+ }
+
+ public FortunaGenerator(byte[] seed) {
+ generator = new Generator(new AESFastEngine(), new SHA256Digest());
+ pools = new Digest[NUM_POOLS];
+ for (int i = 0; i < NUM_POOLS; i++)
+ pools[i] = new SHA256Digest();
+ buffer = new byte[256];
+ if (seed != null) {
+ generator.init(seed);
+ fillBlock();
+ initialized = true;
+ }
+ }
+
+ private void fillBlock() {
+ if (pool0Count >= MIN_POOL_SIZE
+ && System.currentTimeMillis() - lastReseed > 100)
+ {
+ long powerOfTwo = 1;
+ reseedCount++;
+ byte[] randomBytes = new byte[pools[0].getDigestSize()];
+ for (int i = 0; i < NUM_POOLS; i++) {
+ if (i == 0 || reseedCount % powerOfTwo == 0) {
+ pools[i].doFinal(randomBytes, 0);
+ generator.addRandomBytes(randomBytes, 0, randomBytes.length);
+ }
+ else
+ break;
+
+ powerOfTwo <<= 1;
+ }
+ lastReseed = System.currentTimeMillis();
+ pool0Count = 0;
+ }
+ generator.nextBytes(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Get new random data.
+ *
+ * This functions fills a byte buffer with new random data. + * + * @param out the buffer that receives the random data + */ + public void nextBytes(byte[] out) { + nextBytes(out, 0, out.length); + } + + /** + * Get new random data. + *
+ * This functions returns new random data. + * + * @param out the buffer that receives the random data + * @param offset offset into the buffer + * @param length number of random bytes + */ + public void nextBytes(byte[] out, int offset, int length) { + if (!initialized) + throw new IllegalStateException(" Fortuna generator not initialized/seeded"); + + if (length == 0) + return; + + if (offset < 0 || length < 0 || offset + length > out.length) + throw new ArrayIndexOutOfBoundsException("offset=" + offset + " length=" + + length + " limit=" + + out.length); + + if (ndx >= buffer.length) { + fillBlock(); + ndx = 0; + } + int count = 0; + while (count < length) { + int amount = Math.min(buffer.length - ndx, length - count); + System.arraycopy(buffer, ndx, out, offset + count, amount); + count += amount; + ndx += amount; + if (ndx >= buffer.length) { + fillBlock(); + ndx = 0; + } + } + } + + /** + * Adds new random data (entropy) to an entropy pool. + *
+ * This functions adds entropy data to the current pool. Fortuna uses + * 32 pools to gather entropy. After the function added the entropy to + * the pool it increments the current pool number modulo 32. + *
+ * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna + * uses the pools to perform a real re-seed. If an application uses this + * function to add entropy it shall take this behaviour into consideration. + * + * @param b a long with new entropy data. If the current pool is 0 then + * the function adds the length of a long to the overall + * entropy count that controls re-seed. + */ + public void addSeedMaterial(long b) { + pools[pool].update((byte)(b & 0xff)); + pools[pool].update((byte)((b >> 8) & 0xff)); + pools[pool].update((byte)((b >> 16) & 0xff)); + pools[pool].update((byte)((b >> 24) & 0xff)); + pools[pool].update((byte)((b >> 32) & 0xff)); + pools[pool].update((byte)((b >> 40) & 0xff)); + pools[pool].update((byte)((b >> 48) & 0xff)); + pools[pool].update((byte)((b >> 56) & 0xff)); + if (pool == 0) + pool0Count += 8; + pool = (pool + 1) % NUM_POOLS; + } + + /** + * Adds new random data (entropy) to an entropy pool. + *
+ * This functions adds entropy data to the current pool. Fortuna uses + * 32 pools to gather entropy. After the function added the entropy to + * the pool it increments the current pool number modulo 32. + *
+ * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna + * uses the pools to perform a real re-seed. If an application uses this + * function to add entropy it shall take this behaviour into consideration. + * + * @param buf buffer with new entropy data. If the current pool is 0 then + * the function adds the length of the buffer to the overall + * entropy count that controls re-seed. + */ + public void addSeedMaterial(byte[] buf) { + addSeedMaterial(buf, 0, buf.length); + } + + /** + * Adds new random data (entropy) to an entropy pool. + *
+ * This functions adds entropy data to the current pool. Fortuna uses + * 32 pools to gather entropy. After the function added the entropy to + * the pool it increments the current pool number modulo 32. + *
+ * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna + * uses the pools to perform a real re-seed. If an application uses this + * function to add entropy it shall take this behaviour into consideration. + * + * @param buf buffer with new entropy data. + * @param offset offset into the buffer + * @param length number of bytes to add to the current pool's entropy. + * If the current pool is 0 then the function adds the length + * of the buffer to the overall entropy count that controls + * re-seed. + */ + public void addSeedMaterial(byte[] buf, int offset, int length) { + pools[pool].update(buf, offset, length); + if (pool == 0) + pool0Count += buf.length; + pool = (pool + 1) % NUM_POOLS; + } + + /** + * Adds new random data (entropy) to the specified entropy pool. + *
+ * This functions adds entropy data to the the specified pool. Fortuna + * uses32 pools to gather entropy. + *
+ * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna + * uses the pools to perform a real re-seed. If an application uses this + * function to add entropy it shall take this behaviour into consideration. + * + * @param poolNumber specifies which pool receives the entropy data + * @param data buffer with new entropy data. + * @param offset offset into the buffer + * @param length number of bytes to add to the specified pool's entropy. + * If the specified pool is 0 then the function adds the length + * of the data to the overall entropy count that controls + * re-seed. + */ + public void addSeedMaterial(int poolNumber, byte[] data, int offset, int length) { + if (poolNumber < 0 || poolNumber >= pools.length) + throw new IllegalArgumentException("pool number out of range: " + + poolNumber); + pools[poolNumber].update((byte)length); + pools[poolNumber].update(data, offset, length); + if (poolNumber == 0) + pool0Count += length; + } + + + /** + * Return the generator's seed status. + *
+ * An application may get the seed status, store it in a safe place
+ * and retrieve it to seed a new Fortuna PRNG instance.
+ *
+ * @return The seed status.
+ */
+ public byte[] getSeedStatus() {
+ byte[] seed = new byte[SEED_FILE_SIZE];
+ generator.nextBytes(seed, 0, seed.length);
+ return seed;
+ }
+
+ /**
+ * Seed the generator with a previously saved seed.
+ *
+ * @param seedStatus the generator's seed.
+ */
+ public void setSeedStatus(byte[] seedStatus) {
+ generator.init(seedStatus);
+ fillBlock();
+ initialized = true;
+ }
+
+ /**
+ * The Fortuna generator function. The generator is a PRNG in its own right;
+ * Fortuna itself is basically a wrapper around this generator that manages
+ * re-seeding in a secure way.
+ */
+ private static class Generator {
+ private static final int LIMIT = 1 << 20;
+ private final BlockCipher cipher;
+ private final Digest hash;
+ private final byte[] counter;
+ private final byte[] key;
+
+ /** A temporary buffer to serve random bytes. */
+ private byte[] buffer;
+
+ /** The index into buffer of where the next byte will come from. */
+ protected int ndx = 0;
+
+ private Generator(final BlockCipher cipher, final Digest hash)
+ {
+ this.cipher = cipher;
+ this.hash = hash;
+ counter = new byte[cipher.getBlockSize()];
+ buffer = new byte[cipher.getBlockSize()];
+ key = new byte[32];
+ }
+
+ private void nextBytes(byte[] out, int offset, int length) {
+
+ int count = 0;
+ do {
+ int amount = Math.min(LIMIT, length - count);
+ nextBytesInternal(out, offset + count, amount);
+ count += amount;
+ for (int i = 0; i < key.length; i += counter.length) {
+ fillBlock();
+ int l = Math.min(key.length - i, cipher.getBlockSize());
+ System.arraycopy(buffer, 0, key, i, l);
+ }
+ resetKey();
+ } while (count < length);
+
+ fillBlock();
+ ndx = 0;
+ }
+
+ private void addRandomBytes(byte[] seed, int offset, int length) {
+ hash.update(key, 0, key.length);
+ hash.update(seed, offset, length);
+ byte[] newkey = new byte[hash.getDigestSize()];
+ hash.doFinal(newkey, 0);
+ System.arraycopy(newkey, 0, key, 0, Math.min(key.length, newkey.length));
+ resetKey();
+ incrementCounter();
+ }
+
+ private void fillBlock() {
+ cipher.processBlock(counter, 0, buffer, 0);
+ incrementCounter();
+ }
+
+ private void init(byte[] seed) {
+ Arrays.fill(key, (byte) 0);
+ Arrays.fill(counter, (byte) 0);
+ if (seed != null)
+ addRandomBytes(seed, 0, seed.length);
+ fillBlock();
+ }
+
+ private void nextBytesInternal(byte[] out, int offset, int length) {
+
+ if (length == 0)
+ return;
+
+ if (offset < 0 || length < 0 || offset + length > out.length)
+ throw new ArrayIndexOutOfBoundsException("offset=" + offset + " length="
+ + length + " limit="
+ + out.length);
+ if (ndx >= buffer.length) {
+ fillBlock();
+ ndx = 0;
+ }
+ int count = 0;
+ while (count < length) {
+ int amount = Math.min(buffer.length - ndx, length - count);
+ System.arraycopy(buffer, ndx, out, offset + count, amount);
+ count += amount;
+ ndx += amount;
+ if (ndx >= buffer.length) {
+ fillBlock();
+ ndx = 0;
+ }
+ }
+ }
+
+ /**
+ * Resets the cipher's key. This is done after every reseed, which combines
+ * the old key and the seed, and processes that through the hash function.
+ */
+ private void resetKey() {
+ cipher.reset();
+ cipher.init(true, new KeyParameter(key));
+ }
+
+ /**
+ * Increment `counter' as a sixteen-byte little-endian unsigned integer by
+ * one.
+ */
+ private void incrementCounter() {
+ for (int i = 0; i < counter.length; i++) {
+ counter[i]++;
+ if (counter[i] != 0)
+ break;
+ }
+ }
+ }
+}
+
diff --git a/src/gnu/java/zrtp/utils/FortunaSecureRandom.java b/src/gnu/java/zrtp/utils/FortunaSecureRandom.java
new file mode 100644
index 0000000..283b4d6
--- /dev/null
+++ b/src/gnu/java/zrtp/utils/FortunaSecureRandom.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 Ingo Bauersachs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
- * This class manages a Fortuna PRNG generator instance and maintains access. - * Thus all threads of an application can contribute entropy data to the same - * Fortuna PRNG instance. The quality of random data enhances if an application - * is able to add more entropy data. - *
- * If a thread requires random data it should use the methods of this class to - * get high quality random data. - *
- * ZrtpFortuna always creates a Fortuna generator instance and initializes the
- * seed with some random data. An application may set another initialized
- * Fortuna instance using the setFortuna() method after calling
- * getInstance(). An application may use this feature to use a
- * Fortuna instance that was initialized with a saved seed (
- * org.bouncycastle.crypto.prng. FortunaGenerator)
- *
- */
-public class ZrtpFortuna implements RandomGenerator {
-
- static private ZrtpFortuna singleInstance = null;
- private FortunaGenerator fortuna = null;
-
- protected ZrtpFortuna() {
- }
-
- synchronized static public ZrtpFortuna getInstance() {
- if (singleInstance == null) {
- singleInstance = new ZrtpFortuna();
- singleInstance.initialize();
- }
- return singleInstance;
- }
-
- private void initialize() {
- byte[] someData = new byte[256];
- new SecureRandom().nextBytes(someData);
- fortuna = new FortunaGenerator(someData);
- }
-
- /**
- * Get the Fortuna instance.
- *
- * @return The Fortuna instance.
- */
- public FortunaGenerator getFortuna() {
- return fortuna;
- }
-
- /**
- * Set the Fortuna instance.
- *
- * @param fortuna
- * The Fortuna instance to use.
- */
- synchronized public void setFortuna(FortunaGenerator fortuna) {
- this.fortuna = fortuna;
- }
-
- /**
- * Adds new random data (entropy) to a entropy pool.
- *
- * This functions adds entropy data to the current pool. Fortuna uses 32
- * pools to gather entropy. After the function added the entropy to the pool
- * it increments the current pool number modulo 32.
- *
- * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna - * uses the pools to perform a real re-seed. If an application uses this - * function to add entropy it shall take this behaviour into consideration. - * - * @param entropy - * with new entropy data. If the current pool is 0 then the - * function adds the length of the buffer to the overall entropy - * count that controls re-seed. - */ - synchronized public void addSeedMaterial(byte[] entropy) { - fortuna.addSeedMaterial(entropy); - } - - /** - * Adds new random data (entropy) to a entropy pool. - * - * This functions adds entropy data to the current pool. Fortuna uses 32 - * pools to gather entropy. After the function added the entropy to the pool - * it increments the current pool number modulo 32. - *
- * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna - * uses the pools to perform a real re-seed. If an application uses this - * function to add entropy it shall take this behaviour into consideration. - * - * @param entropy - * a long with new entropy data. If the current pool is 0 then - * the function adds the length of a long to the overall entropy - * count that controls re-seed. - */ - synchronized public void addSeedMaterial(long entropy) { - fortuna.addSeedMaterial(entropy); - } - - /** - * Adds new random data (entropy) to a entropy pool. - * - * This functions adds entropy data to the current pool. Fortuna uses 32 - * pools to gather entropy. After the function added the entropy to the pool - * it increments the current pool number modulo 32. - *
- * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna - * uses the pools to perform a real re-seed. If an application uses this - * function to add entropy it shall take this behaviour into consideration. - * - * @param entropy - * buffer with new entropy data. - * @param offset - * offset into the buffer - * @param length - * number of bytes to add to the current pool's entropy. If the - * current pool is 0 then the function adds the length of the - * entropy to the overall entropy count that controls re-seed. - */ - synchronized public void addSeedMaterial(byte[] entropy, int offset, int length) { - fortuna.addSeedMaterial(entropy, offset, length); - } - - /** - * Adds new random data (entropy) to the specified entropy pool. - * - * This functions adds entropy data to the the specified pool. Fortuna - * uses32 pools to gather entropy. - *
- * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna
- * uses the pools to perform a real re-seed. If an application uses this
- * function to add entropy it shall take this behaviour into consideration.
- *
- * @param poolNumber
- * specifies which pool receives the entropy data
- * @param entropy
- * buffer with new entropy data.
- * @param offset
- * offset into the buffer
- * @param length
- * number of bytes to add to the specified pool's entropy. If the
- * specified pool is 0 then the function adds the length of the
- * entropy to the overall entropy count that controls re-seed.
- */
- synchronized public void addSeedMaterial(int poolNumber, byte[] entropy,
- int offset, int length) {
- fortuna.addSeedMaterial(poolNumber, entropy, offset, length);
- }
-
- /**
- * Get new random data.
- *
- * This functions fills a byte buffer with new random data.
- *
- * @param randomData
- * the buffer that receives the random data
- */
- synchronized public void nextBytes(byte[] randomData) {
- fortuna.nextBytes(randomData);
- }
-
- /**
- * Get new random data.
- *
- * This functions returns new random data.
- *
- * @param randomData
- * the buffer that receives the random data
- * @param offset
- * offset into the buffer
- * @param length
- * number of random bytes
- */
- synchronized public void nextBytes(byte[] randomData, int offset, int length) {
- fortuna.nextBytes(randomData, offset, length);
- }
-}
diff --git a/src/gnu/java/zrtp/utils/ZrtpSecureRandom.java b/src/gnu/java/zrtp/utils/ZrtpSecureRandom.java
new file mode 100644
index 0000000..0bd20cf
--- /dev/null
+++ b/src/gnu/java/zrtp/utils/ZrtpSecureRandom.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 Ingo Bauersachs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
- * Clears all known agreement data and resets the agreement. To use the - * agreement againt the application must initialize it again. - */ - - void clear(); -} \ No newline at end of file diff --git a/src/org/bouncycastle/cryptozrtp/CipherParameters.java b/src/org/bouncycastle/cryptozrtp/CipherParameters.java deleted file mode 100755 index d5ff291..0000000 --- a/src/org/bouncycastle/cryptozrtp/CipherParameters.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.bouncycastle.cryptozrtp; - -/** - * all parameter classes implement this. - */ -public interface CipherParameters -{ -} diff --git a/src/org/bouncycastle/cryptozrtp/KeyGenerationParameters.java b/src/org/bouncycastle/cryptozrtp/KeyGenerationParameters.java deleted file mode 100755 index cb0689c..0000000 --- a/src/org/bouncycastle/cryptozrtp/KeyGenerationParameters.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.bouncycastle.cryptozrtp; - -import org.bouncycastle.crypto.prng.RandomGenerator; -/** - * The base class for parameters to key generators. - */ -public class KeyGenerationParameters -{ - private RandomGenerator random; - private int strength; - - /** - * initialise the generator with a source of randomness - * and a strength (in bits). - * - * @param random the random byte source. - * @param strength the size, in bits, of the keys we want to produce. - */ - public KeyGenerationParameters( - RandomGenerator random, - int strength) - { - this.random = random; - this.strength = strength; - } - - /** - * return the random source associated with this - * generator. - * - * @return the generators random source. - */ - public RandomGenerator getRandom() - { - return random; - } - - /** - * return the bit strength for keys produced by this generator, - * - * @return the strength of the keys this generator produces (in bits). - */ - public int getStrength() - { - return strength; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/agreement/DHAgreement.java b/src/org/bouncycastle/cryptozrtp/agreement/DHAgreement.java deleted file mode 100755 index c96fbb1..0000000 --- a/src/org/bouncycastle/cryptozrtp/agreement/DHAgreement.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.bouncycastle.cryptozrtp.agreement; - -import gnu.java.bigintcrypto.BigIntegerCrypto; -import java.security.SecureRandom; - -import org.bouncycastle.cryptozrtp.CipherParameters; -import org.bouncycastle.cryptozrtp.params.DHParameters; -import org.bouncycastle.cryptozrtp.params.DHPublicKeyParameters; -import org.bouncycastle.cryptozrtp.params.DHPrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.AsymmetricKeyParameter; -import org.bouncycastle.cryptozrtp.params.ParametersWithRandom; - -/** - * a Diffie-Hellman key exchange engine. - *
- * note: This uses MTI/A0 key agreement in order to make the key agreement - * secure against passive attacks. If you're doing Diffie-Hellman and both - * parties have long term public keys you should look at using this. For - * further information have a look at RFC 2631. - *
- * It's possible to extend this to more than two parties as well, for the moment - * that is left as an exercise for the reader. - */ -public class DHAgreement -{ - private DHPrivateKeyParameters key; - private DHParameters dhParams; - private BigIntegerCrypto privateValue; - private SecureRandom random; - - public void init( - CipherParameters param) - { - AsymmetricKeyParameter kParam; - - if (param instanceof ParametersWithRandom) - { - ParametersWithRandom rParam = (ParametersWithRandom)param; - - this.random = rParam.getRandom(); - kParam = (AsymmetricKeyParameter)rParam.getParameters(); - } - else - { - this.random = new SecureRandom(); - kParam = (AsymmetricKeyParameter)param; - } - - - if (!(kParam instanceof DHPrivateKeyParameters)) - { - throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters"); - } - - this.key = (DHPrivateKeyParameters)kParam; - this.dhParams = key.getParameters(); - } - - /** - * calculate our initial message. - */ - public BigIntegerCrypto calculateMessage() - { - int bits = dhParams.getP().bitLength() - 1; - - // TODO Should the generated numbers always have length 'p.bitLength() - 1'? - this.privateValue = new BigIntegerCrypto(bits, random).setBit(bits - 1); - - return dhParams.getG().modPow(privateValue, dhParams.getP()); - } - - /** - * given a message from a given party and the corresponding public key, - * calculate the next message in the agreement sequence. In this case - * this will represent the shared secret. - */ - public BigIntegerCrypto calculateAgreement( - DHPublicKeyParameters pub, - BigIntegerCrypto message) - { - if (!pub.getParameters().equals(dhParams)) - { - throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters."); - } - - return message.modPow(key.getX(), dhParams.getP()).multiply(pub.getY().modPow(privateValue, dhParams.getP())).mod(dhParams.getP()); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/agreement/DHBasicAgreement.java b/src/org/bouncycastle/cryptozrtp/agreement/DHBasicAgreement.java deleted file mode 100755 index 273a23b..0000000 --- a/src/org/bouncycastle/cryptozrtp/agreement/DHBasicAgreement.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.bouncycastle.cryptozrtp.agreement; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -import org.bouncycastle.cryptozrtp.BasicAgreement; -import org.bouncycastle.cryptozrtp.CipherParameters; -import org.bouncycastle.cryptozrtp.params.DHParameters; -import org.bouncycastle.cryptozrtp.params.DHPublicKeyParameters; -import org.bouncycastle.cryptozrtp.params.DHPrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.AsymmetricKeyParameter; -import org.bouncycastle.cryptozrtp.params.ParametersWithRandom; - -/** - * a Diffie-Hellman key agreement class. - *
- * note: This is only the basic algorithm, it doesn't take advantage of - * long term public keys if they are available. See the DHAgreement class - * for a "better" implementation. - */ -public class DHBasicAgreement - implements BasicAgreement -{ - private DHPrivateKeyParameters key; - private DHParameters dhParams; - - public void init( - CipherParameters param) - { - AsymmetricKeyParameter kParam; - - if (param instanceof ParametersWithRandom) - { - ParametersWithRandom rParam = (ParametersWithRandom)param; - kParam = (AsymmetricKeyParameter)rParam.getParameters(); - } - else - { - kParam = (AsymmetricKeyParameter)param; - } - - if (!(kParam instanceof DHPrivateKeyParameters)) - { - throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters"); - } - - this.key = (DHPrivateKeyParameters)kParam; - this.dhParams = key.getParameters(); - } - - /** - * given a short term public key from a given party calculate the next - * message in the agreement sequence. - */ - public BigIntegerCrypto calculateAgreement( - CipherParameters pubKey) - { - DHPublicKeyParameters pub = (DHPublicKeyParameters)pubKey; - - if (!pub.getParameters().equals(dhParams)) - { - throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters."); - } - - return pub.getY().modPow(key.getX(), dhParams.getP()); - } - - /** - * Clear agreement data including private key data. - * - * Clears all known agreement data and resets the agreement. To use the - * agreement againt the application must initialize it again. - */ - - public void clear() { - key.getX().zeroize(); // clear private key data - key = null; - dhParams = null; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/agreement/Djb25519DHBasicAgreement.java b/src/org/bouncycastle/cryptozrtp/agreement/Djb25519DHBasicAgreement.java deleted file mode 100755 index 1cbd24a..0000000 --- a/src/org/bouncycastle/cryptozrtp/agreement/Djb25519DHBasicAgreement.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.bouncycastle.cryptozrtp.agreement; - -import djb.Curve25519; -import gnu.java.bigintcrypto.BigIntegerCrypto; -import org.bouncycastle.cryptozrtp.BasicAgreement; -import org.bouncycastle.cryptozrtp.CipherParameters; -import org.bouncycastle.cryptozrtp.params.Djb25519PrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.Djb25519PublicKeyParameters; -import org.bouncycastle.cryptozrtp.params.ECPrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.ECPublicKeyParameters; -import org.bouncycastle.mathzrtp.ec.ECPoint; - -import java.util.Arrays; - - -/** - * P1363 7.2.1 ECSVDP-DH - * - * ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive, - * Diffie-Hellman version. It is based on the work of [DH76], [Mil86], - * and [Kob87]. This primitive derives a shared secret value from one - * party's private key and another party's public key, where both have - * the same set of EC domain parameters. If two parties correctly - * execute this primitive, they will produce the same output. This - * primitive can be invoked by a scheme to derive a shared secret key; - * specifically, it may be used with the schemes ECKAS-DH1 and - * DL/ECKAS-DH2. It assumes that the input keys are valid (see also - * Section 7.2.2). - */ -public class Djb25519DHBasicAgreement implements BasicAgreement -{ - private Djb25519PrivateKeyParameters key; - - public void init(CipherParameters key) { - this.key = (Djb25519PrivateKeyParameters)key; - } - - public BigIntegerCrypto calculateAgreement(CipherParameters pubKey) { - Djb25519PublicKeyParameters pub = (Djb25519PublicKeyParameters)pubKey; - byte[] P = pub.getP(); - - /* Key agreement - * Z [out] shared secret (needs hashing before use) - * k [in] your private key for key agreement - * P [in] peer's public key - */ - byte[] Z = new byte[Curve25519.KEY_SIZE]; - Curve25519.curve(Z, key.getK(), P); - - // Return a BigInteger, use only as a byte array transport and to keep the API - return new BigIntegerCrypto(1, Z); - } - /** - * Clear agreement data including private key data. - * - * Clears all known agreement data and resets the agreement. To use the - * agreement againt the application must initialize it again. - */ - - public void clear() { - Arrays.fill(key.getK(), (byte)0); - key = null; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/agreement/ECDHBasicAgreement.java b/src/org/bouncycastle/cryptozrtp/agreement/ECDHBasicAgreement.java deleted file mode 100755 index 66baee1..0000000 --- a/src/org/bouncycastle/cryptozrtp/agreement/ECDHBasicAgreement.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.bouncycastle.cryptozrtp.agreement; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -import org.bouncycastle.mathzrtp.ec.ECPoint; - -import org.bouncycastle.cryptozrtp.BasicAgreement; -import org.bouncycastle.cryptozrtp.CipherParameters; -import org.bouncycastle.cryptozrtp.params.ECPublicKeyParameters; -import org.bouncycastle.cryptozrtp.params.ECPrivateKeyParameters; - - -/** - * P1363 7.2.1 ECSVDP-DH - * - * ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive, - * Diffie-Hellman version. It is based on the work of [DH76], [Mil86], - * and [Kob87]. This primitive derives a shared secret value from one - * party's private key and another party's public key, where both have - * the same set of EC domain parameters. If two parties correctly - * execute this primitive, they will produce the same output. This - * primitive can be invoked by a scheme to derive a shared secret key; - * specifically, it may be used with the schemes ECKAS-DH1 and - * DL/ECKAS-DH2. It assumes that the input keys are valid (see also - * Section 7.2.2). - */ -public class ECDHBasicAgreement - implements BasicAgreement -{ - private ECPrivateKeyParameters key; - - public void init( - CipherParameters key) - { - this.key = (ECPrivateKeyParameters)key; - } - - public BigIntegerCrypto calculateAgreement( - CipherParameters pubKey) - { - ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey; - ECPoint P = pub.getQ().multiply(key.getD()); - - // if (p.isInfinity()) throw new RuntimeException("d*Q == infinity"); - - return P.getX().toBigInteger(); - } - /** - * Clear agreement data including private key data. - * - * Clears all known agreement data and resets the agreement. To use the - * agreement againt the application must initialize it again. - */ - - public void clear() { - key.getD().zeroize(); // clear private key data - key = null; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/DHBasicKeyPairGenerator.java b/src/org/bouncycastle/cryptozrtp/generators/DHBasicKeyPairGenerator.java deleted file mode 100755 index f63cc99..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/DHBasicKeyPairGenerator.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPair; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPairGenerator; -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.DHKeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.DHParameters; -import org.bouncycastle.cryptozrtp.params.DHPrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.DHPublicKeyParameters; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -/** - * a basic Diffie-Helman key pair generator. - * - * This generates keys consistent for use with the basic algorithm for - * Diffie-Helman. - */ -public class DHBasicKeyPairGenerator - implements AsymmetricCipherKeyPairGenerator -{ - private DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.INSTANCE; - private DHKeyGenerationParameters param; - - public void init( - KeyGenerationParameters param) - { - this.param = (DHKeyGenerationParameters)param; - } - - public AsymmetricCipherKeyPair generateKeyPair() - { - BigIntegerCrypto p, x, y; - DHParameters dhParams = param.getParameters(); - - p = dhParams.getP(); - x = helper.calculatePrivate(p, param.getRandom(), dhParams.getL()); - y = helper.calculatePublic(p, dhParams.getG(), x); - - return new AsymmetricCipherKeyPair( - new DHPublicKeyParameters(y, dhParams), - new DHPrivateKeyParameters(x, dhParams)); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/DHKeyGeneratorHelper.java b/src/org/bouncycastle/cryptozrtp/generators/DHKeyGeneratorHelper.java deleted file mode 100755 index 68cb2c3..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/DHKeyGeneratorHelper.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import gnu.java.bigintcrypto.BigIntegerCrypto; -import org.bouncycastle.crypto.prng.RandomGenerator; - -class DHKeyGeneratorHelper -{ - private static final int MAX_ITERATIONS = 1000; - - static final DHKeyGeneratorHelper INSTANCE = new DHKeyGeneratorHelper(); - - private static final BigIntegerCrypto ZERO = BigIntegerCrypto.valueOf(0); - private static final BigIntegerCrypto TWO = BigIntegerCrypto.valueOf(2); - - private DHKeyGeneratorHelper() - { - } - - BigIntegerCrypto calculatePrivate(BigIntegerCrypto p, RandomGenerator random, int limit) - { - // - // calculate the private key - // - BigIntegerCrypto pSub2 = p.subtract(TWO); - BigIntegerCrypto x; - - if (limit == 0) - { - x = createInRange(pSub2, random); - } - else - { - do - { - x = new BigIntegerCrypto(limit, 0, random); - } - while (x.equals(ZERO)); - } - - return x; - } - - private BigIntegerCrypto createInRange(BigIntegerCrypto max, RandomGenerator random) - { - BigIntegerCrypto x; - int maxLength = max.bitLength(); - int count = 0; - - do - { - x = new BigIntegerCrypto(maxLength, random); - count++; - } - while ((x.equals(ZERO) || x.compareTo(max) > 0) && count != MAX_ITERATIONS); - - if (count == MAX_ITERATIONS) // fall back to a faster (restricted) method - { - return new BigIntegerCrypto(maxLength - 1, random).setBit(0); - } - - return x; - } - - BigIntegerCrypto calculatePublic(BigIntegerCrypto p, BigIntegerCrypto g, BigIntegerCrypto x) - { - return g.modPow(x, p); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/DHKeyPairGenerator.java b/src/org/bouncycastle/cryptozrtp/generators/DHKeyPairGenerator.java deleted file mode 100755 index 1b8dd28..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/DHKeyPairGenerator.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPair; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPairGenerator; -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.DHKeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.DHParameters; -import org.bouncycastle.cryptozrtp.params.DHPrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.DHPublicKeyParameters; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -/** - * a Diffie-Helman key pair generator. - * - * This generates keys consistent for use in the MTI/A0 key agreement protocol - * as described in "Handbook of Applied Cryptography", Pages 516-519. - */ -public class DHKeyPairGenerator - implements AsymmetricCipherKeyPairGenerator -{ - private DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.INSTANCE; - - private DHKeyGenerationParameters param; - - public void init( - KeyGenerationParameters param) - { - this.param = (DHKeyGenerationParameters)param; - } - - public AsymmetricCipherKeyPair generateKeyPair() - { - BigIntegerCrypto p, x, y; - DHParameters dhParams = param.getParameters(); - - p = dhParams.getP(); - x = helper.calculatePrivate(p, param.getRandom(), dhParams.getL()); - y = helper.calculatePublic(p, dhParams.getG(), x); - - return new AsymmetricCipherKeyPair( - new DHPublicKeyParameters(y, dhParams), - new DHPrivateKeyParameters(x, dhParams)); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/DHParametersGenerator.java b/src/org/bouncycastle/cryptozrtp/generators/DHParametersGenerator.java deleted file mode 100755 index b0e2ef9..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/DHParametersGenerator.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import org.bouncycastle.cryptozrtp.params.DHParameters; - -import gnu.java.bigintcrypto.BigIntegerCrypto; -import org.bouncycastle.crypto.prng.RandomGenerator; - -public class DHParametersGenerator -{ - private int size; - private int certainty; - private RandomGenerator random; - - private static final BigIntegerCrypto TWO = BigIntegerCrypto.valueOf(2); - - /** - * Initialise the parameters generator. - * - * @param size bit length for the prime p - * @param certainty level of certainty for the prime number tests - * @param random a source of randomness - */ - public void init( - int size, - int certainty, - RandomGenerator random) - { - this.size = size; - this.certainty = certainty; - this.random = random; - } - - /** - * which generates the p and g values from the given parameters, - * returning the DHParameters object. - *
- * Note: can take a while... - */ - public DHParameters generateParameters() - { - // - // find a safe prime p where p = 2*q + 1, where p and q are prime. - // - BigIntegerCrypto[] safePrimes = DHParametersHelper.generateSafePrimes(size, certainty, random); - - BigIntegerCrypto p = safePrimes[0]; - BigIntegerCrypto q = safePrimes[1]; - BigIntegerCrypto g = DHParametersHelper.selectGenerator(p, q, random); - - return new DHParameters(p, g, q, TWO, null); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/DHParametersHelper.java b/src/org/bouncycastle/cryptozrtp/generators/DHParametersHelper.java deleted file mode 100755 index c7c2eed..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/DHParametersHelper.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -import org.bouncycastle.crypto.prng.RandomGenerator; -import org.bouncycastle.cryptozrtp.util.BigIntegers; - -class DHParametersHelper -{ - private static final BigIntegerCrypto ONE = BigIntegerCrypto.valueOf(1); - private static final BigIntegerCrypto TWO = BigIntegerCrypto.valueOf(2); - - // Finds a pair of prime BigIntegerCrypto's {p, q: p = 2q + 1} - static BigIntegerCrypto[] generateSafePrimes( - int size, - int certainty, - RandomGenerator random) - { - BigIntegerCrypto p, q; - int qLength = size - 1; - - for (;;) - { - q = new BigIntegerCrypto(qLength, 2, random); - - // p <- 2q + 1 - p = q.shiftLeft(1).add(ONE); - - if (p.isProbablePrime(certainty) - && (certainty <= 2 || q.isProbablePrime(certainty))) - { - break; - } - } - - return new BigIntegerCrypto[] { p, q }; - } - - // Select a high order element of the multiplicative group Zp* - // p and q must be s.t. p = 2*q + 1, where p and q are prime - static BigIntegerCrypto selectGenerator( - BigIntegerCrypto p, - BigIntegerCrypto q, - RandomGenerator random) - { - BigIntegerCrypto pMinusTwo = p.subtract(TWO); - BigIntegerCrypto g; - - // Handbook of Applied Cryptography 4.86 - do - { - g = BigIntegers.createRandomInRange(TWO, pMinusTwo, random); - } - while (g.modPow(TWO, p).equals(ONE) - || g.modPow(q, p).equals(ONE)); - -/* - // RFC 2631 2.1.1 (and see Handbook of Applied Cryptography 4.81) - do - { - BigInteger h = createInRange(TWO, pMinusTwo, random); - - g = h.modPow(TWO, p); - } - while (g.equals(ONE)); -*/ - - return g; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/Djb25519KeyPairGenerator.java b/src/org/bouncycastle/cryptozrtp/generators/Djb25519KeyPairGenerator.java deleted file mode 100755 index 7dccea8..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/Djb25519KeyPairGenerator.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import djb.Curve25519; -import gnu.java.bigintcrypto.BigIntegerCrypto; -import org.bouncycastle.crypto.prng.RandomGenerator; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPair; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPairGenerator; -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.*; -import org.bouncycastle.mathzrtp.ec.ECConstants; -import org.bouncycastle.mathzrtp.ec.ECPoint; - -public class Djb25519KeyPairGenerator implements AsymmetricCipherKeyPairGenerator, ECConstants -{ - RandomGenerator random; - - public void init(KeyGenerationParameters param) { - Djb25519KeyGenerationParameters ecP = (Djb25519KeyGenerationParameters)param; - - this.random = ecP.getRandom(); - } - - /** - * Given the domain parameters this routine generates an EC key - * pair in accordance with X9.62 section 5.2.1 pages 26, 27. - */ - public AsymmetricCipherKeyPair generateKeyPair() - { - int nBitLength = Curve25519.KEY_SIZE * 8; - BigIntegerCrypto d; - - // Generate 32 bytes random data - byte[] k = new byte[Curve25519.KEY_SIZE]; - random.nextBytes(k); - - byte[] P = new byte[Curve25519.KEY_SIZE]; - Curve25519.keygen(P, null, k); - return new AsymmetricCipherKeyPair( - new Djb25519PublicKeyParameters(P), - new Djb25519PrivateKeyParameters(k)); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/ECKeyPairGenerator.java b/src/org/bouncycastle/cryptozrtp/generators/ECKeyPairGenerator.java deleted file mode 100755 index c7dc12c..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/ECKeyPairGenerator.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -import org.bouncycastle.crypto.prng.RandomGenerator; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPair; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPairGenerator; -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.ECDomainParameters; -import org.bouncycastle.cryptozrtp.params.ECKeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.ECPrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.ECPublicKeyParameters; -import org.bouncycastle.mathzrtp.ec.ECConstants; -import org.bouncycastle.mathzrtp.ec.ECPoint; - -public class ECKeyPairGenerator - implements AsymmetricCipherKeyPairGenerator, ECConstants -{ - ECDomainParameters params; - RandomGenerator random; - - public void init(KeyGenerationParameters param) { - ECKeyGenerationParameters ecP = (ECKeyGenerationParameters)param; - - this.random = ecP.getRandom(); - this.params = ecP.getDomainParameters(); - } - - /** - * Given the domain parameters this routine generates an EC key - * pair in accordance with X9.62 section 5.2.1 pages 26, 27. - */ - public AsymmetricCipherKeyPair generateKeyPair() - { - BigIntegerCrypto n = params.getN(); - int nBitLength = n.bitLength(); - BigIntegerCrypto d; - - do - { - d = new BigIntegerCrypto(nBitLength, random); - } - while (d.equals(ZERO) || (d.compareTo(n) >= 0)); - - ECPoint Q = params.getG().multiply(d); - - return new AsymmetricCipherKeyPair( - new ECPublicKeyParameters(Q, params), - new ECPrivateKeyParameters(d, params)); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/AsymmetricKeyParameter.java b/src/org/bouncycastle/cryptozrtp/params/AsymmetricKeyParameter.java deleted file mode 100755 index 1154ba9..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/AsymmetricKeyParameter.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import org.bouncycastle.cryptozrtp.CipherParameters; - -public class AsymmetricKeyParameter - implements CipherParameters -{ - boolean privateKey; - - public AsymmetricKeyParameter( - boolean privateKey) - { - this.privateKey = privateKey; - } - - public boolean isPrivate() - { - return privateKey; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/DHKeyGenerationParameters.java b/src/org/bouncycastle/cryptozrtp/params/DHKeyGenerationParameters.java deleted file mode 100755 index e0aeb32..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/DHKeyGenerationParameters.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import org.bouncycastle.crypto.prng.RandomGenerator; - -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; - -public class DHKeyGenerationParameters - extends KeyGenerationParameters -{ - private DHParameters params; - - public DHKeyGenerationParameters( - RandomGenerator random, - DHParameters params) - { - super(random, params.getP().bitLength()); - - this.params = params; - } - - public DHParameters getParameters() - { - return params; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/DHKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/DHKeyParameters.java deleted file mode 100755 index a522880..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/DHKeyParameters.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - - -public class DHKeyParameters - extends AsymmetricKeyParameter -{ - private DHParameters params; - - protected DHKeyParameters( - boolean isPrivate, - DHParameters params) - { - super(isPrivate); - - this.params = params; - } - - public DHParameters getParameters() - { - return params; - } - - public boolean equals( - Object obj) - { - if (!(obj instanceof DHKeyParameters)) - { - return false; - } - - DHKeyParameters dhKey = (DHKeyParameters)obj; - - if (params == null) - { - return dhKey.getParameters() == null; - } - else - { - return params.equals(dhKey.getParameters()); - } - } - - public int hashCode() - { - int code = isPrivate() ? 0 : 1; - - if (params != null) - { - code ^= params.hashCode(); - } - - return code; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/DHParameters.java b/src/org/bouncycastle/cryptozrtp/params/DHParameters.java deleted file mode 100755 index dafdff8..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/DHParameters.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import org.bouncycastle.cryptozrtp.CipherParameters; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -public class DHParameters - implements CipherParameters -{ - private static final int DEFAULT_MINIMUM_LENGTH = 160; - - private BigIntegerCrypto g; - private BigIntegerCrypto p; - private BigIntegerCrypto q; - private BigIntegerCrypto j; - private int m = DEFAULT_MINIMUM_LENGTH; - private int l; - private DHValidationParameters validation; - - public DHParameters( - BigIntegerCrypto p, - BigIntegerCrypto g) - { - this(p, g, null, DEFAULT_MINIMUM_LENGTH, 0, null, null); - } - - public DHParameters( - BigIntegerCrypto p, - BigIntegerCrypto g, - BigIntegerCrypto q) - { - this(p, g, q, DEFAULT_MINIMUM_LENGTH, 0, null, null); - } - - public DHParameters( - BigIntegerCrypto p, - BigIntegerCrypto g, - BigIntegerCrypto q, - int l) - { - this(p, g, q, l, l, null, null); - } - - public DHParameters( - BigIntegerCrypto p, - BigIntegerCrypto g, - BigIntegerCrypto q, - int m, - int l) - { - this(p, g, q, m, l, null, null); - } - - public DHParameters( - BigIntegerCrypto p, - BigIntegerCrypto g, - BigIntegerCrypto q, - BigIntegerCrypto j, - DHValidationParameters validation) - { - this(p, g, q, DEFAULT_MINIMUM_LENGTH, 0, j, validation); - } - - public DHParameters( - BigIntegerCrypto p, - BigIntegerCrypto g, - BigIntegerCrypto q, - int m, - int l, - BigIntegerCrypto j, - DHValidationParameters validation) - { - if (l != 0 && m > l) - { - throw new IllegalArgumentException("l value must be greater than m value if provided"); - } - - this.g = g; - this.p = p; - this.q = q; - this.m = m; - this.l = l; - this.j = j; - this.validation = validation; - } - - public BigIntegerCrypto getP() - { - return p; - } - - public BigIntegerCrypto getG() - { - return g; - } - - public BigIntegerCrypto getQ() - { - return q; - } - - /** - * Return the subgroup factor J. - * - * @return subgroup factor - */ - public BigIntegerCrypto getJ() - { - return j; - } - - /** - * Return the minimum length of the private value. - * - * @return the minimum length of the private value in bits. - */ - public int getM() - { - return m; - } - - /** - * Return the private value length in bits - if set, zero otherwise (use bitLength(P) - 1). - * - * @return the private value length in bits, zero otherwise. - */ - public int getL() - { - return l; - } - - public DHValidationParameters getValidationParameters() - { - return validation; - } - - public boolean equals( - Object obj) - { - if (!(obj instanceof DHParameters)) - { - return false; - } - - DHParameters pm = (DHParameters)obj; - - if (this.getQ() != null) - { - if (!this.getQ().equals(pm.getQ())) - { - return false; - } - } - else - { - if (pm.getQ() != null) - { - return false; - } - } - - return pm.getP().equals(p) && pm.getG().equals(g); - } - - public int hashCode() - { - return getP().hashCode() ^ getG().hashCode() ^ (getQ() != null ? getQ().hashCode() : 0); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/DHPrivateKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/DHPrivateKeyParameters.java deleted file mode 100755 index fc62f6b..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/DHPrivateKeyParameters.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -public class DHPrivateKeyParameters - extends DHKeyParameters -{ - private BigIntegerCrypto x; - - public DHPrivateKeyParameters( - BigIntegerCrypto x, - DHParameters params) - { - super(true, params); - - this.x = x; - } - - public BigIntegerCrypto getX() - { - return x; - } - - public int hashCode() - { - return x.hashCode() ^ super.hashCode(); - } - - public boolean equals( - Object obj) - { - if (!(obj instanceof DHPrivateKeyParameters)) - { - return false; - } - - DHPrivateKeyParameters other = (DHPrivateKeyParameters)obj; - - return other.getX().equals(this.x) && super.equals(obj); - } - - /** - * Clear private key data. - * - * Clears the private key data and overwrites it. To use the - * agreement again the application must initialize it again. - */ - - public void clear() { - if (x != null) - x.zeroize(); // overwrites BigIntere data with zero - x = null; - } - -} diff --git a/src/org/bouncycastle/cryptozrtp/params/DHPublicKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/DHPublicKeyParameters.java deleted file mode 100755 index 5fd9e44..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/DHPublicKeyParameters.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -public class DHPublicKeyParameters - extends DHKeyParameters -{ - private BigIntegerCrypto y; - - public DHPublicKeyParameters( - BigIntegerCrypto y, - DHParameters params) - { - super(false, params); - - this.y = y; - } - - public BigIntegerCrypto getY() - { - return y; - } - - public int hashCode() - { - return y.hashCode() ^ super.hashCode(); - } - - public boolean equals( - Object obj) - { - if (!(obj instanceof DHPublicKeyParameters)) - { - return false; - } - - DHPublicKeyParameters other = (DHPublicKeyParameters)obj; - - return other.getY().equals(y) && super.equals(obj); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/DHValidationParameters.java b/src/org/bouncycastle/cryptozrtp/params/DHValidationParameters.java deleted file mode 100755 index 44a2d89..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/DHValidationParameters.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import java.util.Arrays; - -public class DHValidationParameters -{ - private byte[] seed; - private int counter; - - public DHValidationParameters( - byte[] seed, - int counter) - { - this.seed = seed; - this.counter = counter; - } - - public int getCounter() - { - return counter; - } - - public byte[] getSeed() - { - return seed; - } - - public boolean equals( - Object o) - { - if (!(o instanceof DHValidationParameters)) - { - return false; - } - - DHValidationParameters other = (DHValidationParameters)o; - - if (other.counter != this.counter) - { - return false; - } - - return Arrays.equals(this.seed, other.seed); - } - - public int hashCode() - { - return counter ^ Arrays.hashCode(seed); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/Djb25519KeyGenerationParameters.java b/src/org/bouncycastle/cryptozrtp/params/Djb25519KeyGenerationParameters.java deleted file mode 100755 index f2f4f14..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/Djb25519KeyGenerationParameters.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import djb.Curve25519; -import org.bouncycastle.crypto.prng.RandomGenerator; -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; - -public class Djb25519KeyGenerationParameters extends KeyGenerationParameters { - - public Djb25519KeyGenerationParameters(RandomGenerator random) { - super(random, Curve25519.KEY_SIZE * 8); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/Djb25519PrivateKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/Djb25519PrivateKeyParameters.java deleted file mode 100755 index a8d360b..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/Djb25519PrivateKeyParameters.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -// Curve25519 uses 32 byte random data as a private key, not a BigInteger -public class Djb25519PrivateKeyParameters extends ECKeyParameters { - byte[] k; - - public Djb25519PrivateKeyParameters(byte[] k) { - super(true, null); - this.k = k; - } - - public byte[] getK() - { - return k; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/Djb25519PublicKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/Djb25519PublicKeyParameters.java deleted file mode 100755 index 4b589c6..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/Djb25519PublicKeyParameters.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -// Curve25519 derives 32 byte data as a public key from the private key data. -public class Djb25519PublicKeyParameters extends ECKeyParameters { - byte[] P; - - public Djb25519PublicKeyParameters(byte[] P) { - super(false, null); - this.P = P; - } - - public byte[] getP() - { - return P; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/ECDomainParameters.java b/src/org/bouncycastle/cryptozrtp/params/ECDomainParameters.java deleted file mode 100755 index 4017223..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/ECDomainParameters.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import gnu.java.bigintcrypto.BigIntegerCrypto; -import org.bouncycastle.mathzrtp.ec.ECConstants; -import org.bouncycastle.mathzrtp.ec.ECCurve; -import org.bouncycastle.mathzrtp.ec.ECPoint; - -public class ECDomainParameters - implements ECConstants -{ - ECCurve curve; - byte[] seed; - ECPoint G; - BigIntegerCrypto n; - BigIntegerCrypto h; - - public ECDomainParameters( - ECCurve curve, - ECPoint G, - BigIntegerCrypto n) - { - this.curve = curve; - this.G = G; - this.n = n; - this.h = ONE; - this.seed = null; - } - - public ECDomainParameters( - ECCurve curve, - ECPoint G, - BigIntegerCrypto n, - BigIntegerCrypto h) - { - this.curve = curve; - this.G = G; - this.n = n; - this.h = h; - this.seed = null; - } - - public ECDomainParameters( - ECCurve curve, - ECPoint G, - BigIntegerCrypto n, - BigIntegerCrypto h, - byte[] seed) - { - this.curve = curve; - this.G = G; - this.n = n; - this.h = h; - this.seed = seed; - } - - // Convert from "classic" parameters to cryptozrtp/mathzrtp parameters - public ECDomainParameters( - org.bouncycastle.math.ec.ECCurve curveIn, - org.bouncycastle.math.ec.ECPoint GIn, - java.math.BigInteger nIn, - java.math.BigInteger hIn, - byte[] seed) - { - org.bouncycastle.math.ec.ECCurve.Fp fpCurve = - (org.bouncycastle.math.ec.ECCurve.Fp)curveIn; - BigIntegerCrypto q = new BigIntegerCrypto(fpCurve.getQ().toByteArray()); - BigIntegerCrypto a = new BigIntegerCrypto(curveIn.getA().toBigInteger().toByteArray()); - BigIntegerCrypto b = new BigIntegerCrypto(curveIn.getB().toBigInteger().toByteArray()); - this.curve = new ECCurve.Fp(q, a, b); - - byte[] encoded = GIn.getEncoded(); - this.G = this.curve.decodePoint(encoded); - this.n = new BigIntegerCrypto(nIn.toByteArray()); - this.h = new BigIntegerCrypto(hIn.toByteArray()); - this.seed = seed; - } - - public ECCurve getCurve() - { - return curve; - } - - public ECPoint getG() - { - return G; - } - - public BigIntegerCrypto getN() - { - return n; - } - - public BigIntegerCrypto getH() - { - return h; - } - - public byte[] getSeed() - { - return seed; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/ECKeyGenerationParameters.java b/src/org/bouncycastle/cryptozrtp/params/ECKeyGenerationParameters.java deleted file mode 100755 index 8c32baf..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/ECKeyGenerationParameters.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import org.bouncycastle.crypto.prng.RandomGenerator; - -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; - -public class ECKeyGenerationParameters - extends KeyGenerationParameters -{ - private ECDomainParameters domainParams; - - public ECKeyGenerationParameters( - ECDomainParameters domainParams, - RandomGenerator random) - { - super(random, domainParams.getN().bitLength()); - - this.domainParams = domainParams; - } - - public ECDomainParameters getDomainParameters() - { - return domainParams; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/ECKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/ECKeyParameters.java deleted file mode 100755 index e36a04c..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/ECKeyParameters.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -public class ECKeyParameters - extends AsymmetricKeyParameter -{ - ECDomainParameters params; - - protected ECKeyParameters( - boolean isPrivate, - ECDomainParameters params) - { - super(isPrivate); - - this.params = params; - } - - public ECDomainParameters getParameters() - { - return params; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/ECPrivateKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/ECPrivateKeyParameters.java deleted file mode 100755 index fcac37e..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/ECPrivateKeyParameters.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -public class ECPrivateKeyParameters - extends ECKeyParameters -{ - BigIntegerCrypto d; - - public ECPrivateKeyParameters( - BigIntegerCrypto d, - ECDomainParameters params) - { - super(true, params); - this.d = d; - } - - public BigIntegerCrypto getD() - { - return d; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/ECPublicKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/ECPublicKeyParameters.java deleted file mode 100755 index 866f9a4..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/ECPublicKeyParameters.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import org.bouncycastle.mathzrtp.ec.ECPoint; - -public class ECPublicKeyParameters - extends ECKeyParameters -{ - ECPoint Q; - - public ECPublicKeyParameters( - ECPoint Q, - ECDomainParameters params) - { - super(false, params); - this.Q = Q; - } - - public ECPoint getQ() - { - return Q; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/ParametersWithRandom.java b/src/org/bouncycastle/cryptozrtp/params/ParametersWithRandom.java deleted file mode 100755 index cbf6d9d..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/ParametersWithRandom.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import org.bouncycastle.crypto.CipherParameters; - -import java.security.SecureRandom; - -public class ParametersWithRandom - implements CipherParameters -{ - private SecureRandom random; - private CipherParameters parameters; - - public ParametersWithRandom( - CipherParameters parameters, - SecureRandom random) - { - this.random = random; - this.parameters = parameters; - } - - public ParametersWithRandom( - CipherParameters parameters) - { - this(parameters, new SecureRandom()); - } - - public SecureRandom getRandom() - { - return random; - } - - public CipherParameters getParameters() - { - return parameters; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/util/BigIntegers.java b/src/org/bouncycastle/cryptozrtp/util/BigIntegers.java deleted file mode 100755 index 5f99bd8..0000000 --- a/src/org/bouncycastle/cryptozrtp/util/BigIntegers.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.bouncycastle.cryptozrtp.util; - -import gnu.java.bigintcrypto.BigIntegerCrypto; -import org.bouncycastle.crypto.prng.RandomGenerator; - -/** - * BigInteger utilities. - */ -public final class BigIntegers -{ - /** - * Return the passed in value as an unsigned byte array. - * - * @param value value to be converted. - * @return a byte array without a leading zero byte if present in the signed encoding. - */ - public static byte[] asUnsignedByteArray( - BigIntegerCrypto value) - { - byte[] bytes = value.toByteArray(); - - if (bytes[0] == 0) - { - byte[] tmp = new byte[bytes.length - 1]; - - System.arraycopy(bytes, 1, tmp, 0, tmp.length); - - return tmp; - } - - return bytes; - } - - /** - * Return a random BigInteger not less than 'min' and not greater than 'max' - * - * @param min the least value that may be generated - * @param max the greatest value that may be generated - * @param random the source of randomness - * @return a random BigInteger value in the range [min,max] - */ - public static BigIntegerCrypto createRandomInRange( - BigIntegerCrypto min, - BigIntegerCrypto max, - RandomGenerator random) - { - BigIntegerCrypto x; - do - { - x = new BigIntegerCrypto(max.bitLength(), random); - } - while (x.compareTo(min) < 0 || x.compareTo(max) > 0); - return x; - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/ECAlgorithms.java b/src/org/bouncycastle/mathzrtp/ec/ECAlgorithms.java deleted file mode 100755 index 0a5379f..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/ECAlgorithms.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -public class ECAlgorithms -{ - public static ECPoint sumOfTwoMultiplies(ECPoint P, BigIntegerCrypto a, - ECPoint Q, BigIntegerCrypto b) - { - ECCurve c = P.getCurve(); - if (!c.equals(Q.getCurve())) - { - throw new IllegalArgumentException("P and Q must be on same curve"); - } - - // TODO Add special case back in when WTNAF is enabled -// // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick -// if (c instanceof ECCurve.F2m) -// { -// ECCurve.F2m f2mCurve = (ECCurve.F2m) c; -// if (f2mCurve.isKoblitz()) -// { -// return P.multiply(a).add(Q.multiply(b)); -// } -// } - - return implShamirsTrick(P, a, Q, b); - } - - /* - * "Shamir's Trick", originally due to E. G. Straus - * (Addition chains of vectors. American Mathematical Monthly, - * 71(7):806-808, Aug./Sept. 1964) - *
- * Input: The points P, Q, scalar k = (km?, ... , k1, k0)
- * and scalar l = (lm?, ... , l1, l0).
- * Output: R = k * P + l * Q.
- * 1: Z <- P + Q
- * 2: R <- O
- * 3: for i from m-1 down to 0 do
- * 4: R <- R + R {point doubling}
- * 5: if (ki = 1) and (li = 0) then R <- R + P end if
- * 6: if (ki = 0) and (li = 1) then R <- R + Q end if
- * 7: if (ki = 1) and (li = 1) then R <- R + Z end if
- * 8: end for
- * 9: return R
- *
- */
- public static ECPoint shamirsTrick(ECPoint P, BigIntegerCrypto k,
- ECPoint Q, BigIntegerCrypto l)
- {
- if (!P.getCurve().equals(Q.getCurve()))
- {
- throw new IllegalArgumentException("P and Q must be on same curve");
- }
-
- return implShamirsTrick(P, k, Q, l);
- }
-
- private static ECPoint implShamirsTrick(ECPoint P, BigIntegerCrypto k,
- ECPoint Q, BigIntegerCrypto l)
- {
- int m = Math.max(k.bitLength(), l.bitLength());
- ECPoint Z = P.add(Q);
- ECPoint R = P.getCurve().getInfinity();
-
- for (int i = m - 1; i >= 0; --i)
- {
- R = R.twice();
-
- if (k.testBit(i))
- {
- if (l.testBit(i))
- {
- R = R.add(Z);
- }
- else
- {
- R = R.add(P);
- }
- }
- else
- {
- if (l.testBit(i))
- {
- R = R.add(Q);
- }
- }
- }
-
- return R;
- }
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/ECConstants.java b/src/org/bouncycastle/mathzrtp/ec/ECConstants.java
deleted file mode 100755
index c430d3b..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/ECConstants.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-
-public interface ECConstants
-{
- public static final BigIntegerCrypto ZERO = BigIntegerCrypto.valueOf(0);
- public static final BigIntegerCrypto ONE = BigIntegerCrypto.valueOf(1);
- public static final BigIntegerCrypto TWO = BigIntegerCrypto.valueOf(2);
- public static final BigIntegerCrypto THREE = BigIntegerCrypto.valueOf(3);
- public static final BigIntegerCrypto FOUR = BigIntegerCrypto.valueOf(4);
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/ECCurve.java b/src/org/bouncycastle/mathzrtp/ec/ECCurve.java
deleted file mode 100755
index f3da51c..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/ECCurve.java
+++ /dev/null
@@ -1,660 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-import java.util.Random;
-
-/**
- * base class for an elliptic curve
- */
-public abstract class ECCurve
-{
- ECFieldElement a, b;
-
- public abstract int getFieldSize();
-
- public abstract ECFieldElement fromBigInteger(BigIntegerCrypto x);
-
- public abstract ECPoint createPoint(BigIntegerCrypto x, BigIntegerCrypto y, boolean withCompression);
-
- public abstract ECPoint decodePoint(byte[] encoded);
-
- public abstract ECPoint getInfinity();
-
- public ECFieldElement getA()
- {
- return a;
- }
-
- public ECFieldElement getB()
- {
- return b;
- }
-
- /**
- * Elliptic curve over Fp
- */
- public static class Fp extends ECCurve
- {
- BigIntegerCrypto q;
- ECPoint.Fp infinity;
-
- public Fp(BigIntegerCrypto q, BigIntegerCrypto a, BigIntegerCrypto b)
- {
- this.q = q;
- this.a = fromBigInteger(a);
- this.b = fromBigInteger(b);
- this.infinity = new ECPoint.Fp(this, null, null);
- }
-
- public BigIntegerCrypto getQ()
- {
- return q;
- }
-
- public int getFieldSize()
- {
- return q.bitLength();
- }
-
- public ECFieldElement fromBigInteger(BigIntegerCrypto x)
- {
- return new ECFieldElement.Fp(this.q, x);
- }
-
- public ECPoint createPoint(BigIntegerCrypto x, BigIntegerCrypto y, boolean withCompression)
- {
- return new ECPoint.Fp(this, fromBigInteger(x), fromBigInteger(y), withCompression);
- }
-
- /**
- * Decode a point on this curve from its ASN.1 encoding. The different
- * encodings are taken account of, including point compression for
- * Fp (X9.62 s 4.2.1 pg 17).
- * @return The decoded point.
- */
- public ECPoint decodePoint(byte[] encoded)
- {
- ECPoint p = null;
-
- switch (encoded[0])
- {
- // infinity
- case 0x00:
- p = getInfinity();
- break;
- // compressed
- case 0x02:
- case 0x03:
- int ytilde = encoded[0] & 1;
- byte[] i = new byte[encoded.length - 1];
-
- System.arraycopy(encoded, 1, i, 0, i.length);
-
- ECFieldElement x = new ECFieldElement.Fp(this.q, new BigIntegerCrypto(1, i));
- ECFieldElement alpha = x.multiply(x.square().add(a)).add(b);
- ECFieldElement beta = alpha.sqrt();
-
- //
- // if we can't find a sqrt we haven't got a point on the
- // curve - run!
- //
- if (beta == null)
- {
- throw new RuntimeException("Invalid point compression");
- }
-
- int bit0 = (beta.toBigInteger().testBit(0) ? 1 : 0);
-
- if (bit0 == ytilde)
- {
- p = new ECPoint.Fp(this, x, beta, true);
- }
- else
- {
- p = new ECPoint.Fp(this, x,
- new ECFieldElement.Fp(this.q, q.subtract(beta.toBigInteger())), true);
- }
- break;
- // uncompressed
- case 0x04:
- // hybrid
- case 0x06:
- case 0x07:
- byte[] xEnc = new byte[(encoded.length - 1) / 2];
- byte[] yEnc = new byte[(encoded.length - 1) / 2];
-
- System.arraycopy(encoded, 1, xEnc, 0, xEnc.length);
- System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length);
-
- p = new ECPoint.Fp(this,
- new ECFieldElement.Fp(this.q, new BigIntegerCrypto(1, xEnc)),
- new ECFieldElement.Fp(this.q, new BigIntegerCrypto(1, yEnc)));
- break;
- default:
- throw new RuntimeException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16));
- }
-
- return p;
- }
-
- public ECPoint getInfinity()
- {
- return infinity;
- }
-
- public boolean equals(
- Object anObject)
- {
- if (anObject == this)
- {
- return true;
- }
-
- if (!(anObject instanceof ECCurve.Fp))
- {
- return false;
- }
-
- ECCurve.Fp other = (ECCurve.Fp) anObject;
-
- return this.q.equals(other.q)
- && a.equals(other.a) && b.equals(other.b);
- }
-
- public int hashCode()
- {
- return a.hashCode() ^ b.hashCode() ^ q.hashCode();
- }
- }
-
- /**
- * Elliptic curves over F2m. The Weierstrass equation is given by
- * y2 + xy = x3 + ax2 + b.
- */
- public static class F2m extends ECCurve
- {
- /**
- * The exponent m of F2m.
- */
- private int m; // can't be final - JDK 1.1
-
- /**
- * TPB: The integer k where xm +
- * xk + 1 represents the reduction polynomial
- * f(z).k1 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).0k2 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).0k3 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).μ of the elliptic curve if this is
- * a Koblitz curve.
- */
- private byte mu = 0;
-
- /**
- * The auxiliary values s0 and
- * s1 used for partial modular reduction for
- * Koblitz curves.
- */
- private BigIntegerCrypto[] si = null;
-
- /**
- * Constructor for Trinomial Polynomial Basis (TPB).
- * @param m The exponent m of
- * F2m.
- * @param k The integer k where xm +
- * xk + 1 represents the reduction
- * polynomial f(z).
- * @param a The coefficient a in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * F2m.
- * @param b The coefficient b in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * F2m.
- */
- public F2m(
- int m,
- int k,
- BigIntegerCrypto a,
- BigIntegerCrypto b)
- {
- this(m, k, 0, 0, a, b, null, null);
- }
-
- /**
- * Constructor for Trinomial Polynomial Basis (TPB).
- * @param m The exponent m of
- * F2m.
- * @param k The integer k where xm +
- * xk + 1 represents the reduction
- * polynomial f(z).
- * @param a The coefficient a in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * F2m.
- * @param b The coefficient b in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * F2m.
- * @param n The order of the main subgroup of the elliptic curve.
- * @param h The cofactor of the elliptic curve, i.e.
- * #Ea(F2m) = h * n.
- */
- public F2m(
- int m,
- int k,
- BigIntegerCrypto a,
- BigIntegerCrypto b,
- BigIntegerCrypto n,
- BigIntegerCrypto h)
- {
- this(m, k, 0, 0, a, b, n, h);
- }
-
- /**
- * Constructor for Pentanomial Polynomial Basis (PPB).
- * @param m The exponent m of
- * F2m.
- * @param k1 The integer k1 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).
- * @param k2 The integer k2 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).
- * @param k3 The integer k3 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).
- * @param a The coefficient a in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * F2m.
- * @param b The coefficient b in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * F2m.
- */
- public F2m(
- int m,
- int k1,
- int k2,
- int k3,
- BigIntegerCrypto a,
- BigIntegerCrypto b)
- {
- this(m, k1, k2, k3, a, b, null, null);
- }
-
- /**
- * Constructor for Pentanomial Polynomial Basis (PPB).
- * @param m The exponent m of
- * F2m.
- * @param k1 The integer k1 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).
- * @param k2 The integer k2 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).
- * @param k3 The integer k3 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).
- * @param a The coefficient a in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * F2m.
- * @param b The coefficient b in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * F2m.
- * @param n The order of the main subgroup of the elliptic curve.
- * @param h The cofactor of the elliptic curve, i.e.
- * #Ea(F2m) = h * n.
- */
- public F2m(
- int m,
- int k1,
- int k2,
- int k3,
- BigIntegerCrypto a,
- BigIntegerCrypto b,
- BigIntegerCrypto n,
- BigIntegerCrypto h)
- {
- this.m = m;
- this.k1 = k1;
- this.k2 = k2;
- this.k3 = k3;
- this.n = n;
- this.h = h;
-
- if (k1 == 0)
- {
- throw new IllegalArgumentException("k1 must be > 0");
- }
-
- if (k2 == 0)
- {
- if (k3 != 0)
- {
- throw new IllegalArgumentException("k3 must be 0 if k2 == 0");
- }
- }
- else
- {
- if (k2 <= k1)
- {
- throw new IllegalArgumentException("k2 must be > k1");
- }
-
- if (k3 <= k2)
- {
- throw new IllegalArgumentException("k3 must be > k2");
- }
- }
-
- this.a = fromBigInteger(a);
- this.b = fromBigInteger(b);
- this.infinity = new ECPoint.F2m(this, null, null);
- }
-
- public int getFieldSize()
- {
- return m;
- }
-
- public ECFieldElement fromBigInteger(BigIntegerCrypto x)
- {
- return new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, x);
- }
-
- public ECPoint createPoint(BigIntegerCrypto x, BigIntegerCrypto y, boolean withCompression)
- {
- return new ECPoint.F2m(this, fromBigInteger(x), fromBigInteger(y), withCompression);
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECCurve#decodePoint(byte[])
- */
- public ECPoint decodePoint(byte[] encoded)
- {
- ECPoint p = null;
-
- switch (encoded[0])
- {
- // infinity
- case 0x00:
- p = getInfinity();
- break;
- // compressed
- case 0x02:
- case 0x03:
- byte[] enc = new byte[encoded.length - 1];
- System.arraycopy(encoded, 1, enc, 0, enc.length);
- if (encoded[0] == 0x02)
- {
- p = decompressPoint(enc, 0);
- }
- else
- {
- p = decompressPoint(enc, 1);
- }
- break;
- // uncompressed
- case 0x04:
- // hybrid
- case 0x06:
- case 0x07:
- byte[] xEnc = new byte[(encoded.length - 1) / 2];
- byte[] yEnc = new byte[(encoded.length - 1) / 2];
-
- System.arraycopy(encoded, 1, xEnc, 0, xEnc.length);
- System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length);
-
- p = new ECPoint.F2m(this,
- new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3,
- new BigIntegerCrypto(1, xEnc)),
- new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3,
- new BigIntegerCrypto(1, yEnc)), false);
- break;
-
- default:
- throw new RuntimeException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16));
- }
-
- return p;
- }
-
- public ECPoint getInfinity()
- {
- return infinity;
- }
-
- /**
- * Returns true if this is a Koblitz curve (ABC curve).
- * @return true if this is a Koblitz curve (ABC curve), false otherwise
- */
- public boolean isKoblitz()
- {
- return ((n != null) && (h != null) &&
- ((a.toBigInteger().equals(ECConstants.ZERO)) ||
- (a.toBigInteger().equals(ECConstants.ONE))) &&
- (b.toBigInteger().equals(ECConstants.ONE)));
- }
-
- /**
- * Returns the parameter μ of the elliptic curve.
- * @return μ of the elliptic curve.
- * @throws IllegalArgumentException if the given ECCurve is not a
- * Koblitz curve.
- */
- synchronized byte getMu()
- {
- if (mu == 0)
- {
- mu = Tnaf.getMu(this);
- }
- return mu;
- }
-
- /**
- * @return the auxiliary values s0 and
- * s1 used for partial modular reduction for
- * Koblitz curves.
- */
- synchronized BigIntegerCrypto[] getSi()
- {
- if (si == null)
- {
- si = Tnaf.getSi(this);
- }
- return si;
- }
-
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param xEnc
- * The encoding of field element xp.
- * @param ypBit
- * ~yp, an indication bit for the decompression of yp.
- * @return the decompressed point.
- */
- private ECPoint decompressPoint(
- byte[] xEnc,
- int ypBit)
- {
- ECFieldElement xp = new ECFieldElement.F2m(
- this.m, this.k1, this.k2, this.k3, new BigIntegerCrypto(1, xEnc));
- ECFieldElement yp = null;
- if (xp.toBigInteger().equals(ECConstants.ZERO))
- {
- yp = b;
- for (int i = 0; i < m - 1; i++)
- {
- yp = yp.square();
- }
- }
- else
- {
- ECFieldElement beta = xp.add(a).add(
- b.multiply(xp.square().invert()));
- ECFieldElement z = solveQuadradicEquation(beta);
- if (z == null)
- {
- throw new RuntimeException("Invalid point compression");
- }
- int zBit = 0;
- if (z.toBigInteger().testBit(0))
- {
- zBit = 1;
- }
- if (zBit != ypBit)
- {
- z = z.add(new ECFieldElement.F2m(this.m, this.k1, this.k2,
- this.k3, ECConstants.ONE));
- }
- yp = xp.multiply(z);
- }
-
- return new ECPoint.F2m(this, xp, yp);
- }
-
- /**
- * Solves a quadratic equation z2 + z = beta(X9.62
- * D.1.6) The other solution is z + 1.
- *
- * @param beta
- * The value to solve the qradratic equation for.
- * @return the solution for z2 + z = beta or
- * null if no solution exists.
- */
- private ECFieldElement solveQuadradicEquation(ECFieldElement beta)
- {
- ECFieldElement zeroElement = new ECFieldElement.F2m(
- this.m, this.k1, this.k2, this.k3, ECConstants.ZERO);
-
- if (beta.toBigInteger().equals(ECConstants.ZERO))
- {
- return zeroElement;
- }
-
- ECFieldElement z = null;
- ECFieldElement gamma = zeroElement;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = new ECFieldElement.F2m(this.m, this.k1,
- this.k2, this.k3, new BigIntegerCrypto(m, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i <= m - 1; i++)
- {
- ECFieldElement w2 = w.square();
- z = z.square().add(w2.multiply(t));
- w = w2.add(beta);
- }
- if (!w.toBigInteger().equals(ECConstants.ZERO))
- {
- return null;
- }
- gamma = z.square().add(z);
- }
- while (gamma.toBigInteger().equals(ECConstants.ZERO));
-
- return z;
- }
-
- public boolean equals(
- Object anObject)
- {
- if (anObject == this)
- {
- return true;
- }
-
- if (!(anObject instanceof ECCurve.F2m))
- {
- return false;
- }
-
- ECCurve.F2m other = (ECCurve.F2m)anObject;
-
- return (this.m == other.m) && (this.k1 == other.k1)
- && (this.k2 == other.k2) && (this.k3 == other.k3)
- && a.equals(other.a) && b.equals(other.b);
- }
-
- public int hashCode()
- {
- return this.a.hashCode() ^ this.b.hashCode() ^ m ^ k1 ^ k2 ^ k3;
- }
-
- public int getM()
- {
- return m;
- }
-
- /**
- * Return true if curve uses a Trinomial basis.
- *
- * @return true if curve Trinomial, false otherwise.
- */
- public boolean isTrinomial()
- {
- return k2 == 0 && k3 == 0;
- }
-
- public int getK1()
- {
- return k1;
- }
-
- public int getK2()
- {
- return k2;
- }
-
- public int getK3()
- {
- return k3;
- }
-
- public BigIntegerCrypto getN()
- {
- return n;
- }
-
- public BigIntegerCrypto getH()
- {
- return h;
- }
- }
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/ECFieldElement.java b/src/org/bouncycastle/mathzrtp/ec/ECFieldElement.java
deleted file mode 100755
index 9bfd175..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/ECFieldElement.java
+++ /dev/null
@@ -1,1196 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-import java.util.Random;
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-
-public abstract class ECFieldElement
- implements ECConstants
-{
-
- public abstract BigIntegerCrypto toBigInteger();
- public abstract String getFieldName();
- public abstract int getFieldSize();
- public abstract ECFieldElement add(ECFieldElement b);
- public abstract ECFieldElement subtract(ECFieldElement b);
- public abstract ECFieldElement multiply(ECFieldElement b);
- public abstract ECFieldElement divide(ECFieldElement b);
- public abstract ECFieldElement negate();
- public abstract ECFieldElement square();
- public abstract ECFieldElement invert();
- public abstract ECFieldElement sqrt();
-
- public String toString()
- {
- return this.toBigInteger().toString(2);
- }
-
- public static class Fp extends ECFieldElement
- {
- BigIntegerCrypto x;
-
- BigIntegerCrypto q;
-
- public Fp(BigIntegerCrypto q, BigIntegerCrypto x)
- {
- this.x = x;
-
- if (x.compareTo(q) >= 0)
- {
- throw new IllegalArgumentException("x value too large in field element");
- }
-
- this.q = q;
- }
-
- public BigIntegerCrypto toBigInteger()
- {
- return x;
- }
-
- /**
- * return the field name for this field.
- *
- * @return the string "Fp".
- */
- public String getFieldName()
- {
- return "Fp";
- }
-
- public int getFieldSize()
- {
- return q.bitLength();
- }
-
- public BigIntegerCrypto getQ()
- {
- return q;
- }
-
- public ECFieldElement add(ECFieldElement b)
- {
- return new Fp(q, x.add(b.toBigInteger()).mod(q));
- }
-
- public ECFieldElement subtract(ECFieldElement b)
- {
- return new Fp(q, x.subtract(b.toBigInteger()).mod(q));
- }
-
- public ECFieldElement multiply(ECFieldElement b)
- {
- return new Fp(q, x.multiply(b.toBigInteger()).mod(q));
- }
-
- public ECFieldElement divide(ECFieldElement b)
- {
- return new Fp(q, x.multiply(b.toBigInteger().modInverse(q)).mod(q));
- }
-
- public ECFieldElement negate()
- {
- return new Fp(q, x.negate().mod(q));
- }
-
- public ECFieldElement square()
- {
- return new Fp(q, x.multiply(x).mod(q));
- }
-
- public ECFieldElement invert()
- {
- return new Fp(q, x.modInverse(q));
- }
-
- // D.1.4 91
- /**
- * return a sqrt root - the routine verifies that the calculation
- * returns the right value - if none exists it returns null.
- */
- public ECFieldElement sqrt()
- {
- if (!q.testBit(0))
- {
- throw new RuntimeException("not done yet");
- }
-
- // note: even though this class implements ECConstants don't be tempted to
- // remove the explicit declaration, some J2ME environments don't cope.
- // p mod 4 == 3
- if (q.testBit(1))
- {
- // z = g^(u+1) + p, p = 4u + 3
- ECFieldElement z = new Fp(q, x.modPow(q.shiftRight(2).add(ECConstants.ONE), q));
-
- return z.square().equals(this) ? z : null;
- }
-
- // p mod 4 == 1
- BigIntegerCrypto qMinusOne = q.subtract(ECConstants.ONE);
-
- BigIntegerCrypto legendreExponent = qMinusOne.shiftRight(1);
- if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE)))
- {
- return null;
- }
-
- BigIntegerCrypto u = qMinusOne.shiftRight(2);
- BigIntegerCrypto k = u.shiftLeft(1).add(ECConstants.ONE);
-
- BigIntegerCrypto Q = this.x;
- BigIntegerCrypto fourQ = Q.shiftLeft(2).mod(q);
-
- BigIntegerCrypto U, V;
- Random rand = new Random();
- do
- {
- BigIntegerCrypto P;
- do
- {
- P = new BigIntegerCrypto(q.bitLength(), rand);
- }
- while (P.compareTo(q) >= 0
- || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, q).equals(qMinusOne)));
-
- BigIntegerCrypto[] result = lucasSequence(q, P, Q, k);
- U = result[0];
- V = result[1];
-
- if (V.multiply(V).mod(q).equals(fourQ))
- {
- // Integer division by 2, mod q
- if (V.testBit(0))
- {
- V = V.add(q);
- }
-
- V = V.shiftRight(1);
-
- //assert V.multiply(V).mod(q).equals(x);
-
- return new ECFieldElement.Fp(q, V);
- }
- }
- while (U.equals(ECConstants.ONE) || U.equals(qMinusOne));
-
- return null;
-
-// BigIntegerCrypto qMinusOne = q.subtract(ECConstants.ONE);
-// BigIntegerCrypto legendreExponent = qMinusOne.shiftRight(1); //divide(ECConstants.TWO);
-// if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE)))
-// {
-// return null;
-// }
-//
-// Random rand = new Random();
-// BigIntegerCrypto fourX = x.shiftLeft(2);
-//
-// BigIntegerCrypto r;
-// do
-// {
-// r = new BigIntegerCrypto(q.bitLength(), rand);
-// }
-// while (r.compareTo(q) >= 0
-// || !(r.multiply(r).subtract(fourX).modPow(legendreExponent, q).equals(qMinusOne)));
-//
-// BigIntegerCrypto n1 = qMinusOne.shiftRight(2); //.divide(ECConstants.FOUR);
-// BigIntegerCrypto n2 = n1.add(ECConstants.ONE); //q.add(ECConstants.THREE).divide(ECConstants.FOUR);
-//
-// BigIntegerCrypto wOne = WOne(r, x, q);
-// BigIntegerCrypto wSum = W(n1, wOne, q).add(W(n2, wOne, q)).mod(q);
-// BigIntegerCrypto twoR = r.shiftLeft(1); //ECConstants.TWO.multiply(r);
-//
-// BigIntegerCrypto root = twoR.modPow(q.subtract(ECConstants.TWO), q)
-// .multiply(x).mod(q)
-// .multiply(wSum).mod(q);
-//
-// return new Fp(q, root);
- }
-
-// private static BigIntegerCrypto W(BigIntegerCrypto n, BigIntegerCrypto wOne, BigIntegerCrypto p)
-// {
-// if (n.equals(ECConstants.ONE))
-// {
-// return wOne;
-// }
-// boolean isEven = !n.testBit(0);
-// n = n.shiftRight(1);//divide(ECConstants.TWO);
-// if (isEven)
-// {
-// BigIntegerCrypto w = W(n, wOne, p);
-// return w.multiply(w).subtract(ECConstants.TWO).mod(p);
-// }
-// BigIntegerCrypto w1 = W(n.add(ECConstants.ONE), wOne, p);
-// BigIntegerCrypto w2 = W(n, wOne, p);
-// return w1.multiply(w2).subtract(wOne).mod(p);
-// }
-//
-// private BigIntegerCrypto WOne(BigIntegerCrypto r, BigIntegerCrypto x, BigIntegerCrypto p)
-// {
-// return r.multiply(r).multiply(x.modPow(q.subtract(ECConstants.TWO), q)).subtract(ECConstants.TWO).mod(p);
-// }
-
- private static BigIntegerCrypto[] lucasSequence(
- BigIntegerCrypto p,
- BigIntegerCrypto P,
- BigIntegerCrypto Q,
- BigIntegerCrypto k)
- {
- int n = k.bitLength();
- int s = k.getLowestSetBit();
-
- BigIntegerCrypto Uh = ECConstants.ONE;
- BigIntegerCrypto Vl = ECConstants.TWO;
- BigIntegerCrypto Vh = P;
- BigIntegerCrypto Ql = ECConstants.ONE;
- BigIntegerCrypto Qh = ECConstants.ONE;
-
- for (int j = n - 1; j >= s + 1; --j)
- {
- Ql = Ql.multiply(Qh).mod(p);
-
- if (k.testBit(j))
- {
- Qh = Ql.multiply(Q).mod(p);
- Uh = Uh.multiply(Vh).mod(p);
- Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
- Vh = Vh.multiply(Vh).subtract(Qh.shiftLeft(1)).mod(p);
- }
- else
- {
- Qh = Ql;
- Uh = Uh.multiply(Vl).subtract(Ql).mod(p);
- Vh = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
- Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p);
- }
- }
-
- Ql = Ql.multiply(Qh).mod(p);
- Qh = Ql.multiply(Q).mod(p);
- Uh = Uh.multiply(Vl).subtract(Ql).mod(p);
- Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
- Ql = Ql.multiply(Qh).mod(p);
-
- for (int j = 1; j <= s; ++j)
- {
- Uh = Uh.multiply(Vl).mod(p);
- Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p);
- Ql = Ql.multiply(Ql).mod(p);
- }
-
- return new BigIntegerCrypto[]{ Uh, Vl };
- }
-
- public boolean equals(Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof ECFieldElement.Fp))
- {
- return false;
- }
-
- ECFieldElement.Fp o = (ECFieldElement.Fp)other;
- return q.equals(o.q) && x.equals(o.x);
- }
-
- public int hashCode()
- {
- return q.hashCode() ^ x.hashCode();
- }
- }
-
-// /**
-// * Class representing the Elements of the finite field
-// * F2m in polynomial basis (PB)
-// * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial
-// * basis representations are supported. Gaussian normal basis (GNB)
-// * representation is not supported.
-// */
-// public static class F2m extends ECFieldElement
-// {
-// BigIntegerCrypto x;
-//
-// /**
-// * Indicates gaussian normal basis representation (GNB). Number chosen
-// * according to X9.62. GNB is not implemented at present.
-// */
-// public static final int GNB = 1;
-//
-// /**
-// * Indicates trinomial basis representation (TPB). Number chosen
-// * according to X9.62.
-// */
-// public static final int TPB = 2;
-//
-// /**
-// * Indicates pentanomial basis representation (PPB). Number chosen
-// * according to X9.62.
-// */
-// public static final int PPB = 3;
-//
-// /**
-// * TPB or PPB.
-// */
-// private int representation;
-//
-// /**
-// * The exponent m of F2m.
-// */
-// private int m;
-//
-// /**
-// * TPB: The integer k where xm +
-// * xk + 1 represents the reduction polynomial
-// * f(z).k1 where xm +
-// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomial f(z).0k2 where xm +
-// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomial f(z).0k3 where xm +
-// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomial f(z).m of
-// * F2m.
-// * @param k1 The integer k1 where xm +
-// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomial f(z).
-// * @param k2 The integer k2 where xm +
-// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomial f(z).
-// * @param k3 The integer k3 where xm +
-// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomial f(z).
-// * @param x The BigIntegerCrypto representing the value of the field element.
-// */
-// public F2m(
-// int m,
-// int k1,
-// int k2,
-// int k3,
-// BigIntegerCrypto x)
-// {
-//// super(x);
-// this.x = x;
-//
-// if ((k2 == 0) && (k3 == 0))
-// {
-// this.representation = TPB;
-// }
-// else
-// {
-// if (k2 >= k3)
-// {
-// throw new IllegalArgumentException(
-// "k2 must be smaller than k3");
-// }
-// if (k2 <= 0)
-// {
-// throw new IllegalArgumentException(
-// "k2 must be larger than 0");
-// }
-// this.representation = PPB;
-// }
-//
-// if (x.signum() < 0)
-// {
-// throw new IllegalArgumentException("x value cannot be negative");
-// }
-//
-// this.m = m;
-// this.k1 = k1;
-// this.k2 = k2;
-// this.k3 = k3;
-// }
-//
-// /**
-// * Constructor for TPB.
-// * @param m The exponent m of
-// * F2m.
-// * @param k The integer k where xm +
-// * xk + 1 represents the reduction
-// * polynomial f(z).
-// * @param x The BigIntegerCrypto representing the value of the field element.
-// */
-// public F2m(int m, int k, BigIntegerCrypto x)
-// {
-// // Set k1 to k, and set k2 and k3 to 0
-// this(m, k, 0, 0, x);
-// }
-//
-// public BigIntegerCrypto toBigInteger()
-// {
-// return x;
-// }
-//
-// public String getFieldName()
-// {
-// return "F2m";
-// }
-//
-// public int getFieldSize()
-// {
-// return m;
-// }
-//
-// /**
-// * Checks, if the ECFieldElements a and b
-// * are elements of the same field F2m
-// * (having the same representation).
-// * @param a field element.
-// * @param b field element to be compared.
-// * @throws IllegalArgumentException if a and b
-// * are not elements of the same field
-// * F2m (having the same
-// * representation).
-// */
-// public static void checkFieldElements(
-// ECFieldElement a,
-// ECFieldElement b)
-// {
-// if ((!(a instanceof F2m)) || (!(b instanceof F2m)))
-// {
-// throw new IllegalArgumentException("Field elements are not "
-// + "both instances of ECFieldElement.F2m");
-// }
-//
-// if ((a.toBigInteger().signum() < 0) || (b.toBigInteger().signum() < 0))
-// {
-// throw new IllegalArgumentException(
-// "x value may not be negative");
-// }
-//
-// ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a;
-// ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b;
-//
-// if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1)
-// || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3))
-// {
-// throw new IllegalArgumentException("Field elements are not "
-// + "elements of the same field F2m");
-// }
-//
-// if (aF2m.representation != bF2m.representation)
-// {
-// // Should never occur
-// throw new IllegalArgumentException(
-// "One of the field "
-// + "elements are not elements has incorrect representation");
-// }
-// }
-//
-// /**
-// * Computes z * a(z) mod f(z), where f(z) is
-// * the reduction polynomial of this.
-// * @param a The polynomial a(z) to be multiplied by
-// * z mod f(z).
-// * @return z * a(z) mod f(z)
-// */
-// private BigIntegerCrypto multZModF(final BigIntegerCrypto a)
-// {
-// // Left-shift of a(z)
-// BigIntegerCrypto az = a.shiftLeft(1);
-// if (az.testBit(this.m))
-// {
-// // If the coefficient of z^m in a(z) equals 1, reduction
-// // modulo f(z) is performed: Add f(z) to to a(z):
-// // Step 1: Unset mth coeffient of a(z)
-// az = az.clearBit(this.m);
-//
-// // Step 2: Add r(z) to a(z), where r(z) is defined as
-// // f(z) = z^m + r(z), and k1, k2, k3 are the positions of
-// // the non-zero coefficients in r(z)
-// az = az.flipBit(0);
-// az = az.flipBit(this.k1);
-// if (this.representation == PPB)
-// {
-// az = az.flipBit(this.k2);
-// az = az.flipBit(this.k3);
-// }
-// }
-// return az;
-// }
-//
-// public ECFieldElement add(final ECFieldElement b)
-// {
-// // No check performed here for performance reasons. Instead the
-// // elements involved are checked in ECPoint.F2m
-// // checkFieldElements(this, b);
-// if (b.toBigInteger().signum() == 0)
-// {
-// return this;
-// }
-//
-// return new F2m(this.m, this.k1, this.k2, this.k3, this.x.xor(b.toBigInteger()));
-// }
-//
-// public ECFieldElement subtract(final ECFieldElement b)
-// {
-// // Addition and subtraction are the same in F2m
-// return add(b);
-// }
-//
-//
-// public ECFieldElement multiply(final ECFieldElement b)
-// {
-// // Left-to-right shift-and-add field multiplication in F2m
-// // Input: Binary polynomials a(z) and b(z) of degree at most m-1
-// // Output: c(z) = a(z) * b(z) mod f(z)
-//
-// // No check performed here for performance reasons. Instead the
-// // elements involved are checked in ECPoint.F2m
-// // checkFieldElements(this, b);
-// final BigIntegerCrypto az = this.x;
-// BigIntegerCrypto bz = b.toBigInteger();
-// BigIntegerCrypto cz;
-//
-// // Compute c(z) = a(z) * b(z) mod f(z)
-// if (az.testBit(0))
-// {
-// cz = bz;
-// }
-// else
-// {
-// cz = ECConstants.ZERO;
-// }
-//
-// for (int i = 1; i < this.m; i++)
-// {
-// // b(z) := z * b(z) mod f(z)
-// bz = multZModF(bz);
-//
-// if (az.testBit(i))
-// {
-// // If the coefficient of x^i in a(z) equals 1, b(z) is added
-// // to c(z)
-// cz = cz.xor(bz);
-// }
-// }
-// return new ECFieldElement.F2m(m, this.k1, this.k2, this.k3, cz);
-// }
-//
-//
-// public ECFieldElement divide(final ECFieldElement b)
-// {
-// // There may be more efficient implementations
-// ECFieldElement bInv = b.invert();
-// return multiply(bInv);
-// }
-//
-// public ECFieldElement negate()
-// {
-// // -x == x holds for all x in F2m
-// return this;
-// }
-//
-// public ECFieldElement square()
-// {
-// // Naive implementation, can probably be speeded up using modular
-// // reduction
-// return multiply(this);
-// }
-//
-// public ECFieldElement invert()
-// {
-// // Inversion in F2m using the extended Euclidean algorithm
-// // Input: A nonzero polynomial a(z) of degree at most m-1
-// // Output: a(z)^(-1) mod f(z)
-//
-// // u(z) := a(z)
-// BigIntegerCrypto uz = this.x;
-// if (uz.signum() <= 0)
-// {
-// throw new ArithmeticException("x is zero or negative, " +
-// "inversion is impossible");
-// }
-//
-// // v(z) := f(z)
-// BigIntegerCrypto vz = ECConstants.ZERO.setBit(m);
-// vz = vz.setBit(0);
-// vz = vz.setBit(this.k1);
-// if (this.representation == PPB)
-// {
-// vz = vz.setBit(this.k2);
-// vz = vz.setBit(this.k3);
-// }
-//
-// // g1(z) := 1, g2(z) := 0
-// BigIntegerCrypto g1z = ECConstants.ONE;
-// BigIntegerCrypto g2z = ECConstants.ZERO;
-//
-// // while u != 1
-// while (!(uz.equals(ECConstants.ZERO)))
-// {
-// // j := deg(u(z)) - deg(v(z))
-// int j = uz.bitLength() - vz.bitLength();
-//
-// // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j
-// if (j < 0)
-// {
-// final BigIntegerCrypto uzCopy = uz;
-// uz = vz;
-// vz = uzCopy;
-//
-// final BigIntegerCrypto g1zCopy = g1z;
-// g1z = g2z;
-// g2z = g1zCopy;
-//
-// j = -j;
-// }
-//
-// // u(z) := u(z) + z^j * v(z)
-// // Note, that no reduction modulo f(z) is required, because
-// // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z)))
-// // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z))
-// // = deg(u(z))
-// uz = uz.xor(vz.shiftLeft(j));
-//
-// // g1(z) := g1(z) + z^j * g2(z)
-// g1z = g1z.xor(g2z.shiftLeft(j));
-//// if (g1z.bitLength() > this.m) {
-//// throw new ArithmeticException(
-//// "deg(g1z) >= m, g1z = " + g1z.toString(2));
-//// }
-// }
-// return new ECFieldElement.F2m(
-// this.m, this.k1, this.k2, this.k3, g2z);
-// }
-//
-// public ECFieldElement sqrt()
-// {
-// throw new RuntimeException("Not implemented");
-// }
-//
-// /**
-// * @return the representation of the field
-// * F2m, either of
-// * TPB (trinomial
-// * basis representation) or
-// * PPB (pentanomial
-// * basis representation).
-// */
-// public int getRepresentation()
-// {
-// return this.representation;
-// }
-//
-// /**
-// * @return the degree m of the reduction polynomial
-// * f(z).
-// */
-// public int getM()
-// {
-// return this.m;
-// }
-//
-// /**
-// * @return TPB: The integer k where xm +
-// * xk + 1 represents the reduction polynomial
-// * f(z).k1 where xm +
-// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomial f(z).0k2 where xm +
-// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomial f(z).0k3 where xm +
-// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomial f(z).F2m in polynomial basis (PB)
- * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial
- * basis representations are supported. Gaussian normal basis (GNB)
- * representation is not supported.
- */
- public static class F2m extends ECFieldElement
- {
- /**
- * Indicates gaussian normal basis representation (GNB). Number chosen
- * according to X9.62. GNB is not implemented at present.
- */
- public static final int GNB = 1;
-
- /**
- * Indicates trinomial basis representation (TPB). Number chosen
- * according to X9.62.
- */
- public static final int TPB = 2;
-
- /**
- * Indicates pentanomial basis representation (PPB). Number chosen
- * according to X9.62.
- */
- public static final int PPB = 3;
-
- /**
- * TPB or PPB.
- */
- private int representation;
-
- /**
- * The exponent m of F2m.
- */
- private int m;
-
- /**
- * TPB: The integer k where xm +
- * xk + 1 represents the reduction polynomial
- * f(z).k1 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).0k2 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).0k3 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).IntArray holding the bits.
- */
- private IntArray x;
-
- /**
- * The number of ints required to hold m bits.
- */
- private int t;
-
- /**
- * Constructor for PPB.
- * @param m The exponent m of
- * F2m.
- * @param k1 The integer k1 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).
- * @param k2 The integer k2 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).
- * @param k3 The integer k3 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).
- * @param x The BigInteger representing the value of the field element.
- */
- public F2m(
- int m,
- int k1,
- int k2,
- int k3,
- BigIntegerCrypto x)
- {
- // t = m / 32 rounded up to the next integer
- t = (m + 31) >> 5;
- this.x = new IntArray(x, t);
-
- if ((k2 == 0) && (k3 == 0))
- {
- this.representation = TPB;
- }
- else
- {
- if (k2 >= k3)
- {
- throw new IllegalArgumentException(
- "k2 must be smaller than k3");
- }
- if (k2 <= 0)
- {
- throw new IllegalArgumentException(
- "k2 must be larger than 0");
- }
- this.representation = PPB;
- }
-
- if (x.signum() < 0)
- {
- throw new IllegalArgumentException("x value cannot be negative");
- }
-
- this.m = m;
- this.k1 = k1;
- this.k2 = k2;
- this.k3 = k3;
- }
-
- /**
- * Constructor for TPB.
- * @param m The exponent m of
- * F2m.
- * @param k The integer k where xm +
- * xk + 1 represents the reduction
- * polynomial f(z).
- * @param x The BigInteger representing the value of the field element.
- */
- public F2m(int m, int k, BigIntegerCrypto x)
- {
- // Set k1 to k, and set k2 and k3 to 0
- this(m, k, 0, 0, x);
- }
-
- private F2m(int m, int k1, int k2, int k3, IntArray x)
- {
- t = (m + 31) >> 5;
- this.x = x;
- this.m = m;
- this.k1 = k1;
- this.k2 = k2;
- this.k3 = k3;
-
- if ((k2 == 0) && (k3 == 0))
- {
- this.representation = TPB;
- }
- else
- {
- this.representation = PPB;
- }
-
- }
-
- public BigIntegerCrypto toBigInteger()
- {
- return x.toBigInteger();
- }
-
- public String getFieldName()
- {
- return "F2m";
- }
-
- public int getFieldSize()
- {
- return m;
- }
-
- /**
- * Checks, if the ECFieldElements a and b
- * are elements of the same field F2m
- * (having the same representation).
- * @param a field element.
- * @param b field element to be compared.
- * @throws IllegalArgumentException if a and b
- * are not elements of the same field
- * F2m (having the same
- * representation).
- */
- public static void checkFieldElements(
- ECFieldElement a,
- ECFieldElement b)
- {
- if ((!(a instanceof F2m)) || (!(b instanceof F2m)))
- {
- throw new IllegalArgumentException("Field elements are not "
- + "both instances of ECFieldElement.F2m");
- }
-
- ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a;
- ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b;
-
- if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1)
- || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3))
- {
- throw new IllegalArgumentException("Field elements are not "
- + "elements of the same field F2m");
- }
-
- if (aF2m.representation != bF2m.representation)
- {
- // Should never occur
- throw new IllegalArgumentException(
- "One of the field "
- + "elements are not elements has incorrect representation");
- }
- }
-
- public ECFieldElement add(final ECFieldElement b)
- {
- // No check performed here for performance reasons. Instead the
- // elements involved are checked in ECPoint.F2m
- // checkFieldElements(this, b);
- IntArray iarrClone = (IntArray)this.x.clone();
- F2m bF2m = (F2m)b;
- iarrClone.addShifted(bF2m.x, 0);
- return new F2m(m, k1, k2, k3, iarrClone);
- }
-
- public ECFieldElement subtract(final ECFieldElement b)
- {
- // Addition and subtraction are the same in F2m
- return add(b);
- }
-
- public ECFieldElement multiply(final ECFieldElement b)
- {
- // Right-to-left comb multiplication in the IntArray
- // Input: Binary polynomials a(z) and b(z) of degree at most m-1
- // Output: c(z) = a(z) * b(z) mod f(z)
-
- // No check performed here for performance reasons. Instead the
- // elements involved are checked in ECPoint.F2m
- // checkFieldElements(this, b);
- F2m bF2m = (F2m)b;
- IntArray mult = x.multiply(bF2m.x, m);
- mult.reduce(m, new int[]{k1, k2, k3});
- return new F2m(m, k1, k2, k3, mult);
- }
-
- public ECFieldElement divide(final ECFieldElement b)
- {
- // There may be more efficient implementations
- ECFieldElement bInv = b.invert();
- return multiply(bInv);
- }
-
- public ECFieldElement negate()
- {
- // -x == x holds for all x in F2m
- return this;
- }
-
- public ECFieldElement square()
- {
- IntArray squared = x.square(m);
- squared.reduce(m, new int[]{k1, k2, k3});
- return new F2m(m, k1, k2, k3, squared);
- }
-
-
- public ECFieldElement invert()
- {
- // Inversion in F2m using the extended Euclidean algorithm
- // Input: A nonzero polynomial a(z) of degree at most m-1
- // Output: a(z)^(-1) mod f(z)
-
- // u(z) := a(z)
- IntArray uz = (IntArray)this.x.clone();
-
- // v(z) := f(z)
- IntArray vz = new IntArray(t);
- vz.setBit(m);
- vz.setBit(0);
- vz.setBit(this.k1);
- if (this.representation == PPB)
- {
- vz.setBit(this.k2);
- vz.setBit(this.k3);
- }
-
- // g1(z) := 1, g2(z) := 0
- IntArray g1z = new IntArray(t);
- g1z.setBit(0);
- IntArray g2z = new IntArray(t);
-
- // while u != 0
- while (!uz.isZero())
-// while (uz.getUsedLength() > 0)
-// while (uz.bitLength() > 1)
- {
- // j := deg(u(z)) - deg(v(z))
- int j = uz.bitLength() - vz.bitLength();
-
- // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j
- if (j < 0)
- {
- final IntArray uzCopy = uz;
- uz = vz;
- vz = uzCopy;
-
- final IntArray g1zCopy = g1z;
- g1z = g2z;
- g2z = g1zCopy;
-
- j = -j;
- }
-
- // u(z) := u(z) + z^j * v(z)
- // Note, that no reduction modulo f(z) is required, because
- // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z)))
- // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z))
- // = deg(u(z))
- // uz = uz.xor(vz.shiftLeft(j));
- // jInt = n / 32
- int jInt = j >> 5;
- // jInt = n % 32
- int jBit = j & 0x1F;
- IntArray vzShift = vz.shiftLeft(jBit);
- uz.addShifted(vzShift, jInt);
-
- // g1(z) := g1(z) + z^j * g2(z)
-// g1z = g1z.xor(g2z.shiftLeft(j));
- IntArray g2zShift = g2z.shiftLeft(jBit);
- g1z.addShifted(g2zShift, jInt);
-
- }
- return new ECFieldElement.F2m(
- this.m, this.k1, this.k2, this.k3, g2z);
- }
-
- public ECFieldElement sqrt()
- {
- throw new RuntimeException("Not implemented");
- }
-
- /**
- * @return the representation of the field
- * F2m, either of
- * TPB (trinomial
- * basis representation) or
- * PPB (pentanomial
- * basis representation).
- */
- public int getRepresentation()
- {
- return this.representation;
- }
-
- /**
- * @return the degree m of the reduction polynomial
- * f(z).
- */
- public int getM()
- {
- return this.m;
- }
-
- /**
- * @return TPB: The integer k where xm +
- * xk + 1 represents the reduction polynomial
- * f(z).k1 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).0k2 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).0k3 where xm +
- * xk3 + xk2 + xk1 + 1
- * represents the reduction polynomial f(z).ECPoints.
- */
-interface ECMultiplier
-{
- /**
- * Multiplies the ECPoint p by k, i.e.
- * p is added k times to itself.
- * @param p The ECPoint to be multiplied.
- * @param k The factor by which p i multiplied.
- * @return p multiplied by k.
- */
- ECPoint multiply(ECPoint p, BigIntegerCrypto k, PreCompInfo preCompInfo);
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/ECPoint.java b/src/org/bouncycastle/mathzrtp/ec/ECPoint.java
deleted file mode 100755
index c9c9682..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/ECPoint.java
+++ /dev/null
@@ -1,592 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-
-/**
- * base class for points on elliptic curves.
- */
-public abstract class ECPoint
-{
- ECCurve curve;
- ECFieldElement x;
- ECFieldElement y;
-
- protected boolean withCompression;
-
- protected ECMultiplier multiplier = null;
-
- protected PreCompInfo preCompInfo = null;
-
- private static X9IntegerConverter converter = new X9IntegerConverter();
-
- protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this.curve = curve;
- this.x = x;
- this.y = y;
- }
-
- public ECCurve getCurve()
- {
- return curve;
- }
-
- public ECFieldElement getX()
- {
- return x;
- }
-
- public ECFieldElement getY()
- {
- return y;
- }
-
- public boolean isInfinity()
- {
- return x == null && y == null;
- }
-
- public boolean isCompressed()
- {
- return withCompression;
- }
-
- public boolean equals(
- Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof ECPoint))
- {
- return false;
- }
-
- ECPoint o = (ECPoint)other;
-
- if (this.isInfinity())
- {
- return o.isInfinity();
- }
-
- return x.equals(o.x) && y.equals(o.y);
- }
-
- public int hashCode()
- {
- if (this.isInfinity())
- {
- return 0;
- }
-
- return x.hashCode() ^ y.hashCode();
- }
-
-// /**
-// * Mainly for testing. Explicitly set the ECMultiplier.
-// * @param multiplier The ECMultiplier to be used to multiply
-// * this ECPoint.
-// */
-// public void setECMultiplier(ECMultiplier multiplier)
-// {
-// this.multiplier = multiplier;
-// }
-
- /**
- * Sets the PreCompInfo. Used by ECMultipliers
- * to save the precomputation for this ECPoint to store the
- * precomputation result for use by subsequent multiplication.
- * @param preCompInfo The values precomputed by the
- * ECMultiplier.
- */
- void setPreCompInfo(PreCompInfo preCompInfo)
- {
- this.preCompInfo = preCompInfo;
- }
-
- public abstract byte[] getEncoded();
-
- public abstract ECPoint add(ECPoint b);
- public abstract ECPoint subtract(ECPoint b);
- public abstract ECPoint negate();
- public abstract ECPoint twice();
-
- /**
- * Sets the default ECMultiplier, unless already set.
- */
- synchronized void assertECMultiplier()
- {
- if (this.multiplier == null)
- {
- this.multiplier = new FpNafMultiplier();
- }
- }
-
- /**
- * Multiplies this ECPoint by the given number.
- * @param k The multiplicator.
- * @return k * this.
- */
- public ECPoint multiply(BigIntegerCrypto k)
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- if (k.signum() == 0)
- {
- return this.curve.getInfinity();
- }
-
- assertECMultiplier();
- return this.multiplier.multiply(this, k, preCompInfo);
- }
-
- /**
- * Elliptic curve points over Fp
- */
- public static class Fp extends ECPoint
- {
-
- /**
- * Create a point which encodes with point compression.
- *
- * @param curve the curve to use
- * @param x affine x co-ordinate
- * @param y affine y co-ordinate
- */
- public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * Create a point that encodes with or without point compresion.
- *
- * @param curve the curve to use
- * @param x affine x co-ordinate
- * @param y affine y co-ordinate
- * @param withCompression if true encode with point compression
- */
- public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x != null && y == null) || (x == null && y != null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- this.withCompression = withCompression;
- }
-
- /**
- * return the field element encoded with point compression. (S 4.3.6)
- */
- public byte[] getEncoded()
- {
- if (this.isInfinity())
- {
- return new byte[1];
- }
-
- int qLength = converter.getByteLength(x);
-
- if (withCompression)
- {
- byte PC;
-
- if (this.getY().toBigInteger().testBit(0))
- {
- PC = 0x03;
- }
- else
- {
- PC = 0x02;
- }
-
- byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
- byte[] PO = new byte[X.length + 1];
-
- PO[0] = PC;
- System.arraycopy(X, 0, PO, 1, X.length);
-
- return PO;
- }
- else
- {
- byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
- byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), qLength);
- byte[] PO = new byte[X.length + Y.length + 1];
-
- PO[0] = 0x04;
- System.arraycopy(X, 0, PO, 1, X.length);
- System.arraycopy(Y, 0, PO, X.length + 1, Y.length);
-
- return PO;
- }
- }
-
- // B.3 pg 62
- public ECPoint add(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
-
- if (b.isInfinity())
- {
- return this;
- }
-
- // Check if b = this or b = -this
- if (this.x.equals(b.x))
- {
- if (this.y.equals(b.y))
- {
- // this = b, i.e. this must be doubled
- return this.twice();
- }
-
- // this = -b, i.e. the result is the point at infinity
- return this.curve.getInfinity();
- }
-
- ECFieldElement gamma = b.y.subtract(this.y).divide(b.x.subtract(this.x));
-
- ECFieldElement x3 = gamma.square().subtract(this.x).subtract(b.x);
- ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
-
- return new ECPoint.Fp(curve, x3, y3);
- }
-
- // B.3 pg 62
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- // Twice identity element (point at infinity) is identity
- return this;
- }
-
- if (this.y.toBigInteger().signum() == 0)
- {
- // if y1 == 0, then (x1, y1) == (x1, -y1)
- // and hence this = -this and thus 2(x1, y1) == infinity
- return this.curve.getInfinity();
- }
-
- ECFieldElement TWO = this.curve.fromBigInteger(BigIntegerCrypto.valueOf(2));
- ECFieldElement THREE = this.curve.fromBigInteger(BigIntegerCrypto.valueOf(3));
- ECFieldElement gamma = this.x.square().multiply(THREE).add(curve.a).divide(y.multiply(TWO));
-
- ECFieldElement x3 = gamma.square().subtract(this.x.multiply(TWO));
- ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
-
- return new ECPoint.Fp(curve, x3, y3, this.withCompression);
- }
-
- // D.3.2 pg 102 (see Note:)
- public ECPoint subtract(ECPoint b)
- {
- if (b.isInfinity())
- {
- return this;
- }
-
- // Add -b
- return add(b.negate());
- }
-
- public ECPoint negate()
- {
- return new ECPoint.Fp(curve, this.x, this.y.negate(), this.withCompression);
- }
-
- // TODO Uncomment this to enable WNAF algorithm for Fp point multiplication
-// /**
-// * Sets the default ECMultiplier, unless already set.
-// */
-// synchronized void assertECMultiplier()
-// {
-// if (this.multiplier == null)
-// {
-// this.multiplier = new WNafMultiplier();
-// }
-// }
- }
-
- /**
- * Elliptic curve points over F2m
- */
- public static class F2m extends ECPoint
- {
- /**
- * @param curve base curve
- * @param x x point
- * @param y y point
- */
- public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * @param curve base curve
- * @param x x point
- * @param y y point
- * @param withCompression true if encode with point compression.
- */
- public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x != null && y == null) || (x == null && y != null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- if (x != null)
- {
- // Check if x and y are elements of the same field
- ECFieldElement.F2m.checkFieldElements(this.x, this.y);
-
- // Check if x and a are elements of the same field
- if (curve != null)
- {
- ECFieldElement.F2m.checkFieldElements(this.x, this.curve.getA());
- }
- }
-
- this.withCompression = withCompression;
- }
-
- /**
- * @deprecated use ECCurve.getInfinity()
- * Constructor for point at infinity
- */
- public F2m(ECCurve curve)
- {
- super(curve, null, null);
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#getEncoded()
- */
- public byte[] getEncoded()
- {
- if (this.isInfinity())
- {
- return new byte[1];
- }
-
- int byteCount = converter.getByteLength(this.x);
- byte[] X = converter.integerToBytes(this.getX().toBigInteger(), byteCount);
- byte[] PO;
-
- if (withCompression)
- {
- // See X9.62 4.3.6 and 4.2.2
- PO = new byte[byteCount + 1];
-
- PO[0] = 0x02;
- // X9.62 4.2.2 and 4.3.6:
- // if x = 0 then ypTilde := 0, else ypTilde is the rightmost
- // bit of y * x^(-1)
- // if ypTilde = 0, then PC := 02, else PC := 03
- // Note: PC === PO[0]
- if (!(this.getX().toBigInteger().equals(ECConstants.ZERO)))
- {
- if (this.getY().multiply(this.getX().invert())
- .toBigInteger().testBit(0))
- {
- // ypTilde = 1, hence PC = 03
- PO[0] = 0x03;
- }
- }
-
- System.arraycopy(X, 0, PO, 1, byteCount);
- }
- else
- {
- byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), byteCount);
-
- PO = new byte[byteCount + byteCount + 1];
-
- PO[0] = 0x04;
- System.arraycopy(X, 0, PO, 1, byteCount);
- System.arraycopy(Y, 0, PO, byteCount + 1, byteCount);
- }
-
- return PO;
- }
-
- /**
- * Check, if two ECPoints can be added or subtracted.
- * @param a The first ECPoint to check.
- * @param b The second ECPoint to check.
- * @throws IllegalArgumentException if a and b
- * cannot be added.
- */
- private static void checkPoints(ECPoint a, ECPoint b)
- {
- // Check, if points are on the same curve
- if (!(a.curve.equals(b.curve)))
- {
- throw new IllegalArgumentException("Only points on the same "
- + "curve can be added or subtracted");
- }
-
-// ECFieldElement.F2m.checkFieldElements(a.x, b.x);
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint)
- */
- public ECPoint add(ECPoint b)
- {
- checkPoints(this, b);
- return addSimple((ECPoint.F2m)b);
- }
-
- /**
- * Adds another ECPoints.F2m to this without
- * checking if both points are on the same curve. Used by multiplication
- * algorithms, because there all points are a multiple of the same point
- * and hence the checks can be omitted.
- * @param b The other ECPoints.F2m to add to
- * this.
- * @return this + b
- */
- public ECPoint.F2m addSimple(ECPoint.F2m b)
- {
- ECPoint.F2m other = b;
- if (this.isInfinity())
- {
- return other;
- }
-
- if (other.isInfinity())
- {
- return this;
- }
-
- ECFieldElement.F2m x2 = (ECFieldElement.F2m)other.getX();
- ECFieldElement.F2m y2 = (ECFieldElement.F2m)other.getY();
-
- // Check if other = this or other = -this
- if (this.x.equals(x2))
- {
- if (this.y.equals(y2))
- {
- // this = other, i.e. this must be doubled
- return (ECPoint.F2m)this.twice();
- }
-
- // this = -other, i.e. the result is the point at infinity
- return (ECPoint.F2m)this.curve.getInfinity();
- }
-
- ECFieldElement.F2m lambda
- = (ECFieldElement.F2m)(this.y.add(y2)).divide(this.x.add(x2));
-
- ECFieldElement.F2m x3
- = (ECFieldElement.F2m)lambda.square().add(lambda).add(this.x).add(x2).add(this.curve.getA());
-
- ECFieldElement.F2m y3
- = (ECFieldElement.F2m)lambda.multiply(this.x.add(x3)).add(x3).add(this.y);
-
- return new ECPoint.F2m(curve, x3, y3, withCompression);
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint)
- */
- public ECPoint subtract(ECPoint b)
- {
- checkPoints(this, b);
- return subtractSimple((ECPoint.F2m)b);
- }
-
- /**
- * Subtracts another ECPoints.F2m from this
- * without checking if both points are on the same curve. Used by
- * multiplication algorithms, because there all points are a multiple
- * of the same point and hence the checks can be omitted.
- * @param b The other ECPoints.F2m to subtract from
- * this.
- * @return this - b
- */
- public ECPoint.F2m subtractSimple(ECPoint.F2m b)
- {
- if (b.isInfinity())
- {
- return this;
- }
-
- // Add -b
- return addSimple((ECPoint.F2m)b.negate());
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#twice()
- */
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- // Twice identity element (point at infinity) is identity
- return this;
- }
-
- if (this.x.toBigInteger().signum() == 0)
- {
- // if x1 == 0, then (x1, y1) == (x1, x1 + y1)
- // and hence this = -this and thus 2(x1, y1) == infinity
- return this.curve.getInfinity();
- }
-
- ECFieldElement.F2m lambda
- = (ECFieldElement.F2m)this.x.add(this.y.divide(this.x));
-
- ECFieldElement.F2m x3
- = (ECFieldElement.F2m)lambda.square().add(lambda).
- add(this.curve.getA());
-
- ECFieldElement ONE = this.curve.fromBigInteger(ECConstants.ONE);
- ECFieldElement.F2m y3
- = (ECFieldElement.F2m)this.x.square().add(
- x3.multiply(lambda.add(ONE)));
-
- return new ECPoint.F2m(this.curve, x3, y3, withCompression);
- }
-
- public ECPoint negate()
- {
- return new ECPoint.F2m(curve, this.getX(), this.getY().add(this.getX()), withCompression);
- }
-
- // TODO Uncomment this to enable WNAF/WTNAF F2m point multiplication
-// /**
-// * Sets the appropriate ECMultiplier, unless already set.
-// */
-// synchronized void assertECMultiplier()
-// {
-// if (this.multiplier == null)
-// {
-// if (((ECCurve.F2m)(this.curve)).isKoblitz())
-// {
-// this.multiplier = new WTauNafMultiplier();
-// }
-// else
-// {
-// this.multiplier = new WNafMultiplier();
-// }
-// }
-// }
- }
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/FpNafMultiplier.java b/src/org/bouncycastle/mathzrtp/ec/FpNafMultiplier.java
deleted file mode 100755
index 21ba32a..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/FpNafMultiplier.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-
-/**
- * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm.
- */
-class FpNafMultiplier implements ECMultiplier
-{
- /**
- * 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, BigIntegerCrypto k, PreCompInfo preCompInfo)
- {
- // TODO Probably should try to add this
- // BigInteger e = k.mod(n); // n == order of p
- BigIntegerCrypto e = k;
- BigIntegerCrypto h = e.multiply(BigIntegerCrypto.valueOf(3));
-
- ECPoint neg = p.negate();
- ECPoint R = p;
-
- for (int i = h.bitLength() - 2; i > 0; --i)
- {
- R = R.twice();
-
- boolean hBit = h.testBit(i);
- boolean eBit = e.testBit(i);
-
- if (hBit != eBit)
- {
- R = R.add(hBit ? p : neg);
- }
- }
-
- return R;
- }
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/IntArray.java b/src/org/bouncycastle/mathzrtp/ec/IntArray.java
deleted file mode 100755
index e6a8356..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/IntArray.java
+++ /dev/null
@@ -1,518 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-import org.bouncycastle.util.Arrays;
-
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-
-class IntArray
-{
- // TODO make m fixed for the IntArray, and hence compute T once and for all
-
- private int[] m_ints;
-
- public IntArray(int intLen)
- {
- m_ints = new int[intLen];
- }
-
- public IntArray(int[] ints)
- {
- m_ints = ints;
- }
-
- public IntArray(BigIntegerCrypto bigInt)
- {
- this(bigInt, 0);
- }
-
- public IntArray(BigIntegerCrypto bigInt, int minIntLen)
- {
- if (bigInt.signum() == -1)
- {
- throw new IllegalArgumentException("Only positive Integers allowed");
- }
- if (bigInt.equals(ECConstants.ZERO))
- {
- m_ints = new int[] { 0 };
- return;
- }
-
- byte[] barr = bigInt.toByteArray();
- int barrLen = barr.length;
- int barrStart = 0;
- if (barr[0] == 0)
- {
- // First byte is 0 to enforce highest (=sign) bit is zero.
- // In this case ignore barr[0].
- barrLen--;
- barrStart = 1;
- }
- int intLen = (barrLen + 3) / 4;
- if (intLen < minIntLen)
- {
- m_ints = new int[minIntLen];
- }
- else
- {
- m_ints = new int[intLen];
- }
-
- int iarrJ = intLen - 1;
- int rem = barrLen % 4 + barrStart;
- int temp = 0;
- int barrI = barrStart;
- if (barrStart < rem)
- {
- for (; barrI < rem; barrI++)
- {
- temp <<= 8;
- int barrBarrI = barr[barrI];
- if (barrBarrI < 0)
- {
- barrBarrI += 256;
- }
- temp |= barrBarrI;
- }
- m_ints[iarrJ--] = temp;
- }
-
- for (; iarrJ >= 0; iarrJ--)
- {
- temp = 0;
- for (int i = 0; i < 4; i++)
- {
- temp <<= 8;
- int barrBarrI = barr[barrI++];
- if (barrBarrI < 0)
- {
- barrBarrI += 256;
- }
- temp |= barrBarrI;
- }
- m_ints[iarrJ] = temp;
- }
- }
-
- public boolean isZero()
- {
- return m_ints.length == 0
- || (m_ints[0] == 0 && getUsedLength() == 0);
- }
-
- public int getUsedLength()
- {
- int highestIntPos = m_ints.length;
-
- if (highestIntPos < 1)
- {
- return 0;
- }
-
- // Check if first element will act as sentinel
- if (m_ints[0] != 0)
- {
- while (m_ints[--highestIntPos] == 0)
- {
- }
- return highestIntPos + 1;
- }
-
- do
- {
- if (m_ints[--highestIntPos] != 0)
- {
- return highestIntPos + 1;
- }
- }
- while (highestIntPos > 0);
-
- return 0;
- }
-
- public int bitLength()
- {
- // JDK 1.5: see Integer.numberOfLeadingZeros()
- int intLen = getUsedLength();
- if (intLen == 0)
- {
- return 0;
- }
-
- int last = intLen - 1;
- int highest = m_ints[last];
- int bits = (last << 5) + 1;
-
- // A couple of binary search steps
- if ((highest & 0xffff0000) != 0)
- {
- if ((highest & 0xff000000) != 0)
- {
- bits += 24;
- highest >>>= 24;
- }
- else
- {
- bits += 16;
- highest >>>= 16;
- }
- }
- else if (highest > 0x000000ff)
- {
- bits += 8;
- highest >>>= 8;
- }
-
- while (highest != 1)
- {
- ++bits;
- highest >>>= 1;
- }
-
- return bits;
- }
-
- private int[] resizedInts(int newLen)
- {
- int[] newInts = new int[newLen];
- int oldLen = m_ints.length;
- int copyLen = oldLen < newLen ? oldLen : newLen;
- System.arraycopy(m_ints, 0, newInts, 0, copyLen);
- return newInts;
- }
-
- public BigIntegerCrypto toBigInteger()
- {
- int usedLen = getUsedLength();
- if (usedLen == 0)
- {
- return ECConstants.ZERO;
- }
-
- int highestInt = m_ints[usedLen - 1];
- byte[] temp = new byte[4];
- int barrI = 0;
- boolean trailingZeroBytesDone = false;
- for (int j = 3; j >= 0; j--)
- {
- byte thisByte = (byte) (highestInt >>> (8 * j));
- if (trailingZeroBytesDone || (thisByte != 0))
- {
- trailingZeroBytesDone = true;
- temp[barrI++] = thisByte;
- }
- }
-
- int barrLen = 4 * (usedLen - 1) + barrI;
- byte[] barr = new byte[barrLen];
- for (int j = 0; j < barrI; j++)
- {
- barr[j] = temp[j];
- }
- // Highest value int is done now
-
- for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
- {
- for (int j = 3; j >= 0; j--)
- {
- barr[barrI++] = (byte) (m_ints[iarrJ] >>> (8 * j));
- }
- }
- return new BigIntegerCrypto(1, barr);
- }
-
- public void shiftLeft()
- {
- int usedLen = getUsedLength();
- if (usedLen == 0)
- {
- return;
- }
- if (m_ints[usedLen - 1] < 0)
- {
- // highest bit of highest used byte is set, so shifting left will
- // make the IntArray one byte longer
- usedLen++;
- if (usedLen > m_ints.length)
- {
- // make the m_ints one byte longer, because we need one more
- // byte which is not available in m_ints
- m_ints = resizedInts(m_ints.length + 1);
- }
- }
-
- boolean carry = false;
- for (int i = 0; i < usedLen; i++)
- {
- // nextCarry is true if highest bit is set
- boolean nextCarry = m_ints[i] < 0;
- m_ints[i] <<= 1;
- if (carry)
- {
- // set lowest bit
- m_ints[i] |= 1;
- }
- carry = nextCarry;
- }
- }
-
- public IntArray shiftLeft(int n)
- {
- int usedLen = getUsedLength();
- if (usedLen == 0)
- {
- return this;
- }
-
- if (n == 0)
- {
- return this;
- }
-
- if (n > 31)
- {
- throw new IllegalArgumentException("shiftLeft() for max 31 bits "
- + ", " + n + "bit shift is not possible");
- }
-
- int[] newInts = new int[usedLen + 1];
-
- int nm32 = 32 - n;
- newInts[0] = m_ints[0] << n;
- for (int i = 1; i < usedLen; i++)
- {
- newInts[i] = (m_ints[i] << n) | (m_ints[i - 1] >>> nm32);
- }
- newInts[usedLen] = m_ints[usedLen - 1] >>> nm32;
-
- return new IntArray(newInts);
- }
-
- public void addShifted(IntArray other, int shift)
- {
- int usedLenOther = other.getUsedLength();
- int newMinUsedLen = usedLenOther + shift;
- if (newMinUsedLen > m_ints.length)
- {
- m_ints = resizedInts(newMinUsedLen);
- //System.out.println("Resize required");
- }
-
- for (int i = 0; i < usedLenOther; i++)
- {
- m_ints[i + shift] ^= other.m_ints[i];
- }
- }
-
- public int getLength()
- {
- return m_ints.length;
- }
-
- public boolean testBit(int n)
- {
- // theInt = n / 32
- int theInt = n >> 5;
- // theBit = n % 32
- int theBit = n & 0x1F;
- int tester = 1 << theBit;
- return ((m_ints[theInt] & tester) != 0);
- }
-
- public void flipBit(int n)
- {
- // theInt = n / 32
- int theInt = n >> 5;
- // theBit = n % 32
- int theBit = n & 0x1F;
- int flipper = 1 << theBit;
- m_ints[theInt] ^= flipper;
- }
-
- public void setBit(int n)
- {
- // theInt = n / 32
- int theInt = n >> 5;
- // theBit = n % 32
- int theBit = n & 0x1F;
- int setter = 1 << theBit;
- m_ints[theInt] |= setter;
- }
-
- public IntArray multiply(IntArray other, int m)
- {
- // Lenght of c is 2m bits rounded up to the next int (32 bit)
- int t = (m + 31) >> 5;
- if (m_ints.length < t)
- {
- m_ints = resizedInts(t);
- }
-
- IntArray b = new IntArray(other.resizedInts(other.getLength() + 1));
- IntArray c = new IntArray((m + m + 31) >> 5);
- // IntArray c = new IntArray(t + t);
- int testBit = 1;
- for (int k = 0; k < 32; k++)
- {
- for (int j = 0; j < t; j++)
- {
- if ((m_ints[j] & testBit) != 0)
- {
- // The kth bit of m_ints[j] is set
- c.addShifted(b, j);
- }
- }
- testBit <<= 1;
- b.shiftLeft();
- }
- return c;
- }
-
- // public IntArray multiplyLeftToRight(IntArray other, int m) {
- // // Lenght of c is 2m bits rounded up to the next int (32 bit)
- // int t = (m + 31) / 32;
- // if (m_ints.length < t) {
- // m_ints = resizedInts(t);
- // }
- //
- // IntArray b = new IntArray(other.resizedInts(other.getLength() + 1));
- // IntArray c = new IntArray((m + m + 31) / 32);
- // // IntArray c = new IntArray(t + t);
- // int testBit = 1 << 31;
- // for (int k = 31; k >= 0; k--) {
- // for (int j = 0; j < t; j++) {
- // if ((m_ints[j] & testBit) != 0) {
- // // The kth bit of m_ints[j] is set
- // c.addShifted(b, j);
- // }
- // }
- // testBit >>>= 1;
- // if (k > 0) {
- // c.shiftLeft();
- // }
- // }
- // return c;
- // }
-
- // TODO note, redPol.length must be 3 for TPB and 5 for PPB
- public void reduce(int m, int[] redPol)
- {
- for (int i = m + m - 2; i >= m; i--)
- {
- if (testBit(i))
- {
- int bit = i - m;
- flipBit(bit);
- flipBit(i);
- int l = redPol.length;
- while (--l >= 0)
- {
- flipBit(redPol[l] + bit);
- }
- }
- }
- m_ints = resizedInts((m + 31) >> 5);
- }
-
- public IntArray square(int m)
- {
- // TODO make the table static final
- final int[] table = { 0x0, 0x1, 0x4, 0x5, 0x10, 0x11, 0x14, 0x15, 0x40,
- 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 };
-
- int t = (m + 31) >> 5;
- if (m_ints.length < t)
- {
- m_ints = resizedInts(t);
- }
-
- IntArray c = new IntArray(t + t);
-
- // TODO twice the same code, put in separate private method
- for (int i = 0; i < t; i++)
- {
- int v0 = 0;
- for (int j = 0; j < 4; j++)
- {
- v0 = v0 >>> 8;
- int u = (m_ints[i] >>> (j * 4)) & 0xF;
- int w = table[u] << 24;
- v0 |= w;
- }
- c.m_ints[i + i] = v0;
-
- v0 = 0;
- int upper = m_ints[i] >>> 16;
- for (int j = 0; j < 4; j++)
- {
- v0 = v0 >>> 8;
- int u = (upper >>> (j * 4)) & 0xF;
- int w = table[u] << 24;
- v0 |= w;
- }
- c.m_ints[i + i + 1] = v0;
- }
- return c;
- }
-
- public boolean equals(Object o)
- {
- if (!(o instanceof IntArray))
- {
- return false;
- }
- IntArray other = (IntArray) o;
- int usedLen = getUsedLength();
- if (other.getUsedLength() != usedLen)
- {
- return false;
- }
- for (int i = 0; i < usedLen; i++)
- {
- if (m_ints[i] != other.m_ints[i])
- {
- return false;
- }
- }
- return true;
- }
-
- public int hashCode()
- {
- int usedLen = getUsedLength();
- int hash = 1;
- for (int i = 0; i < usedLen; i++)
- {
- hash = hash * 31 + m_ints[i];
- }
- return hash;
- }
-
- public Object clone()
- {
- return new IntArray(Arrays.clone(m_ints));
- }
-
- public String toString()
- {
- int usedLen = getUsedLength();
- if (usedLen == 0)
- {
- return "0";
- }
-
- StringBuffer sb = new StringBuffer(Integer
- .toBinaryString(m_ints[usedLen - 1]));
- for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
- {
- String hexString = Integer.toBinaryString(m_ints[iarrJ]);
-
- // Add leading zeroes, except for highest significant int
- for (int i = hexString.length(); i < 8; i++)
- {
- hexString = "0" + hexString;
- }
- sb.append(hexString);
- }
- return sb.toString();
- }
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/PreCompInfo.java b/src/org/bouncycastle/mathzrtp/ec/PreCompInfo.java
deleted file mode 100755
index ee67294..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/PreCompInfo.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-/**
- * Interface for classes storing precomputation data for multiplication
- * algorithms. Used as a Memento (see GOF patterns) for
- * WNafMultiplier.
- */
-interface PreCompInfo
-{
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/ReferenceMultiplier.java b/src/org/bouncycastle/mathzrtp/ec/ReferenceMultiplier.java
deleted file mode 100755
index 6107537..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/ReferenceMultiplier.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-
-class ReferenceMultiplier implements ECMultiplier
-{
- /**
- * Simple shift-and-add multiplication. Serves as reference implementation
- * to verify (possibly faster) implementations in
- * {@link org.bouncycastle.math.ec.ECPoint ECPoint}.
- *
- * @param p The point to multiply.
- * @param k The factor by which to multiply.
- * @return The result of the point multiplication k * p.
- */
- public ECPoint multiply(ECPoint p, BigIntegerCrypto k, PreCompInfo preCompInfo)
- {
- ECPoint q = p.getCurve().getInfinity();
- int t = k.bitLength();
- for (int i = 0; i < t; i++)
- {
- if (k.testBit(i))
- {
- q = q.add(p);
- }
- p = p.twice();
- }
- return q;
- }
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/SimpleBigDecimal.java b/src/org/bouncycastle/mathzrtp/ec/SimpleBigDecimal.java
deleted file mode 100755
index 7678818..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/SimpleBigDecimal.java
+++ /dev/null
@@ -1,253 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-
-/**
- * Class representing a simple version of a big decimal. A
- * SimpleBigDecimal is basically a
- * {@link java.math.BigInteger BigInteger} with a few digits on the right of
- * the decimal point. The number of (binary) digits on the right of the decimal
- * point is called the scale of the SimpleBigDecimal.
- * Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted
- * automatically, but must be set manually. All SimpleBigDecimals
- * taking part in the same arithmetic operation must have equal scale. The
- * result of a multiplication of two SimpleBigDecimals returns a
- * SimpleBigDecimal with double scale.
- */
-class SimpleBigDecimal
- //extends Number // not in J2ME - add compatibility class?
-{
- private static final long serialVersionUID = 1L;
-
- private final BigIntegerCrypto bigInt;
- private final int scale;
-
- /**
- * Returns a SimpleBigDecimal representing the same numerical
- * value as value.
- * @param value The value of the SimpleBigDecimal to be
- * created.
- * @param scale The scale of the SimpleBigDecimal to be
- * created.
- * @return The such created SimpleBigDecimal.
- */
- public static SimpleBigDecimal getInstance(BigIntegerCrypto value, int scale)
- {
- return new SimpleBigDecimal(value.shiftLeft(scale), scale);
- }
-
- /**
- * Constructor for SimpleBigDecimal. The value of the
- * constructed SimpleBigDecimal equals bigInt /
- * 2scale.
- * @param bigInt The bigInt value parameter.
- * @param scale The scale of the constructed SimpleBigDecimal.
- */
- public SimpleBigDecimal(BigIntegerCrypto bigInt, int scale)
- {
- if (scale < 0)
- {
- throw new IllegalArgumentException("scale may not be negative");
- }
-
- this.bigInt = bigInt;
- this.scale = scale;
- }
-
- private SimpleBigDecimal(SimpleBigDecimal limBigDec)
- {
- bigInt = limBigDec.bigInt;
- scale = limBigDec.scale;
- }
-
- private void checkScale(SimpleBigDecimal b)
- {
- if (scale != b.scale)
- {
- throw new IllegalArgumentException("Only SimpleBigDecimal of " +
- "same scale allowed in arithmetic operations");
- }
- }
-
- public SimpleBigDecimal adjustScale(int newScale)
- {
- if (newScale < 0)
- {
- throw new IllegalArgumentException("scale may not be negative");
- }
-
- if (newScale == scale)
- {
- return new SimpleBigDecimal(this);
- }
-
- return new SimpleBigDecimal(bigInt.shiftLeft(newScale - scale),
- newScale);
- }
-
- public SimpleBigDecimal add(SimpleBigDecimal b)
- {
- checkScale(b);
- return new SimpleBigDecimal(bigInt.add(b.bigInt), scale);
- }
-
- public SimpleBigDecimal add(BigIntegerCrypto b)
- {
- return new SimpleBigDecimal(bigInt.add(b.shiftLeft(scale)), scale);
- }
-
- public SimpleBigDecimal negate()
- {
- return new SimpleBigDecimal(bigInt.negate(), scale);
- }
-
- public SimpleBigDecimal subtract(SimpleBigDecimal b)
- {
- return add(b.negate());
- }
-
- public SimpleBigDecimal subtract(BigIntegerCrypto b)
- {
- return new SimpleBigDecimal(bigInt.subtract(b.shiftLeft(scale)),
- scale);
- }
-
- public SimpleBigDecimal multiply(SimpleBigDecimal b)
- {
- checkScale(b);
- return new SimpleBigDecimal(bigInt.multiply(b.bigInt), scale + scale);
- }
-
- public SimpleBigDecimal multiply(BigIntegerCrypto b)
- {
- return new SimpleBigDecimal(bigInt.multiply(b), scale);
- }
-
- public SimpleBigDecimal divide(SimpleBigDecimal b)
- {
- checkScale(b);
- BigIntegerCrypto dividend = bigInt.shiftLeft(scale);
- return new SimpleBigDecimal(dividend.divide(b.bigInt), scale);
- }
-
- public SimpleBigDecimal divide(BigIntegerCrypto b)
- {
- return new SimpleBigDecimal(bigInt.divide(b), scale);
- }
-
- public SimpleBigDecimal shiftLeft(int n)
- {
- return new SimpleBigDecimal(bigInt.shiftLeft(n), scale);
- }
-
- public int compareTo(SimpleBigDecimal val)
- {
- checkScale(val);
- return bigInt.compareTo(val.bigInt);
- }
-
- public int compareTo(BigIntegerCrypto val)
- {
- return bigInt.compareTo(val.shiftLeft(scale));
- }
-
- public BigIntegerCrypto floor()
- {
- return bigInt.shiftRight(scale);
- }
-
- public BigIntegerCrypto round()
- {
- SimpleBigDecimal oneHalf = new SimpleBigDecimal(ECConstants.ONE, 1);
- return add(oneHalf.adjustScale(scale)).floor();
- }
-
- public int intValue()
- {
- return floor().intValue();
- }
-
- public long longValue()
- {
- return floor().longValue();
- }
- /* NON-J2ME compliant.
- public double doubleValue()
- {
- return Double.valueOf(toString()).doubleValue();
- }
-
- public float floatValue()
- {
- return Float.valueOf(toString()).floatValue();
- }
- */
- public int getScale()
- {
- return scale;
- }
-
- public String toString()
- {
- if (scale == 0)
- {
- return bigInt.toString();
- }
-
- BigIntegerCrypto floorBigInt = floor();
-
- BigIntegerCrypto fract = bigInt.subtract(floorBigInt.shiftLeft(scale));
- if (bigInt.signum() == -1)
- {
- fract = ECConstants.ONE.shiftLeft(scale).subtract(fract);
- }
-
- if ((floorBigInt.signum() == -1) && (!(fract.equals(ECConstants.ZERO))))
- {
- floorBigInt = floorBigInt.add(ECConstants.ONE);
- }
- String leftOfPoint = floorBigInt.toString();
-
- char[] fractCharArr = new char[scale];
- String fractStr = fract.toString(2);
- int fractLen = fractStr.length();
- int zeroes = scale - fractLen;
- for (int i = 0; i < zeroes; i++)
- {
- fractCharArr[i] = '0';
- }
- for (int j = 0; j < fractLen; j++)
- {
- fractCharArr[zeroes + j] = fractStr.charAt(j);
- }
- String rightOfPoint = new String(fractCharArr);
-
- StringBuffer sb = new StringBuffer(leftOfPoint);
- sb.append(".");
- sb.append(rightOfPoint);
-
- return sb.toString();
- }
-
- public boolean equals(Object o)
- {
- if (this == o)
- {
- return true;
- }
-
- if (!(o instanceof SimpleBigDecimal))
- {
- return false;
- }
-
- SimpleBigDecimal other = (SimpleBigDecimal)o;
- return ((bigInt.equals(other.bigInt)) && (scale == other.scale));
- }
-
- public int hashCode()
- {
- return bigInt.hashCode() ^ scale;
- }
-
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/Tnaf.java b/src/org/bouncycastle/mathzrtp/ec/Tnaf.java
deleted file mode 100755
index f7479c3..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/Tnaf.java
+++ /dev/null
@@ -1,844 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-
-/**
- * Class holding methods for point multiplication based on the window
- * τ-adic nonadjacent form (WTNAF). The algorithms are based on the
- * paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves"
- * by Jerome A. Solinas. The paper first appeared in the Proceedings of
- * Crypto 1997.
- */
-class Tnaf
-{
- private static final BigIntegerCrypto MINUS_ONE = ECConstants.ONE.negate();
- private static final BigIntegerCrypto MINUS_TWO = ECConstants.TWO.negate();
- private static final BigIntegerCrypto MINUS_THREE = ECConstants.THREE.negate();
-
- /**
- * The window width of WTNAF. The standard value of 4 is slightly less
- * than optimal for running time, but keeps space requirements for
- * precomputation low. For typical curves, a value of 5 or 6 results in
- * a better running time. When changing this value, the
- * αu's must be computed differently, see
- * e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson,
- * Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004,
- * p. 121-122
- */
- public static final byte WIDTH = 4;
-
- /**
- * 24
- */
- public static final byte POW_2_WIDTH = 16;
-
- /**
- * The αu's for a=0 as an array
- * of ZTauElements.
- */
- public static final ZTauElement[] alpha0 = {
- null,
- new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
- new ZTauElement(MINUS_THREE, MINUS_ONE), null,
- new ZTauElement(MINUS_ONE, MINUS_ONE), null,
- new ZTauElement(ECConstants.ONE, MINUS_ONE), null
- };
-
- /**
- * The αu's for a=0 as an array
- * of TNAFs.
- */
- public static final byte[][] alpha0Tnaf = {
- null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, 1}
- };
-
- /**
- * The αu's for a=1 as an array
- * of ZTauElements.
- */
- public static final ZTauElement[] alpha1 = {null,
- new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
- new ZTauElement(MINUS_THREE, ECConstants.ONE), null,
- new ZTauElement(MINUS_ONE, ECConstants.ONE), null,
- new ZTauElement(ECConstants.ONE, ECConstants.ONE), null
- };
-
- /**
- * The αu's for a=1 as an array
- * of TNAFs.
- */
- public static final byte[][] alpha1Tnaf = {
- null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, -1}
- };
-
- /**
- * Computes the norm of an element λ of
- * Z[τ].
- * @param mu The parameter μ of the elliptic curve.
- * @param lambda The element λ of
- * Z[τ].
- * @return The norm of λ.
- */
- public static BigIntegerCrypto norm(final byte mu, ZTauElement lambda)
- {
- BigIntegerCrypto norm;
-
- // s1 = u^2
- BigIntegerCrypto s1 = lambda.u.multiply(lambda.u);
-
- // s2 = u * v
- BigIntegerCrypto s2 = lambda.u.multiply(lambda.v);
-
- // s3 = 2 * v^2
- BigIntegerCrypto s3 = lambda.v.multiply(lambda.v).shiftLeft(1);
-
- if (mu == 1)
- {
- norm = s1.add(s2).add(s3);
- }
- else if (mu == -1)
- {
- norm = s1.subtract(s2).add(s3);
- }
- else
- {
- throw new IllegalArgumentException("mu must be 1 or -1");
- }
-
- return norm;
- }
-
- /**
- * Computes the norm of an element λ of
- * R[τ], where λ = u + vτ
- * and u and u are real numbers (elements of
- * R).
- * @param mu The parameter μ of the elliptic curve.
- * @param u The real part of the element λ of
- * R[τ].
- * @param v The τ-adic part of the element
- * λ of R[τ].
- * @return The norm of λ.
- */
- public static SimpleBigDecimal norm(final byte mu, SimpleBigDecimal u,
- SimpleBigDecimal v)
- {
- SimpleBigDecimal norm;
-
- // s1 = u^2
- SimpleBigDecimal s1 = u.multiply(u);
-
- // s2 = u * v
- SimpleBigDecimal s2 = u.multiply(v);
-
- // s3 = 2 * v^2
- SimpleBigDecimal s3 = v.multiply(v).shiftLeft(1);
-
- if (mu == 1)
- {
- norm = s1.add(s2).add(s3);
- }
- else if (mu == -1)
- {
- norm = s1.subtract(s2).add(s3);
- }
- else
- {
- throw new IllegalArgumentException("mu must be 1 or -1");
- }
-
- return norm;
- }
-
- /**
- * Rounds an element λ of R[τ]
- * to an element of Z[τ], such that their difference
- * has minimal norm. λ is given as
- * λ = λ0 + λ1τ.
- * @param lambda0 The component λ0.
- * @param lambda1 The component λ1.
- * @param mu The parameter μ of the elliptic curve. Must
- * equal 1 or -1.
- * @return The rounded element of Z[τ].
- * @throws IllegalArgumentException if lambda0 and
- * lambda1 do not have same scale.
- */
- public static ZTauElement round(SimpleBigDecimal lambda0,
- SimpleBigDecimal lambda1, byte mu)
- {
- int scale = lambda0.getScale();
- if (lambda1.getScale() != scale)
- {
- throw new IllegalArgumentException("lambda0 and lambda1 do not " +
- "have same scale");
- }
-
- if (!((mu == 1) || (mu == -1)))
- {
- throw new IllegalArgumentException("mu must be 1 or -1");
- }
-
- BigIntegerCrypto f0 = lambda0.round();
- BigIntegerCrypto f1 = lambda1.round();
-
- SimpleBigDecimal eta0 = lambda0.subtract(f0);
- SimpleBigDecimal eta1 = lambda1.subtract(f1);
-
- // eta = 2*eta0 + mu*eta1
- SimpleBigDecimal eta = eta0.add(eta0);
- if (mu == 1)
- {
- eta = eta.add(eta1);
- }
- else
- {
- // mu == -1
- eta = eta.subtract(eta1);
- }
-
- // check1 = eta0 - 3*mu*eta1
- // check2 = eta0 + 4*mu*eta1
- SimpleBigDecimal threeEta1 = eta1.add(eta1).add(eta1);
- SimpleBigDecimal fourEta1 = threeEta1.add(eta1);
- SimpleBigDecimal check1;
- SimpleBigDecimal check2;
- if (mu == 1)
- {
- check1 = eta0.subtract(threeEta1);
- check2 = eta0.add(fourEta1);
- }
- else
- {
- // mu == -1
- check1 = eta0.add(threeEta1);
- check2 = eta0.subtract(fourEta1);
- }
-
- byte h0 = 0;
- byte h1 = 0;
-
- // if eta >= 1
- if (eta.compareTo(ECConstants.ONE) >= 0)
- {
- if (check1.compareTo(MINUS_ONE) < 0)
- {
- h1 = mu;
- }
- else
- {
- h0 = 1;
- }
- }
- else
- {
- // eta < 1
- if (check2.compareTo(ECConstants.TWO) >= 0)
- {
- h1 = mu;
- }
- }
-
- // if eta < -1
- if (eta.compareTo(MINUS_ONE) < 0)
- {
- if (check1.compareTo(ECConstants.ONE) >= 0)
- {
- h1 = (byte)-mu;
- }
- else
- {
- h0 = -1;
- }
- }
- else
- {
- // eta >= -1
- if (check2.compareTo(MINUS_TWO) < 0)
- {
- h1 = (byte)-mu;
- }
- }
-
- BigIntegerCrypto q0 = f0.add(BigIntegerCrypto.valueOf(h0));
- BigIntegerCrypto q1 = f1.add(BigIntegerCrypto.valueOf(h1));
- return new ZTauElement(q0, q1);
- }
-
- /**
- * Approximate division by n. For an integer
- * k, the value λ = s k / n is
- * computed to c bits of accuracy.
- * @param k The parameter k.
- * @param s The curve parameter s0 or
- * s1.
- * @param vm The Lucas Sequence element Vm.
- * @param a The parameter a of the elliptic curve.
- * @param m The bit length of the finite field
- * Fm.
- * @param c The number of bits of accuracy, i.e. the scale of the returned
- * SimpleBigDecimal.
- * @return The value λ = s k / n computed to
- * c bits of accuracy.
- */
- public static SimpleBigDecimal approximateDivisionByN(BigIntegerCrypto k,
- BigIntegerCrypto s, BigIntegerCrypto vm, byte a, int m, int c)
- {
- int _k = (m + 5)/2 + c;
- BigIntegerCrypto ns = k.shiftRight(m - _k - 2 + a);
-
- BigIntegerCrypto gs = s.multiply(ns);
-
- BigIntegerCrypto hs = gs.shiftRight(m);
-
- BigIntegerCrypto js = vm.multiply(hs);
-
- BigIntegerCrypto gsPlusJs = gs.add(js);
- BigIntegerCrypto ls = gsPlusJs.shiftRight(_k-c);
- if (gsPlusJs.testBit(_k-c-1))
- {
- // round up
- ls = ls.add(ECConstants.ONE);
- }
-
- return new SimpleBigDecimal(ls, c);
- }
-
- /**
- * Computes the τ-adic NAF (non-adjacent form) of an
- * element λ of Z[τ].
- * @param mu The parameter μ of the elliptic curve.
- * @param lambda The element λ of
- * Z[τ].
- * @return The τ-adic NAF of λ.
- */
- public static byte[] tauAdicNaf(byte mu, ZTauElement lambda)
- {
- if (!((mu == 1) || (mu == -1)))
- {
- throw new IllegalArgumentException("mu must be 1 or -1");
- }
-
- BigIntegerCrypto norm = norm(mu, lambda);
-
- // Ceiling of log2 of the norm
- int log2Norm = norm.bitLength();
-
- // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
- int maxLength = log2Norm > 30 ? log2Norm + 4 : 34;
-
- // The array holding the TNAF
- byte[] u = new byte[maxLength];
- int i = 0;
-
- // The actual length of the TNAF
- int length = 0;
-
- BigIntegerCrypto r0 = lambda.u;
- BigIntegerCrypto r1 = lambda.v;
-
- while(!((r0.equals(ECConstants.ZERO)) && (r1.equals(ECConstants.ZERO))))
- {
- // If r0 is odd
- if (r0.testBit(0))
- {
- u[i] = (byte) ECConstants.TWO.subtract((r0.subtract(r1.shiftLeft(1))).mod(ECConstants.FOUR)).intValue();
-
- // r0 = r0 - u[i]
- if (u[i] == 1)
- {
- r0 = r0.clearBit(0);
- }
- else
- {
- // u[i] == -1
- r0 = r0.add(ECConstants.ONE);
- }
- length = i;
- }
- else
- {
- u[i] = 0;
- }
-
- BigIntegerCrypto t = r0;
- BigIntegerCrypto s = r0.shiftRight(1);
- if (mu == 1)
- {
- r0 = r1.add(s);
- }
- else
- {
- // mu == -1
- r0 = r1.subtract(s);
- }
-
- r1 = t.shiftRight(1).negate();
- i++;
- }
-
- length++;
-
- // Reduce the TNAF array to its actual length
- byte[] tnaf = new byte[length];
- System.arraycopy(u, 0, tnaf, 0, length);
- return tnaf;
- }
-
- /**
- * Applies the operation τ() to an
- * ECPoint.F2m.
- * @param p The ECPoint.F2m to which τ() is applied.
- * @return τ(p)
- */
- public static ECPoint.F2m tau(ECPoint.F2m p)
- {
- if (p.isInfinity())
- {
- return p;
- }
-
- ECFieldElement x = p.getX();
- ECFieldElement y = p.getY();
-
- return new ECPoint.F2m(p.getCurve(), x.square(), y.square(), p.isCompressed());
- }
-
- /**
- * Returns the parameter μ of the elliptic curve.
- * @param curve The elliptic curve from which to obtain μ.
- * The curve must be a Koblitz curve, i.e. a equals
- * 0 or 1 and b equals
- * 1.
- * @return μ of the elliptic curve.
- * @throws IllegalArgumentException if the given ECCurve is not a Koblitz
- * curve.
- */
- public static byte getMu(ECCurve.F2m curve)
- {
- BigIntegerCrypto a = curve.getA().toBigInteger();
- byte mu;
-
- if (a.equals(ECConstants.ZERO))
- {
- mu = -1;
- }
- else if (a.equals(ECConstants.ONE))
- {
- mu = 1;
- }
- else
- {
- throw new IllegalArgumentException("No Koblitz curve (ABC), " +
- "TNAF multiplication not possible");
- }
- return mu;
- }
-
- /**
- * Calculates the Lucas Sequence elements Uk-1 and
- * Uk or Vk-1 and
- * Vk.
- * @param mu The parameter μ of the elliptic curve.
- * @param k The index of the second element of the Lucas Sequence to be
- * returned.
- * @param doV If set to true, computes Vk-1 and
- * Vk, otherwise Uk-1 and
- * Uk.
- * @return An array with 2 elements, containing Uk-1
- * and Uk or Vk-1
- * and Vk.
- */
- public static BigIntegerCrypto[] getLucas(byte mu, int k, boolean doV)
- {
- if (!((mu == 1) || (mu == -1)))
- {
- throw new IllegalArgumentException("mu must be 1 or -1");
- }
-
- BigIntegerCrypto u0;
- BigIntegerCrypto u1;
- BigIntegerCrypto u2;
-
- if (doV)
- {
- u0 = ECConstants.TWO;
- u1 = BigIntegerCrypto.valueOf(mu);
- }
- else
- {
- u0 = ECConstants.ZERO;
- u1 = ECConstants.ONE;
- }
-
- for (int i = 1; i < k; i++)
- {
- // u2 = mu*u1 - 2*u0;
- BigIntegerCrypto s = null;
- if (mu == 1)
- {
- s = u1;
- }
- else
- {
- // mu == -1
- s = u1.negate();
- }
-
- u2 = s.subtract(u0.shiftLeft(1));
- u0 = u1;
- u1 = u2;
-// System.out.println(i + ": " + u2);
-// System.out.println();
- }
-
- BigIntegerCrypto[] retVal = {u0, u1};
- return retVal;
- }
-
- /**
- * Computes the auxiliary value tw. If the width is
- * 4, then for mu = 1, tw = 6 and for
- * mu = -1, tw = 10
- * @param mu The parameter μ of the elliptic curve.
- * @param w The window width of the WTNAF.
- * @return the auxiliary value tw
- */
- public static BigIntegerCrypto getTw(byte mu, int w)
- {
- if (w == 4)
- {
- if (mu == 1)
- {
- return BigIntegerCrypto.valueOf(6);
- }
- else
- {
- // mu == -1
- return BigIntegerCrypto.valueOf(10);
- }
- }
- else
- {
- // For w <> 4, the values must be computed
- BigIntegerCrypto[] us = getLucas(mu, w, false);
- BigIntegerCrypto twoToW = ECConstants.ZERO.setBit(w);
- BigIntegerCrypto u1invert = us[1].modInverse(twoToW);
- BigIntegerCrypto tw;
- tw = ECConstants.TWO.multiply(us[0]).multiply(u1invert).mod(twoToW);
-// System.out.println("mu = " + mu);
-// System.out.println("tw = " + tw);
- return tw;
- }
- }
-
- /**
- * Computes the auxiliary values s0 and
- * s1 used for partial modular reduction.
- * @param curve The elliptic curve for which to compute
- * s0 and s1.
- * @throws IllegalArgumentException if curve is not a
- * Koblitz curve (Anomalous Binary Curve, ABC).
- */
- public static BigIntegerCrypto[] getSi(ECCurve.F2m curve)
- {
- if (!curve.isKoblitz())
- {
- throw new IllegalArgumentException("si is defined for Koblitz curves only");
- }
-
- int m = curve.getM();
- int a = curve.getA().toBigInteger().intValue();
- byte mu = curve.getMu();
- int h = curve.getH().intValue();
- int index = m + 3 - a;
- BigIntegerCrypto[] ui = getLucas(mu, index, false);
-
- BigIntegerCrypto dividend0;
- BigIntegerCrypto dividend1;
- if (mu == 1)
- {
- dividend0 = ECConstants.ONE.subtract(ui[1]);
- dividend1 = ECConstants.ONE.subtract(ui[0]);
- }
- else if (mu == -1)
- {
- dividend0 = ECConstants.ONE.add(ui[1]);
- dividend1 = ECConstants.ONE.add(ui[0]);
- }
- else
- {
- throw new IllegalArgumentException("mu must be 1 or -1");
- }
-
- BigIntegerCrypto[] si = new BigIntegerCrypto[2];
-
- if (h == 2)
- {
- si[0] = dividend0.shiftRight(1);
- si[1] = dividend1.shiftRight(1).negate();
- }
- else if (h == 4)
- {
- si[0] = dividend0.shiftRight(2);
- si[1] = dividend1.shiftRight(2).negate();
- }
- else
- {
- throw new IllegalArgumentException("h (Cofactor) must be 2 or 4");
- }
-
- return si;
- }
-
- /**
- * Partial modular reduction modulo
- * (τm - 1)/(τ - 1).
- * @param k The integer to be reduced.
- * @param m The bitlength of the underlying finite field.
- * @param a The parameter a of the elliptic curve.
- * @param s The auxiliary values s0 and
- * s1.
- * @param mu The parameter μ of the elliptic curve.
- * @param c The precision (number of bits of accuracy) of the partial
- * modular reduction.
- * @return ρ := k partmod (τm - 1)/(τ - 1)
- */
- public static ZTauElement partModReduction(BigIntegerCrypto k, int m, byte a,
- BigIntegerCrypto[] s, byte mu, byte c)
- {
- // d0 = s[0] + mu*s[1]; mu is either 1 or -1
- BigIntegerCrypto d0;
- if (mu == 1)
- {
- d0 = s[0].add(s[1]);
- }
- else
- {
- d0 = s[0].subtract(s[1]);
- }
-
- BigIntegerCrypto[] v = getLucas(mu, m, true);
- BigIntegerCrypto vm = v[1];
-
- SimpleBigDecimal lambda0 = approximateDivisionByN(
- k, s[0], vm, a, m, c);
-
- SimpleBigDecimal lambda1 = approximateDivisionByN(
- k, s[1], vm, a, m, c);
-
- ZTauElement q = round(lambda0, lambda1, mu);
-
- // r0 = n - d0*q0 - 2*s1*q1
- BigIntegerCrypto r0 = k.subtract(d0.multiply(q.u)).subtract(
- BigIntegerCrypto.valueOf(2).multiply(s[1]).multiply(q.v));
-
- // r1 = s1*q0 - s0*q1
- BigIntegerCrypto r1 = s[1].multiply(q.u).subtract(s[0].multiply(q.v));
-
- return new ZTauElement(r0, r1);
- }
-
- /**
- * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
- * by a BigInteger using the reduced τ-adic
- * NAF (RTNAF) method.
- * @param p The ECPoint.F2m to multiply.
- * @param k The BigInteger by which to multiply p.
- * @return k * p
- */
- public static ECPoint.F2m multiplyRTnaf(ECPoint.F2m p, BigIntegerCrypto k)
- {
- ECCurve.F2m curve = (ECCurve.F2m) p.getCurve();
- int m = curve.getM();
- byte a = (byte) curve.getA().toBigInteger().intValue();
- byte mu = curve.getMu();
- BigIntegerCrypto[] s = curve.getSi();
- ZTauElement rho = partModReduction(k, m, a, s, mu, (byte)10);
-
- return multiplyTnaf(p, rho);
- }
-
- /**
- * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
- * by an element λ of Z[τ]
- * using the τ-adic NAF (TNAF) method.
- * @param p The ECPoint.F2m to multiply.
- * @param lambda The element λ of
- * Z[τ].
- * @return λ * p
- */
- public static ECPoint.F2m multiplyTnaf(ECPoint.F2m p, ZTauElement lambda)
- {
- ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
- byte mu = curve.getMu();
- byte[] u = tauAdicNaf(mu, lambda);
-
- ECPoint.F2m q = multiplyFromTnaf(p, u);
-
- return q;
- }
-
- /**
- * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
- * by an element λ of Z[τ]
- * using the τ-adic NAF (TNAF) method, given the TNAF
- * of λ.
- * @param p The ECPoint.F2m to multiply.
- * @param u The the TNAF of λ..
- * @return λ * p
- */
- public static ECPoint.F2m multiplyFromTnaf(ECPoint.F2m p, byte[] u)
- {
- ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
- ECPoint.F2m q = (ECPoint.F2m) curve.getInfinity();
- for (int i = u.length - 1; i >= 0; i--)
- {
- q = tau(q);
- if (u[i] == 1)
- {
- q = q.addSimple(p);
- }
- else if (u[i] == -1)
- {
- q = q.subtractSimple(p);
- }
- }
- return q;
- }
-
- /**
- * Computes the [τ]-adic window NAF of an element
- * λ of Z[τ].
- * @param mu The parameter μ of the elliptic curve.
- * @param lambda The element λ of
- * Z[τ] of which to compute the
- * [τ]-adic NAF.
- * @param width The window width of the resulting WNAF.
- * @param pow2w 2width.
- * @param tw The auxiliary value tw.
- * @param alpha The αu's for the window width.
- * @return The [τ]-adic window NAF of
- * λ.
- */
- public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda,
- byte width, BigIntegerCrypto pow2w, BigIntegerCrypto tw, ZTauElement[] alpha)
- {
- if (!((mu == 1) || (mu == -1)))
- {
- throw new IllegalArgumentException("mu must be 1 or -1");
- }
-
- BigIntegerCrypto norm = norm(mu, lambda);
-
- // Ceiling of log2 of the norm
- int log2Norm = norm.bitLength();
-
- // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
- int maxLength = log2Norm > 30 ? log2Norm + 4 + width : 34 + width;
-
- // The array holding the TNAF
- byte[] u = new byte[maxLength];
-
- // 2^(width - 1)
- BigIntegerCrypto pow2wMin1 = pow2w.shiftRight(1);
-
- // Split lambda into two BigIntegers to simplify calculations
- BigIntegerCrypto r0 = lambda.u;
- BigIntegerCrypto r1 = lambda.v;
- int i = 0;
-
- // while lambda <> (0, 0)
- while (!((r0.equals(ECConstants.ZERO))&&(r1.equals(ECConstants.ZERO))))
- {
- // if r0 is odd
- if (r0.testBit(0))
- {
- // uUnMod = r0 + r1*tw mod 2^width
- BigIntegerCrypto uUnMod
- = r0.add(r1.multiply(tw)).mod(pow2w);
-
- byte uLocal;
- // if uUnMod >= 2^(width - 1)
- if (uUnMod.compareTo(pow2wMin1) >= 0)
- {
- uLocal = (byte) uUnMod.subtract(pow2w).intValue();
- }
- else
- {
- uLocal = (byte) uUnMod.intValue();
- }
- // uLocal is now in [-2^(width-1), 2^(width-1)-1]
-
- u[i] = uLocal;
- boolean s = true;
- if (uLocal < 0)
- {
- s = false;
- uLocal = (byte)-uLocal;
- }
- // uLocal is now >= 0
-
- if (s)
- {
- r0 = r0.subtract(alpha[uLocal].u);
- r1 = r1.subtract(alpha[uLocal].v);
- }
- else
- {
- r0 = r0.add(alpha[uLocal].u);
- r1 = r1.add(alpha[uLocal].v);
- }
- }
- else
- {
- u[i] = 0;
- }
-
- BigIntegerCrypto t = r0;
-
- if (mu == 1)
- {
- r0 = r1.add(r0.shiftRight(1));
- }
- else
- {
- // mu == -1
- r0 = r1.subtract(r0.shiftRight(1));
- }
- r1 = t.shiftRight(1).negate();
- i++;
- }
- return u;
- }
-
- /**
- * Does the precomputation for WTNAF multiplication.
- * @param p The ECPoint for which to do the precomputation.
- * @param a The parameter a of the elliptic curve.
- * @return The precomputation array for p.
- */
- public static ECPoint.F2m[] getPreComp(ECPoint.F2m p, byte a)
- {
- ECPoint.F2m[] pu;
- pu = new ECPoint.F2m[16];
- pu[1] = p;
- byte[][] alphaTnaf;
- if (a == 0)
- {
- alphaTnaf = Tnaf.alpha0Tnaf;
- }
- else
- {
- // a == 1
- alphaTnaf = Tnaf.alpha1Tnaf;
- }
-
- int precompLen = alphaTnaf.length;
- for (int i = 3; i < precompLen; i = i + 2)
- {
- pu[i] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]);
- }
-
- return pu;
- }
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/WNafMultiplier.java b/src/org/bouncycastle/mathzrtp/ec/WNafMultiplier.java
deleted file mode 100755
index a019bf6..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/WNafMultiplier.java
+++ /dev/null
@@ -1,240 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-
-/**
- * Class implementing the WNAF (Window Non-Adjacent Form) multiplication
- * algorithm.
- */
-class WNafMultiplier implements ECMultiplier
-{
- /**
- * Computes the Window NAF (non-adjacent Form) of an integer.
- * @param width The width w of the Window NAF. The width is
- * defined as the minimal number w, such that for any
- * w consecutive digits in the resulting representation, at
- * most one is non-zero.
- * @param k The integer of which the Window NAF is computed.
- * @return The Window NAF of the given width, such that the following holds:
- * k = ∑i=0l-1 ki2i
- * , where the ki denote the elements of the
- * returned byte[].
- */
- public byte[] windowNaf(byte width, BigIntegerCrypto k)
- {
- // The window NAF is at most 1 element longer than the binary
- // representation of the integer k. byte can be used instead of short or
- // int unless the window width is larger than 8. For larger width use
- // short or int. However, a width of more than 8 is not efficient for
- // m = log2(q) smaller than 2305 Bits. Note: Values for m larger than
- // 1000 Bits are currently not used in practice.
- byte[] wnaf = new byte[k.bitLength() + 1];
-
- // 2^width as short and BigInteger
- short pow2wB = (short)(1 << width);
- BigIntegerCrypto pow2wBI = BigIntegerCrypto.valueOf(pow2wB);
-
- int i = 0;
-
- // The actual length of the WNAF
- int length = 0;
-
- // while k >= 1
- while (k.signum() > 0)
- {
- // if k is odd
- if (k.testBit(0))
- {
- // k mod 2^width
- BigIntegerCrypto remainder = k.mod(pow2wBI);
-
- // if remainder > 2^(width - 1) - 1
- if (remainder.testBit(width - 1))
- {
- wnaf[i] = (byte)(remainder.intValue() - pow2wB);
- }
- else
- {
- wnaf[i] = (byte)remainder.intValue();
- }
- // wnaf[i] is now in [-2^(width-1), 2^(width-1)-1]
-
- k = k.subtract(BigIntegerCrypto.valueOf(wnaf[i]));
- length = i;
- }
- else
- {
- wnaf[i] = 0;
- }
-
- // k = k/2
- k = k.shiftRight(1);
- i++;
- }
-
- length++;
-
- // Reduce the WNAF array to its actual length
- byte[] wnafShort = new byte[length];
- System.arraycopy(wnaf, 0, wnafShort, 0, length);
- return wnafShort;
- }
-
- /**
- * Multiplies this by an integer k using the
- * Window NAF method.
- * @param k The integer by which this is multiplied.
- * @return A new ECPoint which equals this
- * multiplied by k.
- */
- public ECPoint multiply(ECPoint p, BigIntegerCrypto k, PreCompInfo preCompInfo)
- {
- WNafPreCompInfo wnafPreCompInfo;
-
- if ((preCompInfo != null) && (preCompInfo instanceof WNafPreCompInfo))
- {
- wnafPreCompInfo = (WNafPreCompInfo)preCompInfo;
- }
- else
- {
- // Ignore empty PreCompInfo or PreCompInfo of incorrect type
- wnafPreCompInfo = new WNafPreCompInfo();
- }
-
- // floor(log2(k))
- int m = k.bitLength();
-
- // width of the Window NAF
- byte width;
-
- // Required length of precomputation array
- int reqPreCompLen;
-
- // Determine optimal width and corresponding length of precomputation
- // array based on literature values
- if (m < 13)
- {
- width = 2;
- reqPreCompLen = 1;
- }
- else
- {
- if (m < 41)
- {
- width = 3;
- reqPreCompLen = 2;
- }
- else
- {
- if (m < 121)
- {
- width = 4;
- reqPreCompLen = 4;
- }
- else
- {
- if (m < 337)
- {
- width = 5;
- reqPreCompLen = 8;
- }
- else
- {
- if (m < 897)
- {
- width = 6;
- reqPreCompLen = 16;
- }
- else
- {
- if (m < 2305)
- {
- width = 7;
- reqPreCompLen = 32;
- }
- else
- {
- width = 8;
- reqPreCompLen = 127;
- }
- }
- }
- }
- }
- }
-
- // The length of the precomputation array
- int preCompLen = 1;
-
- ECPoint[] preComp = wnafPreCompInfo.getPreComp();
- ECPoint twiceP = wnafPreCompInfo.getTwiceP();
-
- // Check if the precomputed ECPoints already exist
- if (preComp == null)
- {
- // Precomputation must be performed from scratch, create an empty
- // precomputation array of desired length
- preComp = new ECPoint[]{ p };
- }
- else
- {
- // Take the already precomputed ECPoints to start with
- preCompLen = preComp.length;
- }
-
- if (twiceP == null)
- {
- // Compute twice(p)
- twiceP = p.twice();
- }
-
- if (preCompLen < reqPreCompLen)
- {
- // Precomputation array must be made bigger, copy existing preComp
- // array into the larger new preComp array
- ECPoint[] oldPreComp = preComp;
- preComp = new ECPoint[reqPreCompLen];
- System.arraycopy(oldPreComp, 0, preComp, 0, preCompLen);
-
- for (int i = preCompLen; i < reqPreCompLen; i++)
- {
- // Compute the new ECPoints for the precomputation array.
- // The values 1, 3, 5, ..., 2^(width-1)-1 times p are
- // computed
- preComp[i] = twiceP.add(preComp[i - 1]);
- }
- }
-
- // Compute the Window NAF of the desired width
- byte[] wnaf = windowNaf(width, k);
- int l = wnaf.length;
-
- // Apply the Window NAF to p using the precomputed ECPoint values.
- ECPoint q = p.getCurve().getInfinity();
- for (int i = l - 1; i >= 0; i--)
- {
- q = q.twice();
-
- if (wnaf[i] != 0)
- {
- if (wnaf[i] > 0)
- {
- q = q.add(preComp[(wnaf[i] - 1)/2]);
- }
- else
- {
- // wnaf[i] < 0
- q = q.subtract(preComp[(-wnaf[i] - 1)/2]);
- }
- }
- }
-
- // Set PreCompInfo in ECPoint, such that it is available for next
- // multiplication.
- wnafPreCompInfo.setPreComp(preComp);
- wnafPreCompInfo.setTwiceP(twiceP);
- p.setPreCompInfo(wnafPreCompInfo);
- return q;
- }
-
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/WNafPreCompInfo.java b/src/org/bouncycastle/mathzrtp/ec/WNafPreCompInfo.java
deleted file mode 100755
index 1c303cc..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/WNafPreCompInfo.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-/**
- * Class holding precomputation data for the WNAF (Window Non-Adjacent Form)
- * algorithm.
- */
-class WNafPreCompInfo implements PreCompInfo
-{
- /**
- * Array holding the precomputed ECPoints used for the Window
- * NAF multiplication in
- * {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply()
- * WNafMultiplier.multiply()}.
- */
- private ECPoint[] preComp = null;
-
- /**
- * Holds an ECPoint representing twice(this). Used for the
- * Window NAF multiplication in
- * {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply()
- * WNafMultiplier.multiply()}.
- */
- private ECPoint twiceP = null;
-
- protected ECPoint[] getPreComp()
- {
- return preComp;
- }
-
- protected void setPreComp(ECPoint[] preComp)
- {
- this.preComp = preComp;
- }
-
- protected ECPoint getTwiceP()
- {
- return twiceP;
- }
-
- protected void setTwiceP(ECPoint twiceThis)
- {
- this.twiceP = twiceThis;
- }
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/WTauNafMultiplier.java b/src/org/bouncycastle/mathzrtp/ec/WTauNafMultiplier.java
deleted file mode 100755
index e2d42e7..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/WTauNafMultiplier.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-
-/**
- * Class implementing the WTNAF (Window
- * τ-adic Non-Adjacent Form) algorithm.
- */
-class WTauNafMultiplier implements ECMultiplier
-{
- /**
- * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
- * by k using the reduced τ-adic NAF (RTNAF)
- * method.
- * @param p The ECPoint.F2m to multiply.
- * @param k The integer by which to multiply k.
- * @return p multiplied by k.
- */
- public ECPoint multiply(ECPoint point, BigIntegerCrypto k, PreCompInfo preCompInfo)
- {
- if (!(point instanceof ECPoint.F2m))
- {
- throw new IllegalArgumentException("Only ECPoint.F2m can be " +
- "used in WTauNafMultiplier");
- }
-
- ECPoint.F2m p = (ECPoint.F2m)point;
-
- ECCurve.F2m curve = (ECCurve.F2m) p.getCurve();
- int m = curve.getM();
- byte a = curve.getA().toBigInteger().byteValue();
- byte mu = curve.getMu();
- BigIntegerCrypto[] s = curve.getSi();
-
- ZTauElement rho = Tnaf.partModReduction(k, m, a, s, mu, (byte)10);
-
- return multiplyWTnaf(p, rho, preCompInfo, a, mu);
- }
-
- /**
- * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
- * by an element λ of Z[τ] using
- * the τ-adic NAF (TNAF) method.
- * @param p The ECPoint.F2m to multiply.
- * @param lambda The element λ of
- * Z[τ] of which to compute the
- * [τ]-adic NAF.
- * @return p multiplied by λ.
- */
- private ECPoint.F2m multiplyWTnaf(ECPoint.F2m p, ZTauElement lambda,
- PreCompInfo preCompInfo, byte a, byte mu)
- {
- ZTauElement[] alpha;
- if (a == 0)
- {
- alpha = Tnaf.alpha0;
- }
- else
- {
- // a == 1
- alpha = Tnaf.alpha1;
- }
-
- BigIntegerCrypto tw = Tnaf.getTw(mu, Tnaf.WIDTH);
-
- byte[]u = Tnaf.tauAdicWNaf(mu, lambda, Tnaf.WIDTH,
- BigIntegerCrypto.valueOf(Tnaf.POW_2_WIDTH), tw, alpha);
-
- return multiplyFromWTnaf(p, u, preCompInfo);
- }
-
- /**
- * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
- * by an element λ of Z[τ]
- * using the window τ-adic NAF (TNAF) method, given the
- * WTNAF of λ.
- * @param p The ECPoint.F2m to multiply.
- * @param u The the WTNAF of λ..
- * @return λ * p
- */
- private static ECPoint.F2m multiplyFromWTnaf(ECPoint.F2m p, byte[] u,
- PreCompInfo preCompInfo)
- {
- ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
- byte a = curve.getA().toBigInteger().byteValue();
-
- ECPoint.F2m[] pu;
- if ((preCompInfo == null) || !(preCompInfo instanceof WTauNafPreCompInfo))
- {
- pu = Tnaf.getPreComp(p, a);
- p.setPreCompInfo(new WTauNafPreCompInfo(pu));
- }
- else
- {
- pu = ((WTauNafPreCompInfo)preCompInfo).getPreComp();
- }
-
- // q = infinity
- ECPoint.F2m q = (ECPoint.F2m) p.getCurve().getInfinity();
- for (int i = u.length - 1; i >= 0; i--)
- {
- q = Tnaf.tau(q);
- if (u[i] != 0)
- {
- if (u[i] > 0)
- {
- q = q.addSimple(pu[u[i]]);
- }
- else
- {
- // u[i] < 0
- q = q.subtractSimple(pu[-u[i]]);
- }
- }
- }
-
- return q;
- }
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/WTauNafPreCompInfo.java b/src/org/bouncycastle/mathzrtp/ec/WTauNafPreCompInfo.java
deleted file mode 100755
index 17d3b63..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/WTauNafPreCompInfo.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-/**
- * Class holding precomputation data for the WTNAF (Window
- * τ-adic Non-Adjacent Form) algorithm.
- */
-class WTauNafPreCompInfo implements PreCompInfo
-{
- /**
- * Array holding the precomputed ECPoint.F2ms used for the
- * WTNAF multiplication in
- * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
- * WTauNafMultiplier.multiply()}.
- */
- private ECPoint.F2m[] preComp = null;
-
- /**
- * Constructor for WTauNafPreCompInfo
- * @param preComp Array holding the precomputed ECPoint.F2ms
- * used for the WTNAF multiplication in
- * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
- * WTauNafMultiplier.multiply()}.
- */
- WTauNafPreCompInfo(ECPoint.F2m[] preComp)
- {
- this.preComp = preComp;
- }
-
- /**
- * @return the array holding the precomputed ECPoint.F2ms
- * used for the WTNAF multiplication in
- * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
- * WTauNafMultiplier.multiply()}.
- */
- protected ECPoint.F2m[] getPreComp()
- {
- return preComp;
- }
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/X9IntegerConverter.java b/src/org/bouncycastle/mathzrtp/ec/X9IntegerConverter.java
deleted file mode 100755
index 0f26d8a..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/X9IntegerConverter.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-import org.bouncycastle.mathzrtp.ec.ECCurve;
-import org.bouncycastle.mathzrtp.ec.ECFieldElement;
-
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-
-public class X9IntegerConverter
-{
- public int getByteLength(
- ECCurve c)
- {
- return (c.getFieldSize() + 7) / 8;
- }
-
- public int getByteLength(
- ECFieldElement fe)
- {
- return (fe.getFieldSize() + 7) / 8;
- }
-
- public byte[] integerToBytes(
- BigIntegerCrypto s,
- int qLength)
- {
- byte[] bytes = s.toByteArray();
-
- if (qLength < bytes.length)
- {
- byte[] tmp = new byte[qLength];
-
- System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length);
-
- return tmp;
- }
- else if (qLength > bytes.length)
- {
- byte[] tmp = new byte[qLength];
-
- System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length);
-
- return tmp;
- }
-
- return bytes;
- }
-}
diff --git a/src/org/bouncycastle/mathzrtp/ec/ZTauElement.java b/src/org/bouncycastle/mathzrtp/ec/ZTauElement.java
deleted file mode 100755
index 40ac910..0000000
--- a/src/org/bouncycastle/mathzrtp/ec/ZTauElement.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.bouncycastle.mathzrtp.ec;
-
-import gnu.java.bigintcrypto.BigIntegerCrypto;
-
-/**
- * Class representing an element of Z[τ]. Let
- * λ be an element of Z[τ]. Then
- * λ is given as λ = u + vτ. The
- * components u and v may be used directly, there
- * are no accessor methods.
- * Immutable class.
- */
-class ZTauElement
-{
- /**
- * The "real" part of λ.
- */
- public final BigIntegerCrypto u;
-
- /**
- * The "τ-adic" part of λ.
- */
- public final BigIntegerCrypto v;
-
- /**
- * Constructor for an element λ of
- * Z[τ].
- * @param u The "real" part of λ.
- * @param v The "τ-adic" part of
- * λ.
- */
- public ZTauElement(BigIntegerCrypto u, BigIntegerCrypto v)
- {
- this.u = u;
- this.v = v;
- }
-}