ope icon indicating copy to clipboard operation
ope copied to clipboard

When the plaintext is a floating point number, the order of the ciphertext cannot be guaranteed.

Open littleniannian opened this issue 1 year ago • 3 comments

  • case1: When i use FastOPE, encrypt the plaintext to hex ciphertext, then i insert data to database. I select data order by ciphertext. the order is out of order.
  • case2: When i use mope,encrypt short data, the same as case 1

littleniannian avatar Jul 23 '24 07:07 littleniannian

@littleniannian Can you provide sample data?

aymanmadkour avatar Jul 23 '24 08:07 aymanmadkour

@littleniannian Can you provide sample data? Change the OpeTest like this.


import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * @author Ayman Madkour
 */
public abstract class OpeTest {
	
	protected double[] plaintexts;
	protected byte[][] ciphertexts;
	
	protected Cipher cipher;
	protected Key key;
	
	protected abstract Cipher createCipher();
	
	@Before
	public void setUp() {
		// Initialize cipher
		cipher = createCipher();
		key = cipher.generateKey();
		
		// Initialize plaintexts
		this.plaintexts = new double[] {
				-30000.2,
				-20000.3,
				-10000.1,
				-5000.6,
				-2000.3,
				-1500.7,
				-1000.3,
				-500.5,
				-100,
				-10.8,
				-5.4,
				-1.1,
				0.5,
				1.3,
				5.7,
				10.4,
				100.2,
				500.3,
				1000,
				1500.7,
				2000.2,
				5000.1,
				10000.3,
				20000.4,
				30000.6
		};
		
		// Encrypt data
		ciphertexts = new byte[plaintexts.length][];
		for (int i = 0; i < plaintexts.length; i++) {
			ciphertexts[i] = key.encryptDouble(plaintexts[i]);
		}

		// Print data set
		System.out.println("Data set:");
		System.out.println();
		for (int i = 0; i < plaintexts.length; i++) {
			System.out.println(String.format("%6f => %s", plaintexts[i], toString(ciphertexts[i])));
		}
	}
	
	@Test
	public void testRangeQuery() {
		// Prepare range query
		double minPlaintext = -100;
		double maxPlaintext = 1000;

		System.out.println();
		System.out.println("================================================================================");
		System.out.println("Searching for range:");
		System.out.println();
		System.out.println("Min Plaintext = " + minPlaintext);
		System.out.println("Max Plaintext = " + maxPlaintext);
		// Encrypt range
		byte[] minCiphertext = key.encryptDouble(minPlaintext);
		byte[] maxCiphertext = key.encryptDouble(maxPlaintext);
		
		System.out.println("Min Ciphertext = " + toString(minCiphertext));
		System.out.println("Max Ciphertext = " + toString(maxCiphertext));
		new String(ciphertexts[0], Charset.defaultCharset());
		// Search in ciphertexts
		List<byte[]> results = new ArrayList<>();
		for (int i = 0; i < ciphertexts.length; i++) {
			if (inRange(ciphertexts[i], minCiphertext, maxCiphertext)) {
				results.add(ciphertexts[i]);
			}
		}
		
		// Print encrypted results
		System.out.println();
		System.out.println("================================================================================");
		System.out.println("Ciphertext Results:");
		System.out.println();
		for (byte[] result : results) {
			System.out.println(toString(result));
		}
		
		// Validate result set size
		Assert.assertEquals(results.size(), 11);
		
		// Print plaintext results
		System.out.println();
		System.out.println("================================================================================");
		System.out.println("Plaintext Results:");
		System.out.println();
		for (byte[] result : results) {
			System.out.println(String.format("%6d", key.decryptDouble(result)));
		}
		
		// Validate results
		for (byte[] result : results) {
			double value = key.decryptDouble(result);
			Assert.assertTrue(value >= minPlaintext && value <= maxPlaintext);
		}
	}

	protected static String toString(byte[] bytes) {
		StringBuilder s = new StringBuilder();
		for (byte b : bytes) { s.append(String.format("%02x", Byte.toUnsignedInt(b))); }
		return s.toString();
	}
	
	protected static int compare(byte[] c1, byte[] c2) {
		for (int i = 0; i < c1.length; i++) {
			int b1 = Byte.toUnsignedInt(c1[i]);
			int b2 = Byte.toUnsignedInt(c2[i]);
			if (b1 < b2) { return -1; }
			else if (b1 > b2) { return 1; }
		}
		return 0;
	}
	
	protected static boolean inRange(byte[] value, byte[] min, byte[] max) {
		return compare(value, min) >= 0 && compare(value, max) <= 0;
	}
}

littleniannian avatar Jul 23 '24 09:07 littleniannian

@littleniannian You are right... Must be an issue in float encoding

aymanmadkour avatar Jul 23 '24 09:07 aymanmadkour