Files
Thomas Montaigu 39fbc20360 fix(js): catch undefined variant using Option<>
In the JS ShortintParametersName, users could
make typo in the variant used e.g:
`ShortintParametersName.PARAM_MESSAGE_2_CARRY128`

In JS this returns `undefined` which is then later casted to an
int and it becomes 0, leading to match the first variant

We modify the input to receive an `Option<ShortintParametersName>`
as it seems to allow us to catch the `undefined` and return a proper
error
2025-10-20 14:37:36 +02:00

303 lines
10 KiB
JavaScript

const crypto = require("crypto");
const test = require("node:test");
const assert = require("node:assert").strict;
const {
Boolean,
Shortint,
BooleanParameterSet,
ShortintParametersName,
ShortintParameters,
shortint_params_name,
} = require("../pkg");
function genRandomBigIntWithBytes(byteCount) {
return BigInt("0x" + crypto.randomBytes(byteCount).toString("hex"));
}
test("invalid variant of ShortintParametersName", (t) => {
assert.throws(() => {
shortint_params_name(ShortintParametersName.IDontExist);
});
assert.throws(() => {
new ShortintParameters(ShortintParametersName.IDontExist);
});
});
// Boolean tests
test("boolean_encrypt_decrypt", (t) => {
let params = Boolean.get_parameters(BooleanParameterSet.Default);
let cks = Boolean.new_client_key(params);
let ct = Boolean.encrypt(cks, true);
let serialized_cks = Boolean.serialize_client_key(cks);
let deserialized_cks = Boolean.deserialize_client_key(serialized_cks);
let serialized_ct = Boolean.serialize_ciphertext(ct);
let deserialized_ct = Boolean.deserialize_ciphertext(serialized_ct);
let decrypted = Boolean.decrypt(deserialized_cks, deserialized_ct);
assert.deepStrictEqual(decrypted, true);
let sks = Boolean.new_compressed_server_key(cks);
let serialized_sks = Boolean.serialize_compressed_server_key(sks);
let deserialized_sks =
Boolean.deserialize_compressed_server_key(serialized_sks);
// No equality tests here, as wasm stores pointers which will always differ
});
test("boolean_compressed_encrypt_decrypt", (t) => {
let params = Boolean.get_parameters(BooleanParameterSet.Default);
let cks = Boolean.new_client_key(params);
let ct = Boolean.encrypt_compressed(cks, true);
let serialized_cks = Boolean.serialize_client_key(cks);
let deserialized_cks = Boolean.deserialize_client_key(serialized_cks);
let serialized_ct = Boolean.serialize_compressed_ciphertext(ct);
let deserialized_ct =
Boolean.deserialize_compressed_ciphertext(serialized_ct);
let decompressed_ct = Boolean.decompress_ciphertext(deserialized_ct);
let decrypted = Boolean.decrypt(deserialized_cks, decompressed_ct);
assert.deepStrictEqual(decrypted, true);
});
test("boolean_public_encrypt_decrypt", (t) => {
let params = Boolean.get_parameters(BooleanParameterSet.Default);
let cks = Boolean.new_client_key(params);
let pk = Boolean.new_public_key(cks);
let serialized_pk = Boolean.serialize_public_key(pk);
let deserialized_pk = Boolean.deserialize_public_key(serialized_pk);
let ct = Boolean.encrypt_with_public_key(deserialized_pk, true);
let serialized_ct = Boolean.serialize_ciphertext(ct);
let deserialized_ct = Boolean.deserialize_ciphertext(serialized_ct);
let decrypted = Boolean.decrypt(cks, deserialized_ct);
assert.deepStrictEqual(decrypted, true);
});
test("boolean_deterministic_keygen", (t) => {
const TEST_LOOP_COUNT = 128;
let seed_high_bytes = genRandomBigIntWithBytes(8);
let seed_low_bytes = genRandomBigIntWithBytes(8);
let params = Boolean.get_parameters(BooleanParameterSet.Default);
let cks = Boolean.new_client_key_from_seed_and_parameters(
seed_high_bytes,
seed_low_bytes,
params,
);
let other_cks = Boolean.new_client_key_from_seed_and_parameters(
seed_high_bytes,
seed_low_bytes,
params,
);
for (let i = 0; i < TEST_LOOP_COUNT; i++) {
let ct_true = Boolean.encrypt(cks, true);
let decrypt_true_other = Boolean.decrypt(other_cks, ct_true);
assert.deepStrictEqual(decrypt_true_other, true);
let ct_false = Boolean.encrypt(cks, false);
let decrypt_false_other = Boolean.decrypt(other_cks, ct_false);
assert.deepStrictEqual(decrypt_false_other, false);
}
});
// Shortint tests
test("shortint_encrypt_decrypt", (t) => {
let params_name =
ShortintParametersName.PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let params = new ShortintParameters(params_name);
let cks = Shortint.new_client_key(params);
let ct = Shortint.encrypt(cks, BigInt(3));
let serialized_cks = Shortint.serialize_client_key(cks);
let deserialized_cks = Shortint.deserialize_client_key(serialized_cks);
let serialized_ct = Shortint.serialize_ciphertext(ct);
let deserialized_ct = Shortint.deserialize_ciphertext(serialized_ct);
let decrypted = Shortint.decrypt(deserialized_cks, deserialized_ct);
assert.deepStrictEqual(decrypted, BigInt(3));
let sks = Shortint.new_compressed_server_key(cks);
let serialized_sks = Shortint.serialize_compressed_server_key(sks);
let deserialized_sks =
Shortint.deserialize_compressed_server_key(serialized_sks);
// No equality tests here, as wasm stores pointers which will always differ
// Encryption using small keys
let params_name_small =
ShortintParametersName.V1_5_PARAM_MESSAGE_2_CARRY_2_PBS_KS_GAUSSIAN_2M128;
let params_small = new ShortintParameters(params_name_small);
let cks_small = Shortint.new_client_key(params_small);
let ct_small = Shortint.encrypt(cks_small, BigInt(3));
let serialized_ct_small = Shortint.serialize_ciphertext(ct_small);
let deserialized_ct_small =
Shortint.deserialize_ciphertext(serialized_ct_small);
let decrypted_small = Shortint.decrypt(cks_small, deserialized_ct_small);
assert.deepStrictEqual(decrypted_small, BigInt(3));
});
test("shortint_compressed_encrypt_decrypt", (t) => {
let params_name =
ShortintParametersName.PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let params = new ShortintParameters(params_name);
let cks = Shortint.new_client_key(params);
let ct = Shortint.encrypt_compressed(cks, BigInt(3));
let serialized_cks = Shortint.serialize_client_key(cks);
let deserialized_cks = Shortint.deserialize_client_key(serialized_cks);
let serialized_ct = Shortint.serialize_compressed_ciphertext(ct);
let deserialized_ct =
Shortint.deserialize_compressed_ciphertext(serialized_ct);
let decompressed_ct = Shortint.decompress_ciphertext(deserialized_ct);
let decrypted = Shortint.decrypt(deserialized_cks, decompressed_ct);
assert.deepStrictEqual(decrypted, BigInt(3));
// Encryption using small keys
// We don't have TUniform small params so use previous gaussian ones.
let params_name_small =
ShortintParametersName.V1_5_PARAM_MESSAGE_2_CARRY_2_PBS_KS_GAUSSIAN_2M128;
let params_small = new ShortintParameters(params_name_small);
let cks_small = Shortint.new_client_key(params_small);
let ct_small = Shortint.encrypt_compressed(cks_small, BigInt(3));
let serialized_ct_small = Shortint.serialize_compressed_ciphertext(ct_small);
let deserialized_ct_small =
Shortint.deserialize_compressed_ciphertext(serialized_ct_small);
let decompressed_ct_small = Shortint.decompress_ciphertext(
deserialized_ct_small,
);
let decrypted_small = Shortint.decrypt(cks_small, decompressed_ct_small);
assert.deepStrictEqual(decrypted_small, BigInt(3));
});
test("shortint_public_encrypt_decrypt", (t) => {
let params_name_2_0 =
ShortintParametersName.V1_5_PARAM_MESSAGE_2_CARRY_0_KS_PBS_GAUSSIAN_2M128;
let params_2_0 = new ShortintParameters(params_name_2_0);
let cks = Shortint.new_client_key(params_2_0);
let pk = Shortint.new_public_key(cks);
let ct = Shortint.encrypt_with_public_key(pk, BigInt(3));
let serialized_ct = Shortint.serialize_ciphertext(ct);
let deserialized_ct = Shortint.deserialize_ciphertext(serialized_ct);
let decrypted = Shortint.decrypt(cks, deserialized_ct);
assert.deepStrictEqual(decrypted, BigInt(3));
// Small
let params_name_2_2_small =
ShortintParametersName.V1_5_PARAM_MESSAGE_2_CARRY_2_PBS_KS_GAUSSIAN_2M128;
let params_2_2_small = new ShortintParameters(params_name_2_2_small);
let cks_small = Shortint.new_client_key(params_2_2_small);
let pk_small = Shortint.new_public_key(cks_small);
let ct_small = Shortint.encrypt_with_public_key(pk_small, BigInt(3));
let serialized_ct_small = Shortint.serialize_ciphertext(ct_small);
let deserialized_ct_small =
Shortint.deserialize_ciphertext(serialized_ct_small);
let decrypted_small = Shortint.decrypt(cks_small, deserialized_ct_small);
assert.deepStrictEqual(decrypted_small, BigInt(3));
});
test("shortint_compressed_public_encrypt_decrypt", (t) => {
let params_name =
ShortintParametersName.V1_5_PARAM_MESSAGE_1_CARRY_1_KS_PBS_GAUSSIAN_2M128;
let params = new ShortintParameters(params_name);
let cks = Shortint.new_client_key(params);
let pk = Shortint.new_compressed_public_key(cks);
let serialized_pk = Shortint.serialize_compressed_public_key(pk);
let deserialized_pk =
Shortint.deserialize_compressed_public_key(serialized_pk);
let ct = Shortint.encrypt_with_compressed_public_key(
deserialized_pk,
BigInt(1),
);
let serialized_ct = Shortint.serialize_ciphertext(ct);
let deserialized_ct = Shortint.deserialize_ciphertext(serialized_ct);
let decrypted = Shortint.decrypt(cks, deserialized_ct);
assert.deepStrictEqual(decrypted, BigInt(1));
// Small
let params_name_small =
ShortintParametersName.V1_5_PARAM_MESSAGE_2_CARRY_2_PBS_KS_GAUSSIAN_2M128;
let params_small = new ShortintParameters(params_name_small);
let cks_small = Shortint.new_client_key(params_small);
let pk_small = Shortint.new_compressed_public_key(cks_small);
let serialized_pk_small = Shortint.serialize_compressed_public_key(pk_small);
let deserialized_pk_small =
Shortint.deserialize_compressed_public_key(serialized_pk_small);
let ct_small = Shortint.encrypt_with_compressed_public_key(
deserialized_pk_small,
BigInt(1),
);
let serialized_ct_small = Shortint.serialize_ciphertext(ct_small);
let deserialized_ct_small =
Shortint.deserialize_ciphertext(serialized_ct_small);
let decrypted_small = Shortint.decrypt(cks_small, deserialized_ct_small);
assert.deepStrictEqual(decrypted_small, BigInt(1));
});
test("shortint_deterministic_keygen", (t) => {
const TEST_LOOP_COUNT = 128;
let seed_high_bytes = genRandomBigIntWithBytes(8);
let seed_low_bytes = genRandomBigIntWithBytes(8);
let params_name =
ShortintParametersName.PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let params = new ShortintParameters(params_name);
let cks = Shortint.new_client_key_from_seed_and_parameters(
seed_high_bytes,
seed_low_bytes,
params,
);
let other_cks = Shortint.new_client_key_from_seed_and_parameters(
seed_high_bytes,
seed_low_bytes,
params,
);
for (let i = 0; i < TEST_LOOP_COUNT; i++) {
let random_message = genRandomBigIntWithBytes(4) % BigInt(4);
let ct = Shortint.encrypt(cks, random_message);
let decrypt_other = Shortint.decrypt(other_cks, ct);
assert.deepStrictEqual(decrypt_other, random_message);
}
});