//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the Apache License Version 2.0.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
package com.microsoft.uprove;
import java.io.IOException;
import java.math.BigInteger;
/**
* Class representing the field of integers modulo a prime number
* <code>q</code>.
* <p>
* This is primarily an internal class used by the SDK's implementation. It is
* exposed for developers of new {@link PrimeOrderGroup} implementations, as
* they must support exponentiation of their group's elements to elements of a
* <code>FieldZq</code> whose <code>q</code> is equal to the group's prime
* order.
* </p>
*/
final class FieldZq {
private final BigInteger q;
/**
* Constructs the field of integers modulo <code>q</code>, which should
* be a prime number. Note that the primality of <code>q</code> is not
* check by the constructor, since it only needs to be checked once (and
* not every time the same value is used to instantiate a
* <code>FieldZq</code> object). It's up to the caller to validate
* primality of <code>q</code>.
* @param q number specifying the size of the field.
* @throws NullPointerException if <code>q</code> is <code>null</code>.
* @throws IllegalArgumentException if <code>q</code> is smaller or equal
* to 1.
*/
private FieldZq(final BigInteger q) {
// check that q > 1
if (q.compareTo(BigInteger.ONE) <= 0) {
throw new IllegalArgumentException(
"Invalid value for q (negative or zero)");
}
this.q = q;
}
/**
* Generates an instance of the field Zq.
* @param q number specifying the size of the field.
* @return a new field instance.
* @throws NullPointerException if <code>q</code> is <code>null</code>.
*/
static FieldZq getInstance(final BigInteger q) {
return new FieldZq(q);
}
/**
* Returns the size <code>q</code> of the field.
* @return size <code>q</code> of the field.
*/
public BigInteger getQ() {
// NOTE: no need for a defensive copy since BigInteger is immutable.
return q;
}
/**
* Returns an element of the field of value <code>0</code>.
* @return an element of the field of value <code>0</code>. Ownership of
* the referent is given to the caller.
*/
public ZqElement getZero() {
return new ZqElement(BigInteger.ZERO);
}
/**
* Returns an element of the field of value <code>1</code>.
* @return an element of the field of value <code>1</code>. Ownership of
* the referent is given to the caller.
*/
public ZqElement getOne() {
return new ZqElement(BigInteger.ONE);
}
/**
* Makes a defensive copy of a <code>BigInteger</code> originating from
* outside.
* @param i an integer.
* @return a copy of <code>i</code>.
*/
private static BigInteger makeSafe(final BigInteger i) {
if (i.getClass() == BigInteger.class) {
// it's already a safe instance, no need to copy
return i;
}
final byte[] buffer = i.toByteArray();
final BigInteger retVal = new BigInteger(buffer);
// clear the temporary buffer in case this is sensitive data
ByteArrays.erase(buffer);
return retVal;
}
/**
* Determines an element in the field of value <code>i mod q</code>.
* <p><b>NOTE:</b> As indicated, the value of the element returned will
* not be equal to <code>i</code> if <code>i</code> lies outside the
* field.</p>
*
* @param i a value from which an element in the field is to be derived.
* The caller's ownership of the referent is preserved.
* @return field element <code>i mod q</code>. Ownership of the referent is
* given to the caller.
* @throws NullPointerException if <code>i</code> is <code>null</code>.
*/
public ZqElement determineElement(final BigInteger i) {
// make a defensive copy of i since ZqElement's constructor will
// invoke mod() on its input parameter, and we don't know for sure
// that it won't return an instance of a malicious class derived from
// BigInteger.
return new ZqElement(makeSafe(i));
}
/**
* Returns an element in the field with the value specified by
* <code>i</code>.
* @param i the value of the desired field element.
* @return a field element of value <code>i</code>. Ownership of the
* referent is given to the caller.
* @throws IOException if <code>i</code> lies
* outside the field.
*/
private ZqElement getElementSafe(final BigInteger i)
throws IOException {
// negative values or values greater or equal to q are invalid
if (i.signum() < 0 || i.compareTo(getQ()) >= 0) {
throw new IOException("FieldZq.ZqElement value out of bounds");
}
return new ZqElement(i);
}
/**
* Returns an element in the field with the value specified by
* <code>i</code>.
* @param i the value of the desired field element.
* @return a field element of value <code>i</code>. Ownership of the
* referent is given to the caller.
* @throws NullPointerException if <code>i</code> is <code>null</code>.
* @throws IOException if <code>i</code> lies
* outside the field.
* @see ZqElement#toBigInteger()
*/
public ZqElement getElement(final BigInteger i)
throws IOException {
return getElementSafe(makeSafe(i));
}
/**
* Constructs a new element from the given byte array.
* @param isUnsigned if <code>true</code>, <code>data</code> does not
* carry a sign bit, and is therefore interpreted as the magnitude of
* a positive element; otherwise, it is interpreted as the two's
* complement representation of an element.
* @param data an encoding of an element. The caller's ownership of the
* referent is preserved.
* @return a new element.
* @throws NullPointerException if <code>data</code> is
* <code>null</code>.
* @throws IOException if the value is out of range.
*/
private ZqElement getElement(final boolean isUnsigned,
final byte[] data) throws IOException {
if (!isUnsigned && data.length == 0) {
// BigInteger's byte[] ctor would throw an NFE
throw new IOException(
"Zero-length encoded FieldZq.ZqElement value");
}
final BigInteger i = isUnsigned
? new BigInteger(1, data)
: new BigInteger(data);
return getElementSafe(i);
}
/**
* Returns an element in the field with the value specified by
* <code>data</code>.
* @param data the two's complement value, in big-endian byte-order, of
* the desired field element. The caller's ownership of the referent is
* preserved.
* @return a field element of value <code>data</code>. Ownership of the
* referent is given to the caller.
* @throws NullPointerException if <code>data</code> is <code>null</code>.
* @throws IOException if <code>data</code> lies
* outside the field, or cannot be converted into a value.
* @see ZqElement#toByteArray()
*/
public ZqElement getElement(final byte[] data)
throws IOException {
// getElement will ensure that the element has the same value
// as the given byte array.
return getElement(false, data);
}
/**
* Returns an element in the field with the value specified by
* <code>data</code>.
* @param data big-endian unsigned integer value of the desired
* field element. The caller's ownership of the referent is preserved.
* @return a field element of value <code>data</code>. Ownership of the
* referent is given to the caller.
* @throws NullPointerException if <code>data</code> is <code>null</code>.
* @throws IOException if <code>data</code> lies
* outside of the field, or cannot be converted into a value.
* @see ZqElement#getMagnitude()
*/
public ZqElement getPositiveElement(final byte[] data)
throws IOException {
// getElement will ensure that the element has the same value
// as the given byte array.
return getElement(true, data);
}
/**
* Determines an element in the field of value <code>e mod q</code>.
* <p>
* <b>NOTE:</b> As indicated, the value of the element returned will not
* be equal to <code>e</code> if <code>e</code> lies outside of this
* field.
* </p>
* @param e element of a field. The caller's ownership of the referent is
* preserved.
* @return an element of value <code>e mod q</code>. Ownership of the
* referent is given to the caller.
* @throws NullPointerException if <code>e</code> is <code>null</code>.
*/
public ZqElement determineElement(final ZqElement e) {
// ZqElement is final, so we don't need to make a defensive copy.
return new ZqElement(e.toBigInteger());
}
/**
* Returns a random element in the field, with uniform distribution.
* @param nonZero <code>true</code> to indicate that the result must
* not be equal to zero.
* @return an element in the field chosen uniformly at random.
* Ownership of the referent is given to the caller.
*/
public ZqElement getRandomElement(final boolean nonZero) {
BigInteger bi;
do {
bi = RandomSourceImpl.getRandomBigInteger(q.bitLength());
} while (
// Make sure the value is smaller than q. The constructor
// of ZqElement mods the value to make it a Zq element.
// If values between q and 2^(q.bitLength) were allowed,
// they would get mapped to Zq elements and this would
// introduce a bias in the RNG. This would open up
// attacks on the system (see Bleichenbacher's attack
// on FIPS 186's RNG). This technique is equivalent to
// NIST SP 800-90 (draft)'s "simple discard method"
// (section B.5.1.1). Maybe a future version will
// implement the "simple modular method" (section B.5.1.3)
// if the ratio q/2^(q.bitLength) is close to 0.5
(bi.compareTo(q) >= 0)
// Make sure that if nonZero is true, that the value
// is not zero.
|| (nonZero && bi.signum() == 0));
return new ZqElement(bi);
}
/**
* Returns an array of random element in the field, with uniform
* distribution.
* @param n number of elements to return, must be greater than zero.
* @param nonZero <code>true</code> to indicate that the elements must
* not be equal to zero.
* @return an array of random elements. Ownership of the referent and its
* contents are given to the caller.
*/
public ZqElement[] getRandomElements(final int n, final boolean nonZero) {
if (n <= 0) {
throw new IllegalArgumentException(
"n must be positive and greater than zero");
}
ZqElement[] values = new ZqElement[n];
for (int i = 0; i < n; i++) {
values[i] = getRandomElement(nonZero);
}
return values;
}
/**
* Indicates whether some other object is "equal to" this one.
* @param obj the reference object with which to compare.
* @return <code>true</code> if this object is the same as the
* <code>obj</code> argument; <code>false</code> otherwise.
*/
public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof FieldZq)) {
return false;
}
FieldZq f = (FieldZq) obj;
return q.equals(f.q);
}
/**
* Returns a hash code value for the object.
* @return a hash code value for the object.
*/
public int hashCode() {
return q.hashCode();
}
/**
* Returns an array of <code>ZqElement</code> objects corresponding to
* the given <code>byte[]</code> array elements.
* @param values array of <code>byte[]</code> to convert. The caller's
* ownership of the referent is preserved.
* @return an array of <code>ZqElement</code>. Ownership of the referent
* and its contents are given to the caller.
* @throws IOException if the data in the
* <code>values</code> array cannot be converted into elements.
* @see #getElement(byte[])
*/
public ZqElement[] getElementArray(final BigInteger[] values)
throws IOException {
ZqElement[] array = new ZqElement[values.length];
for (int i = 0; i < values.length; i++) {
array[i] = getElement(values[i]);
}
return array;
}
/**
* Returns the size (in bytes) of the largest encoded element.
* @return the size (in bytes) of the largest encoded element.
*/
public int getMaxEncodedElementSize() {
// add one to account for the added sign bit
// add seven to round up if needed (int division truncates, of course)
return (q.bitLength() + 8) / 8;
}
/**
* Validates that the field is well-formed, i.e. that <code>q</code> is
* prime.
* @throws IllegalStateException if the field is malformed.
*/
public void validate() {
// the constructor ensures that q > 1
// verify that q is prime
if (!q.isProbablePrime(ConfigImpl.getPrimeConfidenceLevel())) {
throw new IllegalStateException(
"Invalid value for q (not a prime)");
}
}
/**
* Represents an element in a <code>FieldZq</code>.
* <p>
* This is primarily an internal class used by the SDK's implementation. It
* is exposed for developers of new {@link PrimeOrderGroup}
* implementations, as they must support exponentiation of their group's
* elements by elements of a <code>FieldZq</code> whose <code>q</code>
* is equal to the group's prime order.
* </p>
*/
public final class ZqElement implements Element {
private BigInteger i;
/**
* Constructs a ZqElement.
* @param i integer representation of the element.
*/
ZqElement(final BigInteger i) {
// optimization: only i.mod(q) if (i lt zero) or (i ge q)
final BigInteger qVal = getQ();
this.i = ((i.signum() >= 0 && i.compareTo(qVal) < 0)
? i : i.mod(qVal));
}
/**
* Copy constructor of a ZqElement.
* <p>
* If <code>element</code> belongs to a <code>FieldZq</code> with a
* larger value for <code>q</code> than the field in which the new
* instance is to be created, the value of the new instance may not
* match that of <code>element</code>.
* </p>
* @param element an element.
* @throws NullPointerException if <code>element</code> is
* <code>null</code>.
*/
public ZqElement(final ZqElement element) throws NullPointerException {
// no need for a defensive copy since element is final and
// BigInteger is immutable.
this(element.i);
}
/**
* Returns the field to which this element belongs.
* @return this element's <code>FieldZq</code>.
*/
public FieldZq getField() {
return FieldZq.this;
}
/**
* Returns a ZqElement whose value is <code>this + val</code>.
* @param val value to add to this ZqElement.
* @return <code>this + val</code>.
* @throws IllegalArgumentException if <code>val</code> belongs to a
* field with a different <code>q</code>.
*/
public ZqElement add(final ZqElement val) {
if (!val.getField().equals(FieldZq.this)) {
throw new IllegalArgumentException();
}
return new ZqElement(i.add(val.i)); // constructor will "mod q" it
}
/**
* Assigns the value <code>this + val</code> to this ZqElement.
* @param val value to add to this ZqElement.
* @return <code>this = this + val</code>.
* @throws IllegalArgumentException if <code>val</code> belongs to a
* field with a different <code>q</code>.
*/
public ZqElement addAssign(final ZqElement val) {
if (!val.getField().equals(FieldZq.this)) {
throw new IllegalArgumentException();
}
i = i.add(val.i).mod(getQ());
return this;
}
/**
* Returns a ZqElement whose value is <code>this - val</code>.
* @param val value to subtract from this ZqElement.
* @return <code>this - val</code>.
* @throws IllegalArgumentException if <code>val</code> belongs to a
* field with a different <code>q</code>.
*/
public ZqElement subtract(final ZqElement val) {
if (!val.getField().equals(FieldZq.this)) {
throw new IllegalArgumentException();
}
// constructor will "mod q" result
return new ZqElement(i.subtract(val.i));
}
/**
* Assigns the value <code>this - val</code> to this ZqElement.
* @param val value to subtract from this ZqElement.
* @return <code>this = this - val</code>.
* @throws IllegalArgumentException if <code>val</code> belongs to a
* field with a different <code>q</code>.
*/
public ZqElement subtractAssign(final ZqElement val) {
if (!val.getField().equals(FieldZq.this)) {
throw new IllegalArgumentException();
}
i = i.subtract(val.i).mod(getQ());
return this;
}
/**
* Returns a ZqElement whose value is <code>this * val</code>.
* @param val value to multiply to this ZqElement.
* @return <code>this * val</code>.
* @throws IllegalArgumentException if <code>val</code> belongs to a
* field with a different <code>q</code>.
*/
public ZqElement multiply(final ZqElement val) {
if (!val.getField().equals(FieldZq.this)) {
throw new IllegalArgumentException();
}
// constructor will "mod q" result
return new ZqElement(i.multiply(val.i));
}
/**
* Assigns the value <code>this * val</code> to this ZqElement.
* @param val value to multiply to this ZqElement.
* @return <code>this = this * val</code>.
* @throws IllegalArgumentException if <code>val</code> belongs to a
* field with a different <code>q</code>.
*/
public ZqElement multiplyAssign(final ZqElement val) {
if (!val.getField().equals(FieldZq.this)) {
throw new IllegalArgumentException();
}
i = i.multiply(val.i).mod(getQ());
return this;
}
/**
* Returns a ZqElement whose value is <code>this / val</code>.
* @param val value to divide from this ZqElement.
* @return <code>this / val</code>.
* @throws IllegalArgumentException if <code>val</code> belongs to a
* field with a different <code>q</code>.
*/
public ZqElement divide(final ZqElement val) {
if (!val.getField().equals(FieldZq.this)) {
throw new IllegalArgumentException();
}
return multiply(val.inverse());
}
/**
* Assigns the value <code>this / val</code> to this ZqElement.
* @param val value to divide from this ZqElement.
* @return <code>this = this / val</code>.
* @throws IllegalArgumentException if <code>val</code> belongs to a
* field with a different <code>q</code>.
*/
public ZqElement divideAssign(final ZqElement val) {
if (!val.getField().equals(FieldZq.this)) {
throw new IllegalArgumentException();
}
multiplyAssign(val.inverse());
return this;
}
/**
* Returns the multiplicative inverse of this ZqElement.
* @return <code>this^(-1)</code>.
* @throws IllegalArgumentException if <code>this</code> is zero.
*/
public ZqElement inverse() {
if (i.equals(BigInteger.ZERO)) {
throw new ArithmeticException("Zero is not invertible");
}
return new ZqElement(i.modInverse(getQ()));
}
/**
* Assigns the multiplicative inverse of this ZqElement to
* <code>this</code>.
* @return <code>this = this^(-1)</code>.
* @throws IllegalArgumentException if <code>this</code> is zero.
*/
public ZqElement inverseAssign() {
if (i.equals(BigInteger.ZERO)) {
throw new ArithmeticException("Zero is not invertible");
}
i = i.modInverse(getQ());
return this;
}
/**
* Returns the additive negation of this ZqElement.
* @return <code>-this</code>.
*/
public ZqElement negate() {
return new ZqElement(i.negate()); // constructor will "mod q" it
}
/**
* Assigns the additive negation of this ZqElement to
* <code>this</code>.
* @return <code>this = -this</code>.
*/
public ZqElement negateAssign() {
i = i.negate().mod(getQ());
return this;
}
/**
* Returns a BigInteger representing this ZqElement.
* @return a BigInteger representing this ZqElement.
*/
public BigInteger toBigInteger() {
// NOTE: BigInteger is immutable, so no need for a defensive copy.
return i;
}
/* (non-Javadoc)
* @see com.microsoft.uprove.math.Element#length()
*/
public int length() {
return i.bitLength() / 8 + 1;
}
/**
* Returns an encoded representation of this element.
* @return an encoded representation of this element.
* @see FieldZq#getElement(byte[])
*/
public byte[] toByteArray() {
return ProtocolHelper.getMagnitude(i);
}
/**
* Returns the hexadecimal representation of this ZqElement.
* @return the hexadecimal representation of this ZqElement.
*/
public String toString() {
return i.toString(16);
}
/**
* Returns a String representation of the ZqElement in a given radix.
* If the radix is outside the range from {@link Character#MIN_RADIX}
* to {@link Character#MAX_RADIX} inclusive, it will default to 10.
* @param radix radix (i.e. base) of the String representation.
* @return a String representation of the ZqElement in a given radix.
* @see BigInteger#toString(int)
*/
public String toString(final int radix) {
return i.toString(radix);
}
/**
* Indicates whether some other object is "equal to" this one.
* @param o the reference object with which to compare.
* @return <code>true</code> if this object is the same as the
* <code>o</code> argument; <code>false</code> otherwise.
*/
public boolean equals(final Object o) {
if (o == this) {
return true;
}
if (!(o instanceof ZqElement)) {
return false;
}
ZqElement element = (ZqElement) o;
return i.equals(element.i);
}
/**
* Returns a hash code value for the object.
* @return a hash code value for the object.
*/
public int hashCode() {
return i.hashCode();
}
/**
* Adds the element to the hash updater.
* @param dv the hash updater.
*/
public void addToDigest(final HashUpdater dv) {
dv.update(i);
}
}
}