Skip to content

Commit

Permalink
Fix flaky noise budget snippet
Browse files Browse the repository at this point in the history
  • Loading branch information
fboemer committed Sep 5, 2024
1 parent 5052bab commit da364e9
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 7 deletions.
6 changes: 4 additions & 2 deletions Snippets/HomomorphicEncryption/NoiseBudgetSnippet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ print("Minimum noise budget", Bfv<UInt32>.minNoiseBudget)
noiseBudget = noiseBudgetAfterRelinearization
ciphertext = try plaintext.encrypt(using: secretKey)
var expected = plaintext
while noiseBudget > minNoiseBudget {
while noiseBudget > minNoiseBudget + 1 {
let decrypted = try ciphertext.decrypt(using: secretKey)
precondition(decrypted == expected)
try ciphertext += ciphertext
Expand All @@ -134,8 +134,10 @@ while noiseBudget > minNoiseBudget {
// snippet.show
}

// One more addition yields incorrect results
// Two more additions yields incorrect results
ciphertext = try ciphertext + ciphertext
ciphertext = try ciphertext + ciphertext
try expected += expected
try expected += expected
let decrypted = try ciphertext.decrypt(using: secretKey)
precondition(decrypted != expected)
5 changes: 5 additions & 0 deletions Sources/HomomorphicEncryption/Bfv/Bfv+Decrypt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ extension Bfv {
{
// See Definition 1 of
// https://www.microsoft.com/en-us/research/wp-content/uploads/2017/06/sealmanual_v2.2.pdf.
// More precisely, we should use Theorem 1 from https://eprint.iacr.org/2016/510.pdf, but it's more complicated
// and unlikely to make
// a difference in practice, especially as the noise budget in itself is just a rough proxy for correct
// decryption. For example, with `q=131249, t=17`, a ciphertext has noise budget 0.67181 with Definition 1, but
// noise budget 0.66854 with Theorem 1.
var vTimesT = try Self.dotProduct(ciphertext: ciphertext, with: secretKey)
vTimesT *= Array(repeating: ciphertext.context.plaintextModulus, count: vTimesT.moduli.count)
let rnsTool = ciphertext.context.getRnsTool(moduliCount: vTimesT.moduli.count)
Expand Down
2 changes: 1 addition & 1 deletion Sources/HomomorphicEncryption/Bfv/Bfv.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public enum Bfv<T: ScalarType>: HeScheme {
}

public static var minNoiseBudget: Double {
0.5
0
}

// MARK: HE operations
Expand Down
6 changes: 6 additions & 0 deletions Sources/HomomorphicEncryption/HeScheme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,9 @@ public protocol HeScheme {
/// - Returns: The noise budget.
/// - Throws: Error upon failure to compute the noise budget.
/// - Warning: Leaks `secretKey` through timing. Should be used for testing only.
/// - Warning: The noise budget depends on the encrypted message, which is impractical to know apriori. So this
/// function should be treated only as a rough proxy for correct decryption, rather than a source of truth.
/// See Section 2 of <https://eprint.iacr.org/2016/510.pdf> for more details.
/// - seealso: ``Ciphertext/noiseBudget(using:variableTime:)`` for an alternative API.
static func noiseBudgetCoeff(of ciphertext: CoeffCiphertext, using secretKey: SecretKey, variableTime: Bool) throws
-> Double
Expand All @@ -658,6 +661,9 @@ public protocol HeScheme {
/// - Returns: The noise budget.
/// - Throws: Error upon failure to compute the noise budget.
/// - Warning: Leaks `secretKey` through timing. Should be used for testing only.
/// - Warning: The noise budget depends on the encrypted message, which is impractical to know apriori. So this
/// function should be treated only as a rough proxy for correct decryption, rather than a source of truth.
/// See Section 2 of <https://eprint.iacr.org/2016/510.pdf> for more details.
/// - seealso: ``Ciphertext/noiseBudget(using:variableTime:)`` for an alternative API.
static func noiseBudgetEval(of ciphertext: EvalCiphertext, using secretKey: SecretKey, variableTime: Bool) throws
-> Double
Expand Down
11 changes: 10 additions & 1 deletion Sources/PrivateNearestNeighborsSearch/CiphertextMatrix.swift
Original file line number Diff line number Diff line change
Expand Up @@ -306,12 +306,21 @@ extension CiphertextMatrix {
ciphertexts: [ciphertext])
}

/// Returns the noise budget.
/// Computes the noise budget of the ciphertext matrix.
///
/// The *noise budget* of the each ciphertext in the matrix decreases throughout HE operations. Once a
/// ciphertext's noise budget is
/// below
/// `HeScheme/minNoiseBudget`, decryption may yield inaccurate plaintexts.
/// - Parameters:
/// - secretKey: Secret key.
/// - variableTime: If `true`, indicates the secret key coefficients may be leaked through timing.
/// - Returns: The noise budget.
/// - Throws: Error upon failure to compute the noise budget.
/// - Warning: Leaks `secretKey` through timing. Should be used for testing only.
/// - Warning: The noise budget depends on the encrypted message, which is impractical to know apriori. So this
/// function should be treated only as a rough proxy for correct decryption, rather than a source of truth.
/// See Section 2 of <https://eprint.iacr.org/2016/510.pdf> for more details.
@inlinable
func noiseBudget(using secretKey: Scheme.SecretKey, variableTime: Bool) throws -> Double {
try ciphertexts.map { ciphertext in
Expand Down
10 changes: 7 additions & 3 deletions Sources/PrivateNearestNeighborsSearch/PnnsProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,21 @@ public struct DatabaseDistances: Sendable {
}

extension Response {
/// Computes the noise budget of the ciphertext.
/// Computes the noise budget of the response.
///
/// The *noise budget* of the ciphertext decreases throughout HE operations. Once a ciphertext's noise budget is
/// The *noise budget* of the each ciphertext in the response decreases throughout HE operations. Once a
/// ciphertext's noise budget is
/// below
/// ``HeScheme/minNoiseBudget``, decryption may yield inaccurate plaintexts.
/// `HeScheme/minNoiseBudget`, decryption may yield inaccurate plaintexts.
/// - Parameters:
/// - secretKey: Secret key.
/// - variableTime: If `true`, indicates the secret key coefficients may be leaked through timing.
/// - Returns: The noise budget.
/// - Throws: Error upon failure to compute the noise budget.
/// - Warning: Leaks `secretKey` through timing. Should be used for testing only.
/// - Warning: The noise budget depends on the encrypted message, which is impractical to know apriori. So this
/// function should be treated only as a rough proxy for correct decryption, rather than a source of truth.
/// See Section 2 of <https://eprint.iacr.org/2016/510.pdf> for more details.
@inlinable
public func noiseBudget(using secretKey: Scheme.SecretKey, variableTime: Bool) throws -> Double {
try ciphertextMatrices.map { ciphertextMatrix in
Expand Down

0 comments on commit da364e9

Please sign in to comment.