Esempio n. 1
0
    /**
     * 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 BigInteger(1, xEnc));
      ECFieldElement yp = null;
      if (xp.toBigInteger().equals(ECConstants.ZERO)) {
        yp = (ECFieldElement.F2m) 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);
    }
Esempio n. 2
0
    /**
     * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62 D.1.6) The other
     * solution is <code>z + 1</code>.
     *
     * @param beta The value to solve the qradratic equation for.
     * @return the solution for <code>z<sup>2</sup> + z = beta</code> or <code>null</code> 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 BigInteger(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;
    }
Esempio n. 3
0
    /**
     * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62 D.1.6) The other
     * solution is <code>z + 1</code>.
     *
     * @param beta The value to solve the quadratic equation for.
     * @return the solution for <code>z<sup>2</sup> + z = beta</code> or <code>null</code> if no
     *     solution exists.
     */
    private ECFieldElement solveQuadraticEquation(ECFieldElement beta) {
      if (beta.isZero()) {
        return beta;
      }

      ECFieldElement zeroElement = fromBigInteger(ECConstants.ZERO);

      ECFieldElement z = null;
      ECFieldElement gamma = null;

      Random rand = new Random();
      do {
        ECFieldElement t = fromBigInteger(new BigInteger(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.isZero()) {
          return null;
        }
        gamma = z.square().add(z);
      } while (gamma.isZero());

      return z;
    }
Esempio n. 4
0
    /**
     * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
     *
     * @param yTilde ~yp, an indication bit for the decompression of yp.
     * @param X1 The field element xp.
     * @return the decompressed point.
     */
    protected ECPoint decompressPoint(int yTilde, BigInteger X1) {
      ECFieldElement xp = fromBigInteger(X1);
      ECFieldElement yp = null;
      if (xp.isZero()) {
        yp = (ECFieldElement.F2m) 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 = solveQuadraticEquation(beta);
        if (z == null) {
          throw new IllegalArgumentException("Invalid point compression");
        }
        if (z.testBitZero() != (yTilde == 1)) {
          z = z.addOne();
        }

        yp = xp.multiply(z);

        switch (this.getCoordinateSystem()) {
          case COORD_LAMBDA_AFFINE:
          case COORD_LAMBDA_PROJECTIVE:
            {
              yp = yp.divide(xp).add(xp);
              break;
            }
          default:
            {
              break;
            }
        }
      }

      return new ECPoint.F2m(this, xp, yp, true);
    }
Esempio n. 5
0
    protected ECPoint decompressPoint(int yTilde, BigInteger X1) {
      ECFieldElement x = fromBigInteger(X1);
      ECFieldElement alpha = x.square().add(a).multiply(x).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");
      }

      if (beta.testBitZero() != (yTilde == 1)) {
        // Use the other root
        beta = beta.negate();
      }

      return new ECPoint.Fp(this, x, beta, true);
    }
Esempio n. 6
0
    /**
     * Decode a point on this curve from its ASN.1 encoding. The different encodings are taken
     * account of, including point compression for <code>F<sub>p</sub></code> (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 BigInteger(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 BigInteger(1, xEnc)),
                  new ECFieldElement.Fp(this.q, new BigInteger(1, yEnc)));
          break;
        default:
          throw new RuntimeException(
              "Invalid point encoding 0x" + Integer.toString(encoded[0], 16));
      }

      return p;
    }
Esempio n. 7
0
 private ECFieldElement checkSqrt(ECFieldElement z) {
   return z.square().equals(this) ? z : null;
 }
Esempio n. 8
0
    /**
     * 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");
      }

      // 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(ONE), q));

        return z.square().equals(this) ? z : null;
      }

      // p mod 4 == 1
      BigInteger qMinusOne = q.subtract(ECConstants.ONE);

      BigInteger legendreExponent = qMinusOne.shiftRight(1);
      if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) {
        return null;
      }

      BigInteger u = qMinusOne.shiftRight(2);
      BigInteger k = u.shiftLeft(1).add(ECConstants.ONE);

      BigInteger Q = this.x;
      BigInteger fourQ = Q.shiftLeft(2).mod(q);

      BigInteger U, V;
      Random rand = new Random();
      do {
        BigInteger P;
        do {
          P = new BigInteger(q.bitLength(), rand);
        } while (P.compareTo(q) >= 0
            || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, q).equals(qMinusOne)));

        BigInteger[] 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;

      // BigInteger qMinusOne = q.subtract(ECConstants.ONE);
      // BigInteger legendreExponent = qMinusOne.shiftRight(1); //divide(ECConstants.TWO);
      // if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE)))
      // {
      // return null;
      // }
      //
      // Random rand = new Random();
      // BigInteger fourX = x.shiftLeft(2);
      //
      // BigInteger r;
      // do
      // {
      // r = new BigInteger(q.bitLength(), rand);
      // }
      // while (r.compareTo(q) >= 0
      // || !(r.multiply(r).subtract(fourX).modPow(legendreExponent, q).equals(qMinusOne)));
      //
      // BigInteger n1 = qMinusOne.shiftRight(2); //.divide(ECConstants.FOUR);
      // BigInteger n2 = n1.add(ECConstants.ONE);
      // //q.add(ECConstants.THREE).divide(ECConstants.FOUR);
      //
      // BigInteger wOne = WOne(r, x, q);
      // BigInteger wSum = W(n1, wOne, q).add(W(n2, wOne, q)).mod(q);
      // BigInteger twoR = r.shiftLeft(1); //ECConstants.TWO.multiply(r);
      //
      // BigInteger root = twoR.modPow(q.subtract(ECConstants.TWO), q)
      // .multiply(x).mod(q)
      // .multiply(wSum).mod(q);
      //
      // return new Fp(q, root);
    }