s0l0ist / node-seal

Homomorphic Encryption for TypeScript or JavaScript - Microsoft SEAL
https://s0l0ist.github.io/node-seal/
MIT License
186 stars 22 forks source link

Key.load() with key generate by an api #109

Closed Guillaume-AV closed 3 years ago

Guillaume-AV commented 3 years ago

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.

s0l0ist commented 3 years ago

Hey @Guillaume-AV, when you save any serializable object with node-seal using the .save() function it gets serialized as a base64 string (compression always defaults to use ZSTD for all operations). There's also another method to save/load using a byte-array (Uint8Array) by calling the respective .saveArray() and .loadArray() functions.

I'd start by serializing/deserializing the encryption parameters first before attempting to debug the public key as the serialized output of the encryption parameters can be directly compared since it stores only deterministic data. Then try saving the encryption parameters in node-seal and in your c# application as a plain byte-array and comparing the output. From there, you should be able to identify if there's an issue with the byte-order.

Guillaume-AV commented 3 years ago

Hello, Thanks for the advise. I check parameters and my issue was when I create the CoeffModulus. I used "CoeffModulus.BFVDefault" in C# and I didn't find the bitSizes used in this function. So I adapte the code used with your librairie in C# and I haven't the problem anymore.