Huelse / SEAL-Python

Microsoft SEAL 4.X For Python
MIT License
321 stars 65 forks source link

I/O Error when trying to decrypt a loaded cipher text #122

Open mebner98 opened 2 months ago

mebner98 commented 2 months ago

Im using SEAL-Python for my flask backend and have https://github.com/s0l0ist/node-seal/tree/be71f87c78d20e1471ac0076ed9e50bb276010de for my angular frontend. SEAL is configured the same for both and I send the generated public key from flask to the frontend to encrypt some values. The problem is, when i return the values to flask i can not load the cipher text into flask because i get an I/O Error....

Node-SEAL works with base64 and SEAL-Python with binaries as far i can see Implementation in flask:

def initialize_seal():
    parms = EncryptionParameters(scheme_type.ckks)
    poly_modulus_degree = 4096
    parms.set_poly_modulus_degree(poly_modulus_degree)
    parms.set_coeff_modulus(CoeffModulus.Create(poly_modulus_degree, [46, 16, 46]))

    context = SEALContext(parms, True, sec_level_type.tc128)
    ckks_encoder = CKKSEncoder(context)

    return context, ckks_encoder
def get_seal_decryptor(context, secret_key):
    return Decryptor(context, secret_key)
 ...
        context, ckks_encoder = initialize_seal()
        secret_key = SecretKey()
        secret_key.load(context, "pk.bin")
        decryptor = get_seal_decryptor(context, secret_key)

        # Decode the Base64 string back to binary
        answer_checked_cipher_bytes = base64.b64decode(answer_checked_cipher_string)
        # Create a new Ciphertext object and load the binary data
        answer_checked_cipher = Ciphertext()
        answer_checked_cipher.load(context, answer_checked_cipher_bytes) --> RuntimeError: I/O error

Angular configuration:

 private async initializeSeal(publicKeyBytes?: any) {
    this.sealInstance = await SEAL();
    const schemeType = this.sealInstance.SchemeType.ckks
    const securityLevel = this.sealInstance.SecurityLevel.tc128
    const polyModulusDegree = 4096
    const bitSizes = [46, 16, 46]

    const parms = this.sealInstance.EncryptionParameters(schemeType)

    parms.setPolyModulusDegree(polyModulusDegree);
    parms.setCoeffModulus(
      this.sealInstance.CoeffModulus.Create(polyModulusDegree, Int32Array.from(bitSizes))
    )

    // Create SEALContext
    this.context = this.sealInstance.Context(
      parms, // Encryption Parameters
      true, // ExpandModChain
      securityLevel // Enforce a security level
    )

    if (publicKeyBytes) {
      this.publicKey = this.sealInstance.PublicKey();
      let binaryString = '';
      for (let i = 0; i < publicKeyBytes.length; i++) {
        binaryString += String.fromCharCode(publicKeyBytes[i]);
      }
      // Convert the binary string to Base64
      const base64String = btoa(binaryString);
      this.publicKey.load(this.context, base64String);
...
public async encryptSealValues(values: Float64Array, publicKeyBytes?: any): Promise<string> {
    await this.initializeSeal(publicKeyBytes);
    const scale = Math.pow(2, 40);
    const plainText = this.sealInstance.PlainText();
    this.encoder.encode(values, scale, plainText);
    const cipherText = this.sealInstance.CipherText();
    this.encryptor.encrypt(plainText, cipherText);

    return cipherText.save(); // Returns cipher text as base64
  }

Do you have any ideas - i know the problem is not specific to your project but i would be glad over some input?

Huelse commented 2 months ago

Sorry for replying late, the second param of Ciphertext.load receives a file path, not the data string, reading the examples may help you.