1894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanpackage org.bouncycastle.math.ec.custom.sec; 2894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 3894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanimport java.math.BigInteger; 4894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 5894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanimport org.bouncycastle.math.ec.ECFieldElement; 6894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanimport org.bouncycastle.math.raw.Mod; 7894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanimport org.bouncycastle.math.raw.Nat256; 8894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanimport org.bouncycastle.util.Arrays; 9894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 10894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanpublic class SecP256R1FieldElement extends ECFieldElement 11894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{ 12894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public static final BigInteger Q = SecP256R1Curve.q; 13894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 14894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman protected int[] x; 15894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 16894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public SecP256R1FieldElement(BigInteger x) 17894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 1819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0) 19894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 20894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman throw new IllegalArgumentException("x value invalid for SecP256R1FieldElement"); 21894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 22894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 23894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman this.x = SecP256R1Field.fromBigInteger(x); 2419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 2519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 26894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public SecP256R1FieldElement() 27894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 28894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman this.x = Nat256.create(); 29894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 30894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 31894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman protected SecP256R1FieldElement(int[] x) 32894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 33894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman this.x = x; 34894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 35894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 36894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public boolean isZero() 37894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 38894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return Nat256.isZero(x); 39894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 40894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 41894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public boolean isOne() 42894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 43894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return Nat256.isOne(x); 44894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 45894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 46894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public boolean testBitZero() 47894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 48894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return Nat256.getBit(x, 0) == 1; 49894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 50894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 51894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public BigInteger toBigInteger() 52894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 53894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return Nat256.toBigInteger(x); 54894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 55894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 56894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public String getFieldName() 57894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 58894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return "SecP256R1Field"; 59894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 60894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 61894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public int getFieldSize() 62894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 63894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return Q.bitLength(); 64894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 65894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 66894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public ECFieldElement add(ECFieldElement b) 67894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 68894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman int[] z = Nat256.create(); 69894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SecP256R1Field.add(x, ((SecP256R1FieldElement)b).x, z); 70894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return new SecP256R1FieldElement(z); 71894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 72894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 73894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public ECFieldElement addOne() 74894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 75894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman int[] z = Nat256.create(); 76894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SecP256R1Field.addOne(x, z); 77894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return new SecP256R1FieldElement(z); 78894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 79894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 80894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public ECFieldElement subtract(ECFieldElement b) 81894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 82894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman int[] z = Nat256.create(); 83894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SecP256R1Field.subtract(x, ((SecP256R1FieldElement)b).x, z); 84894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return new SecP256R1FieldElement(z); 85894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 86894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 87894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public ECFieldElement multiply(ECFieldElement b) 88894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 89894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman int[] z = Nat256.create(); 90894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SecP256R1Field.multiply(x, ((SecP256R1FieldElement)b).x, z); 91894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return new SecP256R1FieldElement(z); 92894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 93894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 94894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public ECFieldElement divide(ECFieldElement b) 95894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 96894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// return multiply(b.invert()); 97894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman int[] z = Nat256.create(); 98894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman Mod.invert(SecP256R1Field.P, ((SecP256R1FieldElement)b).x, z); 99894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SecP256R1Field.multiply(z, x, z); 10019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return new SecP256R1FieldElement(z); 10119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 10219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 10319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman public ECFieldElement negate() 10419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman { 105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman int[] z = Nat256.create(); 106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SecP256R1Field.negate(x, z); 107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return new SecP256R1FieldElement(z); 108894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 109894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public ECFieldElement square() 111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 112894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman int[] z = Nat256.create(); 113894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SecP256R1Field.square(x, z); 11419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return new SecP256R1FieldElement(z); 11519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 11619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 11719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman public ECFieldElement invert() 11819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman { 11919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// return new SecP256R1FieldElement(toBigInteger().modInverse(Q)); 12019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman int[] z = Nat256.create(); 12119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Mod.invert(SecP256R1Field.P, x, z); 12219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return new SecP256R1FieldElement(z); 12319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 12419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 12519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman /** 12619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman * return a sqrt root - the routine verifies that the calculation returns the right value - if 12719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman * none exists it returns null. 12819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman */ 12919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman public ECFieldElement sqrt() 13019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman { 13119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Raise this element to the exponent 2^254 - 2^222 + 2^190 + 2^94 13219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 13319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman int[] x1 = this.x; 13419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Nat256.isZero(x1) || Nat256.isOne(x1)) 13519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman { 13619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return this; 13719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 13819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 13919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman int[] t1 = Nat256.create(); 14019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman int[] t2 = Nat256.create(); 14119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 14219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.square(x1, t1); 14319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.multiply(t1, x1, t1); 14419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 14519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.squareN(t1, 2, t2); 14619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.multiply(t2, t1, t2); 14719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 14819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.squareN(t2, 4, t1); 14919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.multiply(t1, t2, t1); 15019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 15119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.squareN(t1, 8, t2); 15219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.multiply(t2, t1, t2); 15319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 15419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.squareN(t2, 16, t1); 15519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.multiply(t1, t2, t1); 15619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 15719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.squareN(t1, 32, t1); 15819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.multiply(t1, x1, t1); 15919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 16019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.squareN(t1, 96, t1); 16119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.multiply(t1, x1, t1); 16219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 16319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.squareN(t1, 94, t1); 16419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SecP256R1Field.square(t1, t2); 16519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 16619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return Nat256.eq(x1, t2) ? new SecP256R1FieldElement(t1) : null; 16719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 16819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 16919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman public boolean equals(Object other) 17019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman { 17119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (other == this) 17219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman { 17319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return true; 174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 176894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman if (!(other instanceof SecP256R1FieldElement)) 177894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 178894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return false; 179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman SecP256R1FieldElement o = (SecP256R1FieldElement)other; 182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return Nat256.eq(x, o.x); 183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 184894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman 185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman public int hashCode() 186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman { 187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman return Q.hashCode() ^ Arrays.hashCode(x, 0, 8); 188894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman } 189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman} 190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman