# frozen_string_literal: true # module secret sharing module Sharing # crt-based secret sharing schemes module CRT # crt-based secret sharing scheme proposed by Asmuth-Bloom module AsmuthBloom # second version of Asmuth-Bloom proposed by Ersoy et al. class V2 include HenselCode::Tools attr_accessor :threshold, :secrecy, :total_shares, :primes, :p, :m_r, :m_to_s, :k_add, :k_mul, :lambda_, :a, :y, :upperbound def self.add(shares1, shares2) shares1.zip(shares2).map { |s| [s[0][0], s[0][1] + s[1][1]] } end def self.mul(shares1, shares2) shares1.zip(shares2).map { |s| [s[0][0], s[0][1] * s[1][1]] } end def initialize(params = {}) @threshold = params[:threshold] @secrecy = params[:secrecy] @total_shares = params[:total_shares] @k_add = params[:k_add] @k_mul = params[:k_mul] @lambda_ = params[:lambda_] generate_unique_primes compute_prime_products generate_single_prime end def compute_upperbound(secret) @upperbound = ((p * m_to_s) - secret) / p end def compute_shares(secret) compute_upperbound(secret) @a = rand(1..upperbound - 1) @y = secret + (a * p) primes.map.with_index { |prime, i| [i, y % prime] } end def reconstruct_secret(selected_shares) indices = selected_shares.map(&:first) moduli = primes.values_at(*indices) shares = selected_shares.map(&:last) y = crt(moduli, shares) y % p end def generate_primes @primes = random_distinct_numbers("prime", total_shares, lambda_) @primes.sort! end def compute_prime_products @m_r = primes[0..threshold - 1].inject(:*) @m_to_s = 1 (0..secrecy - 1).each do |i| @m_to_s *= primes[total_shares - (i + 2) + 1] end end def generate_single_prime bits = lambda_ @p = random_prime(lambda_) while m_r <= (k_add + 1) * ((@p * m_to_s)**(k_mul + 1)) bits -= 1 @p = random_prime(bits) end end def generate_unique_primes @primes = [random_prime(lambda_)] while primes.uniq.size < total_shares prime = random_prime(lambda_) @primes << prime unless @primes.include?(prime) && (@primes + [prime]).reduce(1, :gcd) != 1 end @primes = @primes.uniq.sort end end end end end