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.Nat; 8d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.util.Arrays; 9d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 10d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootpublic class SecP521R1FieldElement extends ECFieldElement 11d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root{ 12d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public static final BigInteger Q = SecP521R1Curve.q; 13d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 14d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected int[] x; 15d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 16d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public SecP521R1FieldElement(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 SecP521R1FieldElement"); 21d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 22d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 23d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.x = SecP521R1Field.fromBigInteger(x); 24d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 25d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 26d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public SecP521R1FieldElement() 27d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 28d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.x = Nat.create(17); 29d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 30d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 31d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected SecP521R1FieldElement(int[] x) 32d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 33d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.x = x; 34d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 35d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 36d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public boolean isZero() 37d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 38d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Nat.isZero(17, x); 39d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 40d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 41d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public boolean isOne() 42d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 43d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Nat.isOne(17, x); 44d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 45d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 46d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public boolean testBitZero() 47d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 48d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Nat.getBit(x, 0) == 1; 49d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 50d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 51d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public BigInteger toBigInteger() 52d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 53d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Nat.toBigInteger(17, x); 54d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 55d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 56d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public String getFieldName() 57d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 58d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return "SecP521R1Field"; 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 = Nat.create(17); 69d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP521R1Field.add(x, ((SecP521R1FieldElement)b).x, z); 70d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP521R1FieldElement(z); 71d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 72d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 73d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement addOne() 74d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 75d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat.create(17); 76d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP521R1Field.addOne(x, z); 77d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP521R1FieldElement(z); 78d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 79d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 80d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement subtract(ECFieldElement b) 81d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 82d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat.create(17); 83d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP521R1Field.subtract(x, ((SecP521R1FieldElement)b).x, z); 84d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP521R1FieldElement(z); 85d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 86d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 87d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement multiply(ECFieldElement b) 88d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 89d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat.create(17); 90d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP521R1Field.multiply(x, ((SecP521R1FieldElement)b).x, z); 91d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP521R1FieldElement(z); 92d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 93d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 94d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement divide(ECFieldElement b) 95d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 96d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root// return multiply(b.invert()); 97d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat.create(17); 98d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root Mod.invert(SecP521R1Field.P, ((SecP521R1FieldElement)b).x, z); 99d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP521R1Field.multiply(z, x, z); 100d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP521R1FieldElement(z); 101d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 102d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 103d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement negate() 104d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 105d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat.create(17); 106d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP521R1Field.negate(x, z); 107d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP521R1FieldElement(z); 108d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 109d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 110d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement square() 111d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 112d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat.create(17); 113d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP521R1Field.square(x, z); 114d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP521R1FieldElement(z); 115d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 116d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 117d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement invert() 118d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 119d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root// return new SecP521R1FieldElement(toBigInteger().modInverse(Q)); 120d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] z = Nat.create(17); 121d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root Mod.invert(SecP521R1Field.P, x, z); 122d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new SecP521R1FieldElement(z); 123d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 124d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 125d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root // D.1.4 91 126d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root /** 127d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * return a sqrt root - the routine verifies that the calculation returns the right value - if 128d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * none exists it returns null. 129d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root */ 130d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECFieldElement sqrt() 131d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 132d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root // Raise this element to the exponent 2^519 133d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 134d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] x1 = this.x; 135d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (Nat.isZero(17, x1) || Nat.isOne(17, x1)) 136d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 137d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return this; 138d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 139d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 140d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] t1 = Nat.create(17); 141d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int[] t2 = Nat.create(17); 142d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 143d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP521R1Field.squareN(x1, 519, t1); 144d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP521R1Field.square(t1, t2); 145d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 146d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Nat.eq(17, x1, t2) ? new SecP521R1FieldElement(t1) : null; 147d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 148d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 149d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public boolean equals(Object other) 150d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 151d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (other == this) 152d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 153d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return true; 154d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 155d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 156d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (!(other instanceof SecP521R1FieldElement)) 157d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 158d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return false; 159d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 160d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 161d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root SecP521R1FieldElement o = (SecP521R1FieldElement)other; 162d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Nat.eq(17, x, o.x); 163d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 164d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 165d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public int hashCode() 166d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 167d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return Q.hashCode() ^ Arrays.hashCode(x, 0, 17); 168d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 169d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root} 170