All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.n1analytics.paillier.EncryptedNumber Maven / Gradle / Ivy

There is a newer version: 0.6.0
Show newest version
/**
 * Copyright 2015 NICTA
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
 * file except in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under
 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
package com.n1analytics.paillier;

import com.n1analytics.paillier.util.HashChain;

import java.math.BigInteger;

/**
 * Immutable class representing encrypted number and arithmetic operations that can be computed on the encrypted number.
 *
 * The attributes stored in this class are:
 * 
    *
  • public key: the Paillier public key use to encrypt this EncryptedNumber
  • *
  • ciphertext: the encrypted representation of the EncodedNumber
  • *
  • exponent: the exponent of the encrypted EncodedNumber
  • *
  • isObfuscated: indicates whether this EncryptedNumber has been obfuscated with a random number
  • *
* * This class provides a method to obfuscate this EncryptedNumber with a random number. It also contains a number of * arithmetic operations that can be computed between this EncryptedNumber and other EncryptedNumber or * a non-encrypted number (EncodedNumber, double, long or BigInteger). The supported arithmetic operations are: *
    *
  • Addition of two encrypted numbers
  • *
  • Addition of an encrypted number with a non-encrypted number
  • *
  • Multiplication of an encrypted number with a non-encrypted number
  • *
  • Subtraction of an encrypted number from another encrypted number
  • *
  • Subtraction of an non-encrypted number from an encrypted number
  • *
  • Division of an encrypted number by a double/long
  • *
* The arithmetic operations can only be performed when both operands have the same exponent, as a result this class * also provides a method to decrase the exponent of the operand with the higher exponent. * * Examples: *
    *
  • * To obfuscate an EncryptedNumber, encryptedNumber: *
    * EncryptedNumber obfuscatedEncrypion = encryptedNumber.obfuscate(); *
  • *
  • * To decrease the exponent of an EncryptedNumber, encryptedNumber, to -20: *
    * EncryptedNumber decreasedExponent = encryptedNumber.decreaseExponentTo(-20); *
  • *
  • * To add two EncryptedNumbers, encryption1 + encryption2: *
    * EncryptedNumber additionResult = encryption1.add(encryption2); *
  • *
  • * To add an EncryptedNumber and an EncodedNumber, encryption + encoded: *
    * EncryptedNumber additionResult = encryption.add(encoded); *
  • *
  • * To subtract an EncryptedNumber from another EncryptedNumber, encryption1 - encryption2: *
    * EncryptedNumber subtractionResult = encryption1.subtract(encryption2); *
  • *
  • * To subtract an EncodedNumber from an EncryptedNumber, encryption - encoded: *
    * EncryptedNumber subtractionResult = encryption.subtract(encoded); *
  • *
  • * To multiply an EncryptedNumber with an EncodedNumber, encryption * encoded: *
    * EncryptedNumber multiplicationResult = encryption.multiply(encoded); *
  • *
  • * To divide an EncryptedNumber by a double, encryption / numDouble: *
    * EncryptedNumber divisionResult = encryption.divide(numDouble); *
  • *
*/ public final class EncryptedNumber { public static interface Serializer { void serialize(PaillierContext context, BigInteger value, int exponent); } protected final PaillierContext context; protected final transient BigInteger ciphertext; protected final int exponent; protected final boolean isSafe; /** * Constructs an encrypted number given the public key used to encrypt this * encrypted number, the ciphertext (ie, the encrypted representation of the * encoded number) and the exponent representing the precision of the * ciphertext. * * @param context PaillierContext used to encrypt this encrypted number. * @param ciphertext the encrypted representation of the encoded number. * @param exponent the exponent of the ciphertext. * @param isSafe set to true if cypertext is obfuscated */ public EncryptedNumber(PaillierContext context, BigInteger ciphertext, int exponent, boolean isSafe) { if (context == null) { throw new IllegalArgumentException("context must not be null"); } if (ciphertext == null) { throw new IllegalArgumentException("unsafeCiphertext must not be null"); } if (ciphertext.signum() < 0) { throw new IllegalArgumentException("unsafeCiphertext must be non-negative"); } if (ciphertext.compareTo(context.getPublicKey().getModulusSquared()) >= 0) { throw new IllegalArgumentException( "unsafeCiphertext must be less than modulus squared"); } this.context = context; this.ciphertext = ciphertext; this.exponent = exponent; this.isSafe = isSafe; } /** * Constructs an encrypted number given the public key used to encrypt this * encrypted number, the ciphertext (ie, the encrypted representation of the * encoded number) and the exponent representing the precision of the * ciphertext. * * @param context PaillierContext used to encrypt this encrypted number. * @param ciphertext the encrypted representation of the encoded number. * @param exponent the exponent of the ciphertext. */ public EncryptedNumber(PaillierContext context, BigInteger ciphertext, int exponent) { this(context, ciphertext, exponent, false); } public PaillierContext getContext() { return context; } /** * Gets the ciphertext. * * @return ciphertext. */ public BigInteger calculateCiphertext() { return isSafe ? ciphertext : obfuscate().ciphertext; } public int getExponent() { return exponent; } public EncryptedNumber checkSameContext(EncryptedNumber other) throws ArithmeticException { return context.checkSameContext(other); } public EncodedNumber checkSameContext(EncodedNumber other) { return context.checkSameContext(other); } public EncodedNumber decrypt(PaillierPrivateKey key) { return key.decrypt(this); } /** * Obfuscates the encrypted number by multiplying it with rn, * where n is the modulus of the public key and r is a random positive * number less than n. * @return An obfuscated version of this encrypted number. */ public EncryptedNumber obfuscate() { return context.obfuscate(this); } public EncryptedNumber add(EncryptedNumber other) { return context.add(this, other); } public EncryptedNumber add(EncodedNumber other) { return context.add(this, other); } public EncryptedNumber add(Number other) { return add(context.encode(other)); } public EncryptedNumber add(BigInteger other) { return add(context.encode(other)); } public EncryptedNumber add(double other) { return add(context.encode(other)); } public EncryptedNumber add(long other) { return add(context.encode(other)); } public EncryptedNumber additiveInverse() { return context.additiveInverse(this); } public EncryptedNumber subtract(EncryptedNumber other) { return context.subtract(this, other); } public EncryptedNumber subtract(EncodedNumber other) { return context.subtract(this, other); } public EncryptedNumber subtract(Number other) { return subtract(context.encode(other)); } public EncryptedNumber subtract(BigInteger other) { return subtract(context.encode(other)); } public EncryptedNumber subtract(double other) { return subtract(context.encode(other)); } public EncryptedNumber subtract(long other) { return subtract(context.encode(other)); } public EncryptedNumber multiply(EncodedNumber other) { return context.multiply(this, other); } public EncryptedNumber multiply(Number other) { return multiply(context.encode(other)); } public EncryptedNumber multiply(BigInteger other) { return multiply(context.encode(other)); } public EncryptedNumber multiply(double other) { return multiply(context.encode(other)); } public EncryptedNumber multiply(long other) { return multiply(context.encode(other)); } // TODO Issue #10 /* public EncryptedNumber divide(EncodedNumber other) { return context.divide(this, other); } public EncryptedNumber divide(Number other) { return divide(context.encode(other)); } public EncryptedNumber divide(BigInteger other) { return divide(context.encode(other)); } */ public EncryptedNumber divide(double other) { return multiply(context.encode(1.0 / other)); // TODO Issue #10: unhack } public EncryptedNumber divide(long other) { return multiply(context.encode(1.0 / other)); // TODO Issue #10: unhack } public void serialize(Serializer serializer) { serializer.serialize(context, calculateCiphertext(), exponent); } @Override public int hashCode() { return new HashChain().chain(context).chain(ciphertext).hashCode(); } @Override public boolean equals(Object o) { if (o == this) { return true; } if (o == null || o.getClass() != EncryptedNumber.class) { return false; } EncryptedNumber number = (EncryptedNumber) o; return context.equals(number.context) && ciphertext.equals(number.ciphertext); } public boolean equals(EncryptedNumber o) { return o == this || (o != null && context.equals(o.context) && ciphertext.equals(o.ciphertext)); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy