package net.i2p.crypto.eddsa.math.bigint; import java.io.Serializable; import java.math.BigInteger; import net.i2p.crypto.eddsa.math.Field; import net.i2p.crypto.eddsa.math.FieldElement; /** * A particular element of the field \Z/(2^255-19). * @author str4d * */ public class BigIntegerFieldElement extends FieldElement implements Serializable { private static final long serialVersionUID = 4890398908392808L; /** * Variable is package private for encoding. */ final BigInteger bi; public BigIntegerFieldElement(Field f, BigInteger bi) { super(f); this.bi = bi; } public boolean isNonZero() { return !bi.equals(BigInteger.ZERO); } public FieldElement add(FieldElement val) { return new BigIntegerFieldElement(f, bi.add(((BigIntegerFieldElement)val).bi)).mod(f.getQ()); } @Override public FieldElement addOne() { return new BigIntegerFieldElement(f, bi.add(BigInteger.ONE)).mod(f.getQ()); } public FieldElement subtract(FieldElement val) { return new BigIntegerFieldElement(f, bi.subtract(((BigIntegerFieldElement)val).bi)).mod(f.getQ()); } @Override public FieldElement subtractOne() { return new BigIntegerFieldElement(f, bi.subtract(BigInteger.ONE)).mod(f.getQ()); } public FieldElement negate() { return f.getQ().subtract(this); } @Override public FieldElement divide(FieldElement val) { return divide(((BigIntegerFieldElement)val).bi); } public FieldElement divide(BigInteger val) { return new BigIntegerFieldElement(f, bi.divide(val)).mod(f.getQ()); } public FieldElement multiply(FieldElement val) { return new BigIntegerFieldElement(f, bi.multiply(((BigIntegerFieldElement)val).bi)).mod(f.getQ()); } public FieldElement square() { return multiply(this); } public FieldElement squareAndDouble() { FieldElement sq = square(); return sq.add(sq); } public FieldElement invert() { // Euler's theorem //return modPow(f.getQm2(), f.getQ()); return new BigIntegerFieldElement(f, bi.modInverse(((BigIntegerFieldElement)f.getQ()).bi)); } public FieldElement mod(FieldElement m) { return new BigIntegerFieldElement(f, bi.mod(((BigIntegerFieldElement)m).bi)); } public FieldElement modPow(FieldElement e, FieldElement m) { return new BigIntegerFieldElement(f, bi.modPow(((BigIntegerFieldElement)e).bi, ((BigIntegerFieldElement)m).bi)); } public FieldElement pow(FieldElement e){ return modPow(e, f.getQ()); } public FieldElement pow22523(){ return pow(f.getQm5d8()); } @Override public int hashCode() { return bi.hashCode(); } @Override public boolean equals(Object obj) { if (!(obj instanceof BigIntegerFieldElement)) return false; BigIntegerFieldElement fe = (BigIntegerFieldElement) obj; return bi.equals(fe.bi); } @Override public String toString() { return "[BigIntegerFieldElement val="+bi+"]"; } }