1d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootpackage org.bouncycastle.math.ec.custom.sec; 2d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 3d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport java.math.BigInteger; 4d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 5d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.math.ec.ECFieldElement; 6d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.math.raw.Mod; 7d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.math.raw.Nat256; 8d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.util.Arrays; 9d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 10d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootpublic class SecP256R1FieldElement extends ECFieldElement 11d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root{ 12d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public static final BigInteger Q = SecP256R1Curve.q; 13d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 14d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected int[] x; 15d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 16d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public SecP256R1FieldElement(BigInteger x) 17d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 18d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0) 19d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 20d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("x value invalid for SecP256R1FieldElement"); 21d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 22d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 23d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.x = SecP256R1Field.fromBigInteger(x); 24d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 25d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 26d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public SecP256R1FieldElement() 27d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 28d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.x = Nat256.create(); 29d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 30d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 31d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected SecP256R1FieldElement(int[] x) 32d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 33d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.x = x; 34d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 35d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 36d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public boolean isZero() 37d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 38d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Nat256.isZero(x); 39d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 40d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 41d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public boolean isOne() 42d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 43d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Nat256.isOne(x); 44d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 45d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 46d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public boolean testBitZero() 47d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 48d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Nat256.getBit(x, 0) == 1; 49d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 50d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 51d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public BigInteger toBigInteger() 52d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 53d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Nat256.toBigInteger(x); 54d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 55d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 56d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public String getFieldName() 57d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 58d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return "SecP256R1Field"; 59d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 60d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 61d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public int getFieldSize() 62d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 63d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Q.bitLength(); 64d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 65d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 66d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement add(ECFieldElement b) 67d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 68d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat256.create(); 69d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.add(x, ((SecP256R1FieldElement)b).x, z); 70d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP256R1FieldElement(z); 71d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 72d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 73d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement addOne() 74d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 75d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat256.create(); 76d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.addOne(x, z); 77d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP256R1FieldElement(z); 78d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 79d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 80d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement subtract(ECFieldElement b) 81d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 82d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat256.create(); 83d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.subtract(x, ((SecP256R1FieldElement)b).x, z); 84d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP256R1FieldElement(z); 85d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 86d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 87d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement multiply(ECFieldElement b) 88d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 89d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat256.create(); 90d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.multiply(x, ((SecP256R1FieldElement)b).x, z); 91d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP256R1FieldElement(z); 92d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 93d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 94d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement divide(ECFieldElement b) 95d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 96d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root// return multiply(b.invert()); 97d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat256.create(); 98d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root Mod.invert(SecP256R1Field.P, ((SecP256R1FieldElement)b).x, z); 99d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.multiply(z, x, z); 100d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP256R1FieldElement(z); 101d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 102d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 103d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement negate() 104d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 105d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat256.create(); 106d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.negate(x, z); 107d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP256R1FieldElement(z); 108d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 109d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 110d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement square() 111d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 112d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat256.create(); 113d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.square(x, z); 114d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP256R1FieldElement(z); 115d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 116d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 117d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement invert() 118d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 119d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root// return new SecP256R1FieldElement(toBigInteger().modInverse(Q)); 120d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat256.create(); 121d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root Mod.invert(SecP256R1Field.P, x, z); 122d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP256R1FieldElement(z); 123d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 124d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 125d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root /** 126d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * return a sqrt root - the routine verifies that the calculation returns the right value - if 127d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * none exists it returns null. 128d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root */ 129d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement sqrt() 130d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 131d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root // Raise this element to the exponent 2^254 - 2^222 + 2^190 + 2^94 132d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 133d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] x1 = this.x; 134d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (Nat256.isZero(x1) || Nat256.isOne(x1)) 135d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 136d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return this; 137d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 138d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 139d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] t1 = Nat256.create(); 140d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] t2 = Nat256.create(); 141d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 142d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.square(x1, t1); 143d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.multiply(t1, x1, t1); 144d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 145d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.squareN(t1, 2, t2); 146d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.multiply(t2, t1, t2); 147d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 148d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.squareN(t2, 4, t1); 149d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.multiply(t1, t2, t1); 150d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 151d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.squareN(t1, 8, t2); 152d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.multiply(t2, t1, t2); 153d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 154d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.squareN(t2, 16, t1); 155d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.multiply(t1, t2, t1); 156d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 157d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.squareN(t1, 32, t1); 158d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.multiply(t1, x1, t1); 159d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 160d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.squareN(t1, 96, t1); 161d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.multiply(t1, x1, t1); 162d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 163d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.squareN(t1, 94, t1); 164d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1Field.square(t1, t2); 165d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 166d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Nat256.eq(x1, t2) ? new SecP256R1FieldElement(t1) : null; 167d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 168d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 169d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public boolean equals(Object other) 170d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 171d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (other == this) 172d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 173d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return true; 174d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 175d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 176d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (!(other instanceof SecP256R1FieldElement)) 177d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 178d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return false; 179d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 180d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 181d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP256R1FieldElement o = (SecP256R1FieldElement)other; 182d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Nat256.eq(x, o.x); 183d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 184d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 185d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public int hashCode() 186d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 187d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Q.hashCode() ^ Arrays.hashCode(x, 0, 8); 188d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 189d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root} 190