All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bccapi.bitlib.crypto.ec.Point Maven / Gradle / Ivy

There is a newer version: 1.0.3
Show newest version
/**
 * This code was extracted from the Java cryptography library from
 * www.bouncycastle.org. The code has been formatted to comply with the rest of
 * the formatting in this library.
 */
package com.bccapi.bitlib.crypto.ec;

import java.io.Serializable;
import java.math.BigInteger;

/**
 * This class represents an elliptic curve point.
 */
public class Point implements Serializable {

   private static final long serialVersionUID = 1L;
   
   private Curve _curve;
   private FieldElement _x;
   private FieldElement _y;
   private boolean _compressed;

   public Point(Curve curve, FieldElement x, FieldElement y) {
      this(curve, x, y, false);
   }

   public Point(Curve curve, FieldElement x, FieldElement y, boolean compressed) {
      this._curve = curve;
      this._x = x;
      this._y = y;
      this._compressed = compressed;
   }

   public Curve getCurve() {
      return _curve;
   }

   public FieldElement getX() {
      return _x;
   }

   public FieldElement getY() {
      return _y;
   }

   public boolean isInfinity() {
      return _x == null && _y == null;
   }

   public boolean isCompressed() {
      return _compressed;
   }

   /**
    * @return the field element encoded with point compression. (S 4.3.6)
    *
    */
   public byte[] getEncoded() {
      if (this.isInfinity()) {
         return new byte[1];
      }

      int length = EcTools.getByteLength(_x);

      if (_compressed) {
         byte PC;

         if (this.getY().toBigInteger().testBit(0)) {
            PC = 0x03;
         } else {
            PC = 0x02;
         }

         byte[] X = EcTools.integerToBytes(this.getX().toBigInteger(), length);
         byte[] PO = new byte[X.length + 1];

         PO[0] = PC;
         System.arraycopy(X, 0, PO, 1, X.length);

         return PO;
      } else {
         byte[] X = EcTools.integerToBytes(this.getX().toBigInteger(), length);
         byte[] Y = EcTools.integerToBytes(this.getY().toBigInteger(), length);
         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 Point add(Point 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();
      }

      FieldElement gamma = b._y.subtract(this._y).divide(b._x.subtract(this._x));

      FieldElement x3 = gamma.square().subtract(this._x).subtract(b._x);
      FieldElement y3 = gamma.multiply(this._x.subtract(x3)).subtract(this._y);

      return new Point(_curve, x3, y3);
   }

   // B.3 pg 62
   public Point 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();
      }

      FieldElement TWO = this._curve.fromBigInteger(BigInteger.valueOf(2));
      FieldElement THREE = this._curve.fromBigInteger(BigInteger.valueOf(3));
      FieldElement gamma = this._x.square().multiply(THREE).add(_curve.getA()).divide(_y.multiply(TWO));

      FieldElement x3 = gamma.square().subtract(this._x.multiply(TWO));
      FieldElement y3 = gamma.multiply(this._x.subtract(x3)).subtract(this._y);

      return new Point(_curve, x3, y3, this._compressed);
   }

   // D.3.2 pg 102 (see Note:)
   public Point subtract(Point b) {
      if (b.isInfinity()) {
         return this;
      }

      // Add -b
      return add(b.negate());
   }

   public Point negate() {
      return new Point(_curve, this._x, this._y.negate(), this._compressed);
   }

   @Override
   public boolean equals(Object other) {
      if (other == this) {
         return true;
      }

      if (!(other instanceof Point)) {
         return false;
      }

      Point o = (Point) other;

      if (this.isInfinity()) {
         return o.isInfinity();
      }

      return _x.equals(o._x) && _y.equals(o._y);
   }

   @Override
   public int hashCode() {
      if (this.isInfinity()) {
         return 0;
      }

      return _x.hashCode() ^ _y.hashCode();
   }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy