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