Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

{Ciphertext,Plaintext}Matrix deserialization #70

Merged
merged 1 commit into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Sources/HomomorphicEncryption/SerializedPlaintext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ extension Plaintext where Format == Eval {
/// - serialized: Serialized plaintext.
/// - context: Context to associate with the plaintext.
/// - moduliCount: Optional number of moduli to associate with the plaintext. If not set, the plaintext will have
/// the top-level ciphertext context with all themoduli.
/// the top-level ciphertext context with all the moduli.
/// - Throws: Error upon failure to deserialize.
public init(deserialize serialized: SerializedPlaintext, context: Context<Scheme>, moduliCount: Int? = nil) throws {
self.context = context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,25 @@ public struct SerializedCiphertextMatrix<Scalar: ScalarType>: Equatable, Sendabl
}

extension CiphertextMatrix {
/// Deserializes a serialized ciphertext matrix.
/// - Parameters:
/// - serialized: Serialized ciphertext matrix.
/// - context: Context to associate with the ciphertext matrix.
/// - moduliCount: Number of moduli in each serialized ciphertext. If not set, deserialization will use the
/// top-level ciphertext with all the moduli.
/// - Throws: Error upon failure to deserialize the ciphertext matrix.
@inlinable
public init(
deserialize serialized: SerializedCiphertextMatrix<Scheme.Scalar>,
context: Context<Scheme>,
moduliCount: Int? = nil) throws
{
let ciphertexts: [Ciphertext<Scheme, Format>] = try serialized.ciphertexts.map { serializedCiphertext in
try Ciphertext(deserialize: serializedCiphertext, context: context, moduliCount: moduliCount)
}
try self.init(dimensions: serialized.dimensions, packing: serialized.packing, ciphertexts: ciphertexts)
}

/// Serializes the ciphertext matrix.
/// - Parameter forDecryption: If true, serialization may use a more concise format, yielding ciphertexts which,
/// once deserialized, are only compatible with decryption, and not any other HE operations.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,37 @@ extension PlaintextMatrix {
plaintexts: plaintexts.map { plaintext in plaintext.serialize() })
}
}

extension PlaintextMatrix where Format == Coeff {
/// Deserializes a plaintext matrix.
/// - Parameters:
/// - serialized: Serialized plaintext matrix.
/// - context: Context to associate with the plaintext matrix.
/// - Throws: Error upon failure to deserialize.
init(deserialize serialized: SerializedPlaintextMatrix, context: Context<Scheme>) throws {
let plaintexts = try serialized.plaintexts.map { serializedPlaintext in
try Plaintext(deserialize: serializedPlaintext, context: context)
}
try self.init(dimensions: serialized.dimensions, packing: serialized.packing, plaintexts: plaintexts)
}
}

extension PlaintextMatrix where Format == Eval {
/// Deserializes a plaintext matrix.
/// - Parameters:
/// - serialized: Serialized plaintext matrix.
/// - context: Context to associate with the plaintext matrix.
/// - moduliCount: Optional number of moduli to associate with each plaintext. If not set, each plaintext will
/// have the top-level ciphertext context with all the moduli.
/// - Throws: Error upon failure to deserialize.
init(
deserialize serialized: SerializedPlaintextMatrix,
context: Context<Scheme>,
moduliCount: Int? = nil) throws
{
let plaintexts = try serialized.plaintexts.map { serializedPlaintext in
try Plaintext(deserialize: serializedPlaintext, context: context, moduliCount: moduliCount)
}
try self.init(dimensions: serialized.dimensions, packing: serialized.packing, plaintexts: plaintexts)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,19 @@ class ConversionTests: XCTestCase {
values: scalars.flatMap { $0 })
let serialized = try plaintextMatrix.serialize()
XCTAssertEqual(try serialized.proto().native(), serialized)
let deserialized = try PlaintextMatrix(deserialize: serialized, context: context)
XCTAssertEqual(deserialized, plaintextMatrix)

for moduliCount in 1..<encryptionParams.coefficientModuli.count {
let evalPlaintextMatrix = try plaintextMatrix.convertToEvalFormat(moduliCount: moduliCount)
let serialized = try evalPlaintextMatrix.serialize()
XCTAssertEqual(try serialized.proto().native(), serialized)
let deserialized = try PlaintextMatrix(
deserialize: serialized,
context: context,
moduliCount: moduliCount)
XCTAssertEqual(deserialized, evalPlaintextMatrix)
}
}

try runTest(Bfv<UInt32>.self)
Expand Down Expand Up @@ -135,10 +148,25 @@ class ConversionTests: XCTestCase {
XCTAssertEqual(try serializedProto.native(), serialized)
let serializedSize = try serializedProto.serializedData().count

// TODO: test deserialization
let serializedForDecryption = try ciphertextMatrix.serialize(forDecryption: true)
let serializedForDecryptionSize = try serializedForDecryption.proto().serializedData().count
XCTAssertLessThanOrEqual(serializedForDecryptionSize, serializedSize)
let deserialized = try CiphertextMatrix<Scheme, Scheme.CanonicalCiphertextFormat>(
deserialize: serializedForDecryption,
context: context)
let decrypted = try deserialized.decrypt(using: secretKey)
XCTAssertEqual(decrypted, plaintextMatrix)

// Check Evaluation format
do {
let evalCiphertextMatrix = try ciphertextMatrix.convertToEvalFormat()
let serialized = try evalCiphertextMatrix.serialize()
XCTAssertEqual(try serialized.proto().native(), serialized)
let deserialized = try CiphertextMatrix<Scheme, Eval>(
deserialize: serialized,
context: context)
XCTAssertEqual(deserialized, evalCiphertextMatrix)
}
}

try runTest(Bfv<UInt32>.self)
Expand Down
Loading