Home | History | Annotate | Download | only in sec
      1 package org.bouncycastle.math.ec.custom.sec;
      2 
      3 import org.bouncycastle.math.ec.ECCurve;
      4 import org.bouncycastle.math.ec.ECFieldElement;
      5 import org.bouncycastle.math.ec.ECPoint;
      6 import org.bouncycastle.math.raw.Nat;
      7 
      8 public class SecP521R1Point extends ECPoint.AbstractFp
      9 {
     10     /**
     11      * Create a point which encodes with point compression.
     12      *
     13      * @param curve
     14      *            the curve to use
     15      * @param x
     16      *            affine x co-ordinate
     17      * @param y
     18      *            affine y co-ordinate
     19      *
     20      * @deprecated Use ECCurve.createPoint to construct points
     21      */
     22     public SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
     23     {
     24         this(curve, x, y, false);
     25     }
     26 
     27     /**
     28      * Create a point that encodes with or without point compresion.
     29      *
     30      * @param curve
     31      *            the curve to use
     32      * @param x
     33      *            affine x co-ordinate
     34      * @param y
     35      *            affine y co-ordinate
     36      * @param withCompression
     37      *            if true encode with point compression
     38      *
     39      * @deprecated per-point compression property will be removed, refer
     40      *             {@link #getEncoded(boolean)}
     41      */
     42     public SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
     43     {
     44         super(curve, x, y);
     45 
     46         if ((x == null) != (y == null))
     47         {
     48             throw new IllegalArgumentException("Exactly one of the field elements is null");
     49         }
     50 
     51         this.withCompression = withCompression;
     52     }
     53 
     54     SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
     55     {
     56         super(curve, x, y, zs);
     57 
     58         this.withCompression = withCompression;
     59     }
     60 
     61     protected ECPoint detach()
     62     {
     63         return new SecP521R1Point(null, getAffineXCoord(), getAffineYCoord());
     64     }
     65 
     66     public ECPoint add(ECPoint b)
     67     {
     68         if (this.isInfinity())
     69         {
     70             return b;
     71         }
     72         if (b.isInfinity())
     73         {
     74             return this;
     75         }
     76         if (this == b)
     77         {
     78             return twice();
     79         }
     80 
     81         ECCurve curve = this.getCurve();
     82 
     83         SecP521R1FieldElement X1 = (SecP521R1FieldElement)this.x, Y1 = (SecP521R1FieldElement)this.y;
     84         SecP521R1FieldElement X2 = (SecP521R1FieldElement)b.getXCoord(), Y2 = (SecP521R1FieldElement)b.getYCoord();
     85 
     86         SecP521R1FieldElement Z1 = (SecP521R1FieldElement)this.zs[0];
     87         SecP521R1FieldElement Z2 = (SecP521R1FieldElement)b.getZCoord(0);
     88 
     89         int[] t1 = Nat.create(17);
     90         int[] t2 = Nat.create(17);
     91         int[] t3 = Nat.create(17);
     92         int[] t4 = Nat.create(17);
     93 
     94         boolean Z1IsOne = Z1.isOne();
     95         int[] U2, S2;
     96         if (Z1IsOne)
     97         {
     98             U2 = X2.x;
     99             S2 = Y2.x;
    100         }
    101         else
    102         {
    103             S2 = t3;
    104             SecP521R1Field.square(Z1.x, S2);
    105 
    106             U2 = t2;
    107             SecP521R1Field.multiply(S2, X2.x, U2);
    108 
    109             SecP521R1Field.multiply(S2, Z1.x, S2);
    110             SecP521R1Field.multiply(S2, Y2.x, S2);
    111         }
    112 
    113         boolean Z2IsOne = Z2.isOne();
    114         int[] U1, S1;
    115         if (Z2IsOne)
    116         {
    117             U1 = X1.x;
    118             S1 = Y1.x;
    119         }
    120         else
    121         {
    122             S1 = t4;
    123             SecP521R1Field.square(Z2.x, S1);
    124 
    125             U1 = t1;
    126             SecP521R1Field.multiply(S1, X1.x, U1);
    127 
    128             SecP521R1Field.multiply(S1, Z2.x, S1);
    129             SecP521R1Field.multiply(S1, Y1.x, S1);
    130         }
    131 
    132         int[] H = Nat.create(17);
    133         SecP521R1Field.subtract(U1, U2, H);
    134 
    135         int[] R = t2;
    136         SecP521R1Field.subtract(S1, S2, R);
    137 
    138         // Check if b == this or b == -this
    139         if (Nat.isZero(17, H))
    140         {
    141             if (Nat.isZero(17, R))
    142             {
    143                 // this == b, i.e. this must be doubled
    144                 return this.twice();
    145             }
    146 
    147             // this == -b, i.e. the result is the point at infinity
    148             return curve.getInfinity();
    149         }
    150 
    151         int[] HSquared = t3;
    152         SecP521R1Field.square(H, HSquared);
    153 
    154         int[] G = Nat.create(17);
    155         SecP521R1Field.multiply(HSquared, H, G);
    156 
    157         int[] V = t3;
    158         SecP521R1Field.multiply(HSquared, U1, V);
    159 
    160         SecP521R1Field.multiply(S1, G, t1);
    161 
    162         SecP521R1FieldElement X3 = new SecP521R1FieldElement(t4);
    163         SecP521R1Field.square(R, X3.x);
    164         SecP521R1Field.add(X3.x, G, X3.x);
    165         SecP521R1Field.subtract(X3.x, V, X3.x);
    166         SecP521R1Field.subtract(X3.x, V, X3.x);
    167 
    168         SecP521R1FieldElement Y3 = new SecP521R1FieldElement(G);
    169         SecP521R1Field.subtract(V, X3.x, Y3.x);
    170         SecP521R1Field.multiply(Y3.x, R, t2);
    171         SecP521R1Field.subtract(t2, t1, Y3.x);
    172 
    173         SecP521R1FieldElement Z3 = new SecP521R1FieldElement(H);
    174         if (!Z1IsOne)
    175         {
    176             SecP521R1Field.multiply(Z3.x, Z1.x, Z3.x);
    177         }
    178         if (!Z2IsOne)
    179         {
    180             SecP521R1Field.multiply(Z3.x, Z2.x, Z3.x);
    181         }
    182 
    183         ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
    184 
    185         return new SecP521R1Point(curve, X3, Y3, zs, this.withCompression);
    186     }
    187 
    188     public ECPoint twice()
    189     {
    190         if (this.isInfinity())
    191         {
    192             return this;
    193         }
    194 
    195         ECCurve curve = this.getCurve();
    196 
    197         SecP521R1FieldElement Y1 = (SecP521R1FieldElement)this.y;
    198         if (Y1.isZero())
    199         {
    200             return curve.getInfinity();
    201         }
    202 
    203         SecP521R1FieldElement X1 = (SecP521R1FieldElement)this.x, Z1 = (SecP521R1FieldElement)this.zs[0];
    204 
    205         int[] t1 = Nat.create(17);
    206         int[] t2 = Nat.create(17);
    207 
    208         int[] Y1Squared = Nat.create(17);
    209         SecP521R1Field.square(Y1.x, Y1Squared);
    210 
    211         int[] T = Nat.create(17);
    212         SecP521R1Field.square(Y1Squared, T);
    213 
    214         boolean Z1IsOne = Z1.isOne();
    215 
    216         int[] Z1Squared = Z1.x;
    217         if (!Z1IsOne)
    218         {
    219             Z1Squared = t2;
    220             SecP521R1Field.square(Z1.x, Z1Squared);
    221         }
    222 
    223         SecP521R1Field.subtract(X1.x, Z1Squared, t1);
    224 
    225         int[] M = t2;
    226         SecP521R1Field.add(X1.x, Z1Squared, M);
    227         SecP521R1Field.multiply(M, t1, M);
    228         Nat.addBothTo(17, M, M, M);
    229         SecP521R1Field.reduce23(M);
    230 
    231         int[] S = Y1Squared;
    232         SecP521R1Field.multiply(Y1Squared, X1.x, S);
    233         Nat.shiftUpBits(17, S, 2, 0);
    234         SecP521R1Field.reduce23(S);
    235 
    236         Nat.shiftUpBits(17, T, 3, 0, t1);
    237         SecP521R1Field.reduce23(t1);
    238 
    239         SecP521R1FieldElement X3 = new SecP521R1FieldElement(T);
    240         SecP521R1Field.square(M, X3.x);
    241         SecP521R1Field.subtract(X3.x, S, X3.x);
    242         SecP521R1Field.subtract(X3.x, S, X3.x);
    243 
    244         SecP521R1FieldElement Y3 = new SecP521R1FieldElement(S);
    245         SecP521R1Field.subtract(S, X3.x, Y3.x);
    246         SecP521R1Field.multiply(Y3.x, M, Y3.x);
    247         SecP521R1Field.subtract(Y3.x, t1, Y3.x);
    248 
    249         SecP521R1FieldElement Z3 = new SecP521R1FieldElement(M);
    250         SecP521R1Field.twice(Y1.x, Z3.x);
    251         if (!Z1IsOne)
    252         {
    253             SecP521R1Field.multiply(Z3.x, Z1.x, Z3.x);
    254         }
    255 
    256         return new SecP521R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
    257     }
    258 
    259     public ECPoint twicePlus(ECPoint b)
    260     {
    261         if (this == b)
    262         {
    263             return threeTimes();
    264         }
    265         if (this.isInfinity())
    266         {
    267             return b;
    268         }
    269         if (b.isInfinity())
    270         {
    271             return twice();
    272         }
    273 
    274         ECFieldElement Y1 = this.y;
    275         if (Y1.isZero())
    276         {
    277             return b;
    278         }
    279 
    280         return twice().add(b);
    281     }
    282 
    283     public ECPoint threeTimes()
    284     {
    285         if (this.isInfinity() || this.y.isZero())
    286         {
    287             return this;
    288         }
    289 
    290         // NOTE: Be careful about recursions between twicePlus and threeTimes
    291         return twice().add(this);
    292     }
    293 
    294     protected ECFieldElement two(ECFieldElement x)
    295     {
    296         return x.add(x);
    297     }
    298 
    299     protected ECFieldElement three(ECFieldElement x)
    300     {
    301         return two(x).add(x);
    302     }
    303 
    304     protected ECFieldElement four(ECFieldElement x)
    305     {
    306         return two(two(x));
    307     }
    308 
    309     protected ECFieldElement eight(ECFieldElement x)
    310     {
    311         return four(two(x));
    312     }
    313 
    314     protected ECFieldElement doubleProductFromSquares(ECFieldElement a, ECFieldElement b,
    315         ECFieldElement aSquared, ECFieldElement bSquared)
    316     {
    317         /*
    318          * NOTE: If squaring in the field is faster than multiplication, then this is a quicker
    319          * way to calculate 2.A.B, if A^2 and B^2 are already known.
    320          */
    321         return a.add(b).square().subtract(aSquared).subtract(bSquared);
    322     }
    323 
    324     public ECPoint negate()
    325     {
    326         if (this.isInfinity())
    327         {
    328             return this;
    329         }
    330 
    331         return new SecP521R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
    332     }
    333 }
    334