--- /dev/null 2018-03-13 15:57:05.100000000 -0400 +++ new/src/java.base/share/classes/sun/security/util/math/IntegerModuloP.java 2018-03-20 10:01:34.838636000 -0400 @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.util.math; + +import java.math.BigInteger; + +/** + * The base interface for integers modulo a prime value. Objects of this + * type may be either mutable or immutable, and subinterfaces can be used + * to specify that an object is mutable or immutable. This type should never + * be used to declare local/member variables, but it may be used for + * formal parameters of a method. None of the methods in this interface + * modify the value of arguments or this. + * + * The behavior of this interface depends on the particular implementation. + * For example, some implementations only support a limited number of add + * operations before each multiply operation. See the documentation of the + * implementation for details. + * + * @see ImmutableIntegerModuloP + * @see MutableIntegerModuloP + */ +public interface IntegerModuloP { + + /** + * Get the field associated with this element. + * + * @return the field + */ + IntegerFieldModuloP getField(); + + /** + * Get the canonical value of this element as a BigInteger. This value + * will always be in the range [0, p), where p is the prime that defines + * the field. This method performs reduction and other computation to + * produce the result. + * + * @return the value as a BigInteger + */ + BigInteger asBigInteger(); + + /** + * Return this value as a fixed (immutable) element. This method will + * copy the underlying representation if the object is mutable. + * + * @return a fixed element with the same value + */ + ImmutableIntegerModuloP fixed(); + + /** + * Return this value as a mutable element. This method will always copy + * the underlying representation. + * + * @return a mutable element with the same value + */ + MutableIntegerModuloP mutable(); + + /** + * Add this field element with the supplied element and return the result. + * + * @param b the sumand + * @return this + b + */ + ImmutableIntegerModuloP add(IntegerModuloP b); + + /** + * Compute the additive inverse of the field element + * @return the addditiveInverse (0 - this) + */ + ImmutableIntegerModuloP additiveInverse(); + + /** + * Multiply this field element with the supplied element and return the + * result. + * + * @param b the multiplicand + * @return this * b + */ + ImmutableIntegerModuloP multiply(IntegerModuloP b); + + /** + * Perform an addition modulo a power of two and return the little-endian + * encoding of the result. The value is (this' + b') % 2^(8 * len), + * where this' and b' are the canonical integer values equivalent to + * this and b. + * + * @param b the sumand + * @param len the length of the desired array + * @return a byte array of length len containing the result + */ + default byte[] addModPowerTwo(IntegerModuloP b, int len) { + byte[] result = new byte[len]; + addModPowerTwo(b, result); + return result; + } + + /** + * Perform an addition modulo a power of two and store the little-endian + * encoding of the result in the supplied array. The value is + * (this' + b') % 2^(8 * result.length), where this' and b' are the + * canonical integer values equivalent to this and b. + * + * @param b the sumand + * @param result an array which stores the result upon return + */ + void addModPowerTwo(IntegerModuloP b, byte[] result); + + /** + * Returns the little-endian encoding of this' % 2^(8 * len), where this' + * is the canonical integer value equivalent to this. + * + * @param len the length of the desired array + * @return a byte array of length len containing the result + */ + default byte[] asByteArray(int len) { + byte[] result = new byte[len]; + asByteArray(result); + return result; + } + + /** + * Places the little-endian encoding of this' % 2^(8 * result.length) + * into the supplied array, where this' is the canonical integer value + * equivalent to this. + * + * @param result an array which stores the result upon return + */ + void asByteArray(byte[] result); + + /** + * Compute the multiplicative inverse of this field element. + * + * @return the multiplicative inverse (1 / this) + */ + default ImmutableIntegerModuloP multiplicativeInverse() { + return pow(getField().getSize().subtract(BigInteger.valueOf(2))); + } + + /** + * Subtract the supplied element from this one and return the result. + * @param b the subtrahend + * + * @return the difference (this - b) + */ + default ImmutableIntegerModuloP subtract(IntegerModuloP b) { + return add(b.additiveInverse()); + } + + /** + * Calculate the square of this element and return the result. This method + * should be used instead of a.multiply(a) because implementations may + * include optimizations that only apply to squaring. + * + * @return the product (this * this) + */ + default ImmutableIntegerModuloP square() { + return multiply(this); + } + + /** + * Calculate the power this^b and return the result. + * + * @param b the exponent + * @return the value of this^b + */ + default ImmutableIntegerModuloP pow(BigInteger b) { + //Default implementation is square and multiply + MutableIntegerModuloP y = getField().get1().mutable(); + MutableIntegerModuloP x = mutable(); + int bitLength = b.bitLength(); + for (int bit = 0; bit < bitLength; bit++) { + if (b.testBit(bit)) { + // odd + y.setProduct(x); + } + x.setSquare(); + } + return y.fixed(); + } + +} +