s0l0ist / node-seal Goto Github PK
View Code? Open in Web Editor NEWHomomorphic Encryption for TypeScript or JavaScript - Microsoft SEAL
Home Page: https://s0l0ist.github.io/node-seal/
License: MIT License
Homomorphic Encryption for TypeScript or JavaScript - Microsoft SEAL
Home Page: https://s0l0ist.github.io/node-seal/
License: MIT License
Maybe you can create a tutorial blog or video, to explain how to use the sandbox page that you created:
https://morfix.io/
I've tried to use it but was not able to get it to work.
It's not clear how to use the interface.
Can we rotate keys without decrypting the data? What is the steps to rotate keys without touching the data?
Hi,
Taking the example from here https://github.com/morfix-io/node-seal/blob/main/FULL-EXAMPLE.md
I have changed the code so that instead of specifying the parameters I do:
let coeffModulus = seal.CoeffModulus.BFVDefault(polyModulusDegree)
// Create a suitable set of CoeffModulus primes
parms.setCoeffModulus(
coeffModulus
)
If I set the polyModulusDegree to 2048
I get
decodedArray Int32Array(2048) [
2, 4, 6, 8, 10, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
... 1948 more items
]
4096 I get
decodedArray Int32Array(4096) [
2, 4, 6, 8, 10, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
... 3996 more items
]
but adjusting it for 1024 bit and using the default function for coeff modulus seems to cause the output to fail:
1024
decodedArray Int32Array(1024) [
105844, -318666, 353194, 308340, -22466, -280593, -121865,
93239, 161666, 56413, -429374, 274691, 214325, 150437,
-262277, -435923, 175173, 180207, -250189, -183222, -302924,
493734, -39478, 507789, -123179, -10467, -247445, 111902,
446943, -463523, 490017, 45863, -455228, -32028, -308374,
161534, -216214, -57172, 453304, 2499, 266728, -17369,
287119, 20179, 211342, 479885, 442275, 46353, 22520,
-432398, 436056, -26115, -103722, 264451, 256323, 308170,
198784, -325548, 205138, -371934, 56778, 372592, -79392,
59866, 409560, -329666, -188138, -473686, 194220, -251112,
199224, 227037, 117366, -311811, -249313, -96853, 293575,
-325482, -27145, -389919, 1070, -414144, 486298, -375258,
-436172, -100284, -60636, 211476, -268699, 444525, 68176,
-465590, -276743, 69281, -471714, 143503, -443269, 357831,
-348976, 85036,
... 924 more items
]
Any ideas whats going on and how to fix it?
My use case is I want the smallest output size data I can get all the while using homomorphic encryption (I need to send the data over HTTP with the smallest payload).
Full code snippet:
;(async () => {
// Using CommonJS for RunKit
const SEAL = require('node-seal')
const seal = await SEAL()
const schemeType = seal.SchemeType.bfv
const securityLevel = seal.SecurityLevel.tc128
const polyModulusDegree = 1024
const bitSize = 20
const parms = seal.EncryptionParameters(schemeType)
// Set the PolyModulusDegree
parms.setPolyModulusDegree(polyModulusDegree)
let coeffModulus = seal.CoeffModulus.BFVDefault(polyModulusDegree)
// Create a suitable set of CoeffModulus primes
parms.setCoeffModulus(
coeffModulus
)
// Set the PlainModulus to a prime of bitSize 20.
parms.setPlainModulus(
seal.PlainModulus.Batching(polyModulusDegree, bitSize)
)
const context = seal.Context(
parms, // Encryption Parameters
true, // ExpandModChain
securityLevel // Enforce a security level
)
// Set the PolyModulusDegree
parms.setPolyModulusDegree(polyModulusDegree)
if (!context.parametersSet()) {
throw new Error(
'Could not set the parameters in the given context. Please try different encryption parameters.'
)
}
const encoder = seal.BatchEncoder(context)
const keyGenerator = seal.KeyGenerator(context)
const publicKey = keyGenerator.createPublicKey()
const secretKey = keyGenerator.secretKey()
const encryptor = seal.Encryptor(context, publicKey)
const decryptor = seal.Decryptor(context, secretKey)
const evaluator = seal.Evaluator(context)
// Create data to be encrypted
const array = Int32Array.from([1, 2, 3, 4, 5])
// Encode the Array
const plainText = encoder.encode(array)
// Encrypt the PlainText
const cipherText = encryptor.encrypt(plainText)
// Add the CipherText to itself and store it in the destination parameter (itself)
evaluator.add(cipherText, cipherText, cipherText) // Op (A), Op (B), Op (Dest)
// Or create return a new cipher with the result (omitting destination parameter)
// const cipher2x = evaluator.add(cipherText, cipherText)
// Decrypt the CipherText
const decryptedPlainText = decryptor.decrypt(cipherText)
// Decode the PlainText
const decodedArray = encoder.decode(decryptedPlainText)
console.log('decodedArray', decodedArray)
})()
Hi,
I have tried using both plaintext.load (commented below) and encoder.encode to construct a PlainText object that I would be using for encryption. However, it seems that the code isnt executing as when I do a console.log("here2") after said lines, it doesn't go there. Please advise... Btw, init() is used by my other function generateKey (which generates both public and privatekey) and it works fine.
Thanks,
Benjie
async function encrypt(file, keyfromDB) {
await init();
//encode plaintext to be encrypted
let buff = fs.readFileSync("uploads/" + file);
const plaintext = seal.PlainText();
/* let base64data = buff.toString('base64');
console.log(base64data);
plaintext.load(context, base64data);
console.log("here2");*/
const encoder = seal.BatchEncoder(context);
const uint32array = new Uint32Array(buff);
console.log(uint32array);
plaintext = encoder.encode(uint32array);
console.log("here2");`
Apologies - couldnt' work out if I can re-open a ticket that has been closed. (#133)
So continuing the conversation there, basically I have data that is larger than i can store in a a single array (each array can't be bigger than the PolyModulusDegree)
So to start, assuming the parameters are:
const heConfig = {
keySize: 4096,
bitSize: 20
}
then in each array of data to process I can store 4096 bits of data.
With regards to my algorithm then:
for (let i = 0, l = arraysToSend.length; i < l; i++) {
const image3232Chunk = seal.CipherText()
image3232Chunk.load(context, arraysToSend[i]) //load the current image chunk
const encryptedFillArray = seal.CipherText()
encryptedFillArray.load(context, savedFillArray) //encrypted load of zeros to store the result
for (let j = 0, end = kernels.length; j < end; j++) {
const tmp = evaluator.multiplyPlain(image3232Chunk, kernels[j])
evaluator.add(encryptedFillArray, tmp, encryptedFillArray)
}
const send = encryptedFillArray.save()
convEncArray.push(send)
}
image3232Chunk.load(context, arraysToSend[i])
encryptedFillArray.load(context, savedFillArray)
(sendFillArray is an encrypted set of zeros that I am cloning into encryptedFillArray)[0]: 1, 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1, 0, 0, 0, 0, 0, 0, 0, 0, 0...... (to 4096 in total)
[1]: 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1...... (to 4096 in total)
etc, until all 4096 places have been a 1 in an entry.
Reason being, I want to multiply the each set of 9 values of image3232Chunk
by the kernel value (which in practice won't be 1's, thats just for testing) - then its stored in tmp
. Then tmp
is added to encryptedFillArray
- the reason for the zeros will then mean the other values in encryptedFillArray
are not affected during the addition here: evaluator.add(encryptedFillArray, tmp, encryptedFillArray)
I.e adding
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1......
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ....
will not affect the first nine 2s so I can keep adding them and only affecting the correct nine slots.
Then i save that result in convEncArray
and do it again for the next arrayToSend
.
This works nicely except that I can't use a smaller keySize than 4096 because evaluator.add
corrupts the data with smaller key sizes however using 4096 to encrypt the data means I have about half a MB of data to send over HTTP, whereas with 1024 key size, I have about 25kb to send over HTTP.
However I reckon either, I can use a relin key on evaluator.add(encryptedFillArray, tmp, encryptedFillArray)
with a smaller keySize, or a more efficient algorithm to do the addition.
My question then is, is there a "neat" way to add all the tmps
I have together in one go so not to corrupt encrytpedFilleArray
with smaller keys (1024, 2048), or can I relin after every loop round (or somehow work out when to relin so not to do it every time around the loop) and will relin key that I have to send with the request over HTTP just make it as big and therefore be pointless?
Hopefully that makes some more sense?
Thank you!
Hey. I'm trying to add two 'vectors' :
const v1 = [0, 0, 1]
const v2 = [1, 0, 0]
which in ciphertext are ciphertext1
and ciphertext1
, respectively.
This is the code use to add them:
const evaluator = Morfix.Evaluator({
context: context
})
const cipherTextResult = Morfix.CipherText()
evaluator.add({
a: cipherText1,
b: cipherText2,
destination: cipherTextResult
})
// Create a new plainText variable to store the decrypted cipherText
const decryptedPlainText = Morfix.PlainText()
decryptor.decrypt({
cipherText: cipherTextResult,
plainText: decryptedPlainText
})
// Create a c++ vector to store the decoded result
const decodeVector = Morfix.Vector({array: new Int32Array(3) })
// Decode the plaintext to the c++ vector
encoder.decodeVectorInt32({
plainText: decryptedPlainText,
vector: decodeVector
})
console.log('decodeVector.size', decodeVector.size)
// Convert the vector to a JS array
const decryptedArray = decodeVector.toArray()
console.log('decryptedArray', decryptedArray)
which outputs:
decodeVector.size 4099
decryptedArray Int32Array [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
... 3999 more items
]
However, i require the result in the form [1, 0, 1]
. How do I get that ?
I am trying to substract rB from rA, but I'm having an issue with the scales.
The cipherTextSxy was previously relinearized and rescaled in other steps of the code.
I have already tried to set rA's scale to rB's scale but then we'd lose the real value of rA and the substraction, even though it would not fail, would not be realistic. I have also tried to turn N's plaintext to a ciphertext and work with the evaluator.multiply() function, but there is also an scale issue with that approach.
// Turn N into a PlainText
const NPlaintext = seal.PlainText();
const NArray = Float64Array.from([N]);
encoder.encode(NArray, scale, NPlaintext);
// Compute rA = N*Sxy
let rA = seal.CipherText();
evaluator.multiplyPlain(cipherTextSxy, NPlaintext, rA);
evaluator.relinearize(rA, relinKey);
evaluator.rescaleToNext(rA);
// Compute rB = Sx*Sy
let rB = seal.CipherText();
evaluator.multiply(cipherTextSx, cipherTextSy, rB);
evaluator.relinearize(rB, relinKey);
evaluator.rescaleToNext(rB);
// Compute rAB = rA - rB
let rAB = seal.CipherText();
//rA.setScale(rB.scale);
console.log(`Scale A: ${rA.scale}`);
console.log(`Scale B: ${rB.scale}`);
console.log(`Scale AB: ${rAB.scale}`);
evaluator.sub(rA, rB, rAB);
/**************************************************
* SCHEME PARAMETERS
**************************************************/
const schemeType = seal.SchemeType.ckks;
const securityLevel = seal.SecurityLevel.tc128;
const polyModulusDegree = 8192;
const bitSizes = [60, 40, 40, 60];
const bitSize = 40;
const parms = seal.EncryptionParameters(schemeType);
/**************************************************
* POLY MODULUS DEGREE
**************************************************/
parms.setPolyModulusDegree(polyModulusDegree);
/**************************************************
* COEFF MODULUS PRIMES
**************************************************/
parms.setCoeffModulus(
seal.CoeffModulus.Create(polyModulusDegree, Int32Array.from(bitSizes))
);
/**************************************************
* CREATE CONTEXT
**************************************************/
const context = seal.Context(
parms, // Encryption Parameters
true, // ExpandModChain
securityLevel // Enforce a security level
);
Hi, I am new in using SEAL, when i use following parameters
const polyModulusDegree = 4096
const bitSizes = [36,36,37]
const bitSize = 20, the response output size is around 180kb,
I need an output less than or equal to 128 kb, is there any way to compress the encrypted result?
Hey ๐
First off. Thanks for a great package. It has really made it easy and fairly trivial to get started using FHE in my application.
According to this conversation, the reference implemention has a switch_key_inplace method.
I was wondering if you have implemented this in any capacity in this implementation?
Best,
async function contextInit() {
const SEAL = require('node-seal')
const seal = await SEAL()
const schemeType = seal.SchemeType.bfv
const securityLevel = seal.SecurityLevel.tc128
const polyModulusDegree = 4096
const bitSizes = [36, 36, 37]
const bitSize = 20
const encParms = seal.EncryptionParameters(schemeType)
encParms.setPolyModulusDegree(polyModulusDegree)
encParms.setCoeffModulus(seal.CoeffModulus.Create(polyModulusDegree, Int32Array.from(bitSizes)))
encParms.setPlainModulus(seal.PlainModulus.Batching(polyModulusDegree, bitSize))
const context = seal.Context(encParms, true, securityLevel)
if (!context.parametersSet()) {
throw new Error('Could not set the parameters in the given context. Please try different encryption parameters.')
}
return context
}
module.exports.context = contextInit()
(async () => {
const SEAL = require('node-seal')
const seal = await SEAL()
const context = await require('./main').context
const key = seal.KeyGenerator(context)
})()
BindingError: Expected null or instance of SEALContext, got an instance of SEALContext
It's can use context(create from another seal) with another seal ?
Is it possible to store the Public key and secret key in a vault. I cant do that as it is returning a complete object as below
secret key {
instance: [Getter],
inject: [Function: inject],
delete: [Function: delete],
save: [Function: save],
saveArray: [Function: saveArray],
load: [Function: load],
loadArray: [Function: loadArray],
copy: [Function: copy],
clone: [Function: clone],
move: [Function: move]
}
I'm trying to play around with the hosted sandbox, but no matter what I do, I always get the error encrypted1 is not valid for encryption parameters
. Before running anything, I generated all the necessary parts. Maybe I am doing something wrong - is there some guide how to use the sandbox?
When running on MacOS Big Sur the command npm run seal:build:bench
it generates the following error:
> [email protected] seal:build:bench
> export BUILD_BENCH=ON && export THROW_ON_TRANSPARENT=ON && npm run seal:cmake && npm run seal:make
> [email protected] seal:cmake
> bash scripts/seal-cmake.sh
scripts/seal-cmake.sh: line 4: ./emsdk_env.sh: No such file or directory
scripts/seal-cmake.sh: line 18: emcmake: command not found
It seems like the script file emsdk_env.sh
is missing from the repository.
I am using the security level SecurityLevel.tc128 and want to use polyModulusDegree=1024
what combinations of bitSizes [-,-,-] can i have and what should be the bitsize?
I need to change scale of CipherText
And CipherText.scale of node-seal
is read-only property.
But MS-SEAL has setScale Function.
I wonder if you could help me by support CipherText.setScale in this great library?
Thank you!
Pretty self explanatory. It'd be awesome to have .d.ts for the project. This would also open up usage in deno.
Currently, I don't see any KMS support LWE Keys. How does it currently manage to store and retrieve keys?
Is there any other better way to handle key management? including Rotations?
Describe the bug
Cannot import node-seal from browser (not node-js)
To Reproduce
Trying import node-seal from browser, my Javascript can not import node-seal.
(Based on Full example so other lines are same. And works perfectly in Node.js)
main.html
....<script type="module" src="/main.js" ></script>....
main.js
(async () => { import SEAL from 'node-seal'; ......
And I got an error like: Uncaught SyntaxError: Unexpected identifier (at main.js:12:12)
So I tried other methods to import node-seal but could not solve it.
tried: const SEAL = require('node-seal');
error: Uncaught (in promise) ReferenceError: require is not defined
tried: import SEAL from 'node-seal/throws_wasm_web_umd'
error: Failed to resolve module specifier "node-seal/throws_wasm_web_umd". Relative references must start with either "/", "./", or "../".
tried: import {SEAL} from './node_modules/node-seal/throws_wasm_node_umd.js'
error: The requested module './node_modules/node-seal/throws_wasm_node_umd.js' does not provide an export named 'SEAL' (at main.js:1:9)
Is there something I missed??
thanks.
Environment
I have a linear regression system working with basic security level tc128. I am trying to switch to tc192 to explore how latency will be affected. To briefly explain what the system does, as the titles are in spanish, in the first div you introduce X and Y axis values and by the Least Squares Method you should get the equation parameters. With the second div, you can compute the prediction.
With tc128 it works perfectly fine but, with tc192, the decrypted data is wrong. I am not sure if the bit sizes I have introduced are not correct or what the issue is here. I have already tried changing the bit sizes, and also swithing to polymodulus degree 16384 and changing the bit sizes accordingly and nothing seems to work. The sum of the bit sizes with tc192 and polymodulus of 8192 is 145, bellow the enforced limit.
Hey. I'm trying to load a previously saved public key (created using keyGenerator.getPublicKey()
) from a .csr file. I'm using the load(context, encoded)
function from the public-key.js, but i am running into trouble.
When using the associated save()
method, i just used it as publicKey.save()
on my previously defined public key. But what exactly do i call the load method on ? I tried using the documentation to solve my dilemma but i'm still stuck. Any guidance would be appreciated.
I want to use an instance like context, publicKey, secretKey and etc. with another device that has own SEAL. but when I export instance to another device and use it with SEAL in each device it not work
have a specific method to share instance like context to other device or other environment that instance still work with other environment ?
this diagram would help to explain this system.
description:
device1: config context, publicKey, secretKey
device2: use context and publicKey from device1 to create Encryptor and encrypt plainText to cipherText
device3: use context from device1 with Evaluator to process with cipherText
device4: use context and secretKey from device1 with Decrypter cipherText to plainText
ps. all device use own SEAL ==> [from require ('node-seal')]
Hello,
I am using CKKS and I would like to compare two chipertext to see if the first one is greater than a certain threshold.
I have integer values as a message.
For example, I have Enc(832) and I would check if it is greater than Enc(850).
How could I accomplish this?
Thank you.
I get a error in the browser dialog box that says:
TypeError: Cannot read property 'BFV' of undefined
this is the only part of the code that has BFV:
const parms = Morfix.EncryptionParameters({
schemeType: Morfix.SchemeType.BFV
})
can you help me out ?
hey so I am very close to something that now works fully which I'm really pleased with. To be honest, most of the work has been converting 2D arrays to 1D arrays.
The one last thing I'm experiencing is:
console.log("kernels length", kernels.length)
for (let i = 0, l = arraysToSend.length; i < l; i++) {
const image3232Chunk = seal.CipherText()
image3232Chunk.load(context, arraysToSend[i]) //load the current image chunk
const encryptedFillArray = seal.CipherText()
encryptedFillArray.load(context, savedFillArray) //encrypted load of zeros to store the result
for (let j = 0, end = kernels.length; j < end; j++) {
const tmp = evaluator.multiplyPlain(image3232Chunk, kernels[j])
evaluator.add(encryptedFillArray, tmp, encryptedFillArray)
}
const send = encryptedFillArray.save()
convEncArray.push(send)
}
In this case the first line prints: kernels length 114
If I use
const heConfig = {
keySize: 4096,
bitSize: 20
}
then I get the correct value after I decrypt. However 2048
or 1024
gives me garbage out. My thinking is my multiplyPlain and add are resulting in too much entropy in the data and its causing garbage when I decrypt. My initial thinking is I am applying too many calculations to the encryptedFillArray (my final resulting array for each iteration) and its becoming a load of mess when the keySize is too small - I think tmp will not be the problem here.
What options do I have to allow myself to use smaller key sizes?
my first guess is relinearize but I think the galois keys are very big and I'd rather not send one over the wire, so then I thought could I create an array of encryptFillArray[...]s and then add them back together afterwards or something, rather than apply the maths on the same one again and again?
The reason I want to use smaller key sizes is because I want to send the base64 exported cipher texts (.save()
) over HTTP and smaller key sizes means smaller amounts of data to send.
also...
UJNRELATED:
Final and unrelated question, I'm actually trying to calculate the average - I need to end up with the multiplication of each value, then sum them and divide by the number of values in kernels[x], but I am not sure how to do that in a 1D array - i.e choosing the correct elements (only a subset of the values in the cipherText array) and secondly I am not sure if I can do division at all (even multiply by inverse....?) so that I end up with 1 value rather than kernels[j].length values (i'm doing gaussian blur on the data which is an average. I may have to do this part after decryption I suspect...?
Thanks!
I have been using the library to build an application and everything seemed to be working fine, until I encountered an error as Error:loaded SEALHeader is invalid. Are any recent changes commited to the library causing this?
Getting the above error when I am doing the following
cipherText.load(context,encryptedSum) cipherText is an instance of Morfix.CipherText()
I'm wondering about the typical example of taking someone's salary, and checking if it's below a certain amount. This should be quite easy doing r = salary - threshold
, where if r < 0
, it doesn't meet the threshold, but how do I express this? I can construct the necessary machinery no problem for everything but the comparison.
Hello,
I try to use the Microsoft Seal librairie and your librairie to build an application.
In my situtation, the api generate the key and the front need to load the public key to send the ciphertext to the api. But when I want to load the string in the key, I have an error : "Error: ciphertext data is invalid"
My api is in C# witth the Microsoft nuget (https://www.nuget.org/packages/Microsoft.Research.SEALNet) version 3.6.4
And my front use angular with your package.
When I export the public key from the api, I use the save function and convert the UTF16 string in UTF8 string (I read that could be a source of issue) :
// Transform public Key in a UTF16 string
MemoryStream stream = new MemoryStream();
publicKey.Save(stream, ComprModeType.ZSTD);
stream.Seek(0, SeekOrigin.Begin);
string utf16String = Convert.ToBase64String(stream.ToArray());
// Get UTF16 bytes and convert UTF16 bytes to UTF8 bytes
byte[] utf16Bytes = Encoding.Unicode.GetBytes(utf16String);
byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes);
// Fill UTF8 bytes inside UTF8 string
for (int i = 0; i < utf8Bytes.Length; i++)
{
// Because char always saves 2 bytes, fill char with 0
byte[] utf8Container = new byte[2] { utf8Bytes[i], 0 };
result += BitConverter.ToChar(utf8Container, 0);
}
Next I imagine build the context with the same parameter :
const securityLevel = seal.SecurityLevel.tc128
const bitSizes = [36, 36, 37]
const bitSize = 20
const schemeType = seal.SchemeType.bfv;
const parms = seal.EncryptionParameters(schemeType)
// Set the PolyModulusDegree
parms.setPolyModulusDegree(polyModulusDegree)
// Create a suitable set of CoeffModulus primes
parms.setCoeffModulus(
seal.CoeffModulus.Create(polyModulusDegree, Int32Array.from(bitSizes))
)
// Set the PlainModulus to a prime of bitSize 20.
parms.setPlainModulus(
seal.PlainModulus.Batching(polyModulusDegree, bitSize)
)
const context = seal.Context(
parms, // Encryption Parameters
true, // ExpandModChain
securityLevel // Enforce a security level
)
And when it's the time to load the key with this :
var publicKey: PublicKey = seal.PublicKey()
publicKey.load( context, publicKeystring)
"Error: ciphertext data is invalid"
I read you are supporting Microsoft Seal 3.6.4, so I would like some advises to understand what is the problem.
The second parameter of the exponential function can only be a positive integer, not 0.5.
Thank you very much!
Can I generate a single secret (symmetric key encryption) rather than assymetric key encryption (public/private) using node-seal? I understand HE supports this but not sure if node-seal does?
Hi guys, I need some help.
I'm using this repository to perform great BVF operations, it's amazing!
When I use the entire lib to perform all operations works fine, but is possible to perform addition operations outside the lib? How can I export 2 ciphertexts in a way that I can perform a external addition (I should execute this into another programming language and restricted hardware)?
My SEAL config:
const schemeType = seal.SchemeType.bfv
const polyModulusDegree = 4096
const bitSize = 20
let parms = seal.EncryptionParameters(schemeType)
parms.setPolyModulusDegree(polyModulusDegree)
parms.setCoeffModulus(seal.CoeffModulus.BFVDefault(polyModulusDegree));
parms.setPlainModulus(seal.PlainModulus.Batching(polyModulusDegree, bitSize));
The result of ciphertext.saveArray()
:
Uint8Array(88518) [
94, 161, 16, 4, 1, 2, 0, 0, 198, 89, 1, 0,
0, 0, 0, 0, 40, 181, 47, 253, 160, 97, 0, 2,
0, 156, 202, 10, 204, 150, 13, 52, 119, 156, 167, 65,
60, 254, 25, 4, 42, 4, 70, 70, 88, 164, 155, 79,
189, 172, 170, 221, 139, 98, 47, 74, 154, 185, 225, 42,
183, 135, 2, 0, 2, 0, 16, 0, 240, 63, 1, 0,
94, 161, 16, 4, 24, 64, 181, 55, 39, 69, 8, 0,
0, 0, 24, 50, 145, 30, 11, 0, 0, 0, 121, 37,
162, 6, 13, 0,
... 88418 more items
]
Sorry if this is a primary question, I'm not a cipher expert
Thanks!
After I've created fresh project with
npx react-native init project-name --template react-native-template-typescript
and installing react-native-get-random-values + adding
global.document = {}
into the code, I'm constantly getting this error: Possible Unhandled Promise Rejection (id: 0):
ReferenceError: Can't find variable: WebAssembly
I'm currently developing on Windows; I've tried to install react-native-wasm, which doesnt work also (complains about not finding react-native-wasm/src/index.js, which exists)
package.json:
{
"name": "project-name",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
},
"dependencies": {
"node-seal": "^4.5.5",
"react": "17.0.1",
"react-native": "0.64.0",
"react-native-get-random-values": "^1.7.0",
"react-native-wasm": "^0.1.3"
},
"devDependencies": {
"@babel/core": "^7.12.9",
"@babel/runtime": "^7.12.5",
"@react-native-community/eslint-config": "^2.0.0",
"@types/jest": "^26.0.20",
"@types/react-native": "^0.64.0",
"@types/react-test-renderer": "^16.9.2",
"babel-jest": "^26.6.3",
"eslint": "^7.14.0",
"jest": "^26.6.3",
"metro-react-native-babel-preset": "^0.64.0",
"react-test-renderer": "17.0.1",
"typescript": "^3.8.3"
},
"resolutions": {
"@types/react": "^17"
},
"jest": {
"preset": "react-native",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
]
}
}
Maybe Windows is the main issue, but I'm not sure.
How to fix this? Any ideas?
UPD: also there is a warning no native wasm support detected that appears before promise gets rejected
Heya, I understand that you're working on this with SIMD in mind so considering that SIMD is coming to webassembly in Chrome and Firefox are you going to implement it or has it already been done?
When trying to run add two numbers twice with same public key and private key, I am getting different strings when computing cipherText.saev() as shown below.
evaluator.add(cipherText, cipherText1, cipherText)
console.log('cipherText----->',cipherText.save())
Hi,
I found your blogs and decided to give your code a go. Pretty cool stuff. Got BFV working, and I wanted to have a go at CKSS.
One issue, I'm not sure you are aware of, or whether it was intentional within the sandbox, is if you just press all the create
buttons (which my guess was that would create a successful default setup, fails with an error of Encrypted1 is not valid for encryption parameters
- maybe this is not a bug but from the blogs it seems that it should work as a default setup and as it doesn't makes it quite tricky as the generated code examples don't then work.... Anyway....
Using the documentation, I put together the following for CKKS
(async () => {
const SEAL = require('node-seal')
const seal = await SEAL()
const schemeType = seal.SchemeType.ckks
// const schemeType = seal.SchemeType.bfv
const securityLevel = seal.SecurityLevel.tc128
const polyModulusDegree = 4096
// const bitSizes = [36, 36, 37]
const bitSizes = [46,16,46]
const bitSize = 20
const encParms = seal.EncryptionParameters(schemeType)
// Set the PolyModulusDegree
encParms.setPolyModulusDegree(polyModulusDegree)
// Create a suitable set of CoeffModulus primes
encParms.setCoeffModulus(
seal.CoeffModulus.Create(polyModulusDegree, Int32Array.from(bitSizes))
)
// Create a new Context
const context = seal.Context(
encParms, // Encryption Parameters
true, // ExpandModChain
securityLevel // Enforce a security level
)
if (!context.parametersSet()) {
throw new Error(
'Could not set the parameters in the given context. Please try different encryption parameters.'
)
}
// Create a new KeyGenerator (creates a new keypair internally)
const keyGenerator = seal.KeyGenerator(context)
const secretKey = keyGenerator.secretKey()
const publicKey = keyGenerator.createPublicKey()
const relinKey = keyGenerator.createRelinKeys()
// Generating Galois keys takes a while compared to the others
const galoisKey = keyGenerator.createGaloisKeys()
// Creating PlainText(s)
const plainA = seal.PlainText()
const plainB = seal.PlainText()
// Creating CipherText(s)
const cipherA = seal.CipherText()
const cipherB = seal.CipherText()
// Create an Evaluator which will allow HE functions to execute
const evaluator = seal.Evaluator(context)
// Or a CKKSEncoder (only CKKS SchemeType)
const encoder = seal.CKKSEncoder(context)
// Create an Encryptor to encrypt PlainTexts
const encryptor = seal.Encryptor(context, publicKey)
// Create a Decryptor to decrypt CipherTexts
const decryptor = seal.Decryptor(context, secretKey)
const plainTextA = encoder.encode(Float64Array.from([1.0, 2.0, 3.0]),1.0) //what is the scale factor here?
const result = encoder.decode(plainTextA) //why is plainTextA void here?
console.log('test result', result)
// Encrypt a PlainText
const cipherTextA = encryptor.encrypt(plainTextA)
// Add CipherText B to CipherText A and store the sum in a destination CipherText
const cipherTextD = seal.CipherText()
evaluator.add(cipherTextA, cipherTextA, cipherTextD)
// Decrypt a CipherText
const plainTextD = decryptor.decrypt(cipherTextD)
const decoded = encoder.decode(
plainTextD,
true // Can be omitted since this defaults to true.
)
console.log("len decoded", decoded.length)
console.log('decoded', decoded)
})()
This almost wrks, however I think I am doing something wrong at the line const plainTextA = encoder.encode......
but i am struggling to work out what. It maybe that I am setting the scale on the encoding incorrectly, I saw in the docs you have Math.pow(2, 20)
so perhaps I have completely missed what its for, but I have not managed to get the above to add the cipher to itself, which worked fine with BFV.
For context, I am trying to create a calculation that I can visually see it takes a long time compared to the decrypted similar calculation and then check the match. My thinking is lots of multiplications - but I am wondering if the batchEncoder will actually make it too efficient to see visually a slow down when encrypting and then doing the maths?
I am aware that CKKS is an approximation so not sure if i will actually be able to compare the results of the plain and cipher'd calculations, but perhaps with some rounding I will be able to.
Anyway, thanks for this project, very cool!
When I am trying to test the load on my application which hits the service number of times, I get the following error
RangeError: WebAssemblyMemory(): could not allocate memory.
Is there any way I can fix this memory allocation ?
Here is my code:
(async () => {
// ES6 or CommonJS
// import { Seal } from 'node-seal'
// const { Seal } = require('node-seal')
// Using CommonJS for RunKit
const { Seal } = require('node-seal')
const Morfix = await Seal
const parms = Morfix.EncryptionParameters({
schemeType: Morfix.SchemeType.BFV
})
parms.setPolyModulusDegree({
polyModulusDegree: 8192
})
// Create a suitable vector of CoeffModulus primes
parms.setCoeffModulus({
coeffModulus: Morfix.CoeffModulus.Create({
polyModulusDegree: 8192,
bitSizes: Morfix.Vector({array: new Int32Array([36,36,37]) }),
//securityLevel: Morfix.SecurityLevel.tc128
})
})
// Set the PlainModulus to a prime of bitSize 20.
parms.setPlainModulus({
plainModulus: Morfix.PlainModulus.Batching({
polyModulusDegree: 8192,
bitSize: 20
})
})
const context = Morfix.Context({
encryptionParams: parms,
expandModChain: true,
securityLevel: Morfix.SecurityLevel.tc128
})
if (!context.parametersSet) {
throw new Error('Could not set the parameters in the given context. Please try different encryption parameters.')
}
const encoder = Morfix.IntegerEncoder({context})
const keyGenerator = Morfix.KeyGenerator({
context: context
})
const publicKey = keyGenerator.getPublicKey()
const secretKey = keyGenerator.getSecretKey()
const encryptor = Morfix.Encryptor({
context: context,
publicKey: publicKey
})
const decryptor = Morfix.Decryptor({
context: context,
secretKey: secretKey
})
// Create a plainText variable and encode the vector to it
const plainText = Morfix.PlainText()
encoder.encodeInt32({value: 6, destination: plainText})
})()
The error message is
'function IntegerEncoder.encodeInt32 called with 2 arguments, expected 1 args!'
Not quite sure how to encode an integer. I didn't find any instructions to encode and decode integer, so I followed the API doc and gave it 1 argument.
Hello, I'm not sure if this is the right place to ask this but I've been using your package for a small university project where i'm generating individual private keys for new users who are joining our system. For some unknown reason i'm generating the same private key but the public key does vary. Is there something that i'm missing? Would really appreciate your help. Thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.