📜  Shamir的秘密共享算法|密码学

📅  最后修改于: 2021-04-17 02:59:02             🧑  作者: Mango

密码术是一种通过使用代码来保护信息和通信的技术,这样,只有那些希望获得该信息的人才能理解和处理该信息。从而防止未经授权的信息访问。前缀“ crypt”表示“隐藏”,后缀图形表示“写入”。本文讨论了一种加密技术,即Shamir的秘密共享算法。

Shamir的秘密共享算法: Shamir的秘密共享算法是Adi Shamir创建的加密算法。该算法的主要目的是将需要加密的秘密划分为各个唯一的部分。

  • 假设S是我们希望编码的秘密。
  • 它分为N个部分:S1,S2,S3,…。,Sn。
  • 在对它进行划分之后,用户选择数字K以便解密部分并找到原始秘密。
  • 以这样的方式进行选择:如果我们知道少于K个部分,那么我们将无法找到秘密S(即,秘密S不能以(K – 1)个或更少的部分进行重构)。
  • 如果我们从S1,S2,S3,…,Sn中知道K个或更多部分,那么我们可以轻松地计算/重构我们的密码S。这通常称为(K,N)阈值方案。

方法: Shamir秘密共享算法的主要思想在于以下概念:对于给定的K个点,我们可以找到一个度数为(K – 1)的多项式方程。

例子:

  • 对于给定的两个点(x1,y1)和(x2,y2),我们可以找到一个线性多项式ax + by = c
  • 类似地,对于给定的三个点,我们可以找到二次多项式ax 2 + bx + cy = d

因此,我们的想法是建立一个多项式,其次数为(K – 1) ,使得常数项是密码,其余数是随机的,并且可以使用从生成的N个点中的任意K个点来找到该常数项。通过使用Legrange的基础多项式,此多项式。

例如:让密码S = 65,N = 4,K = 2。

  1. 最初,为了加密密码,我们建立了一个次数为(K – 1)的多项式。
  2. 因此,令多项式为y = a + bx 。在这里,常量部分“ a”是我们的密码。
  3. 令b为任意随机数,例如b = 15。
  4. 因此,对于这个多项式y = 65 + 15x,我们从中生成N = 4个点。
  5. 令这4个点为(1,80),(2,95),(3,110),(4,125)。显然,我们可以从这4个点中的任意两个点生成初始多项式,并且在所得多项式中,常数项a是所需的密码。

为了重建给定的多项式,使用了拉格朗日基础多项式。

拉格朗日多项式背后的主要概念是首先形成拉格朗日的恒等式,这些恒等式的加和为我们提供了需要从给定点中找到的所需函数。以下等式说明了如何计算它们:

例如,假设我们希望通过从选定的四个点(1、80、3、110)中使用K = 2个点来计算给定方程。下图显示了此问题的分步解决方案:

下面是上述方法的实现:

// C++ implementation of shamir’s
// secret sharing algorithm
  
#include 
using namespace std;
  
// Function to calculate the value
// of y
// y = poly[0] + x*poly[1] + x^2*poly[2] + ...
int calculate_Y(int x, vector& poly)
{
    // Initializing y
    int y = 0;
    int temp = 1;
  
    // Iterating through the array
    for (auto coeff : poly) {
  
        // Computing the value of y
        y = (y + (coeff * temp));
        temp = (temp * x);
    }
    return y;
}
  
// Function to perform the secret
// sharing algorithm and encode the
// given secret
void secret_sharing(int S, vector >& points,
                    int N, int K)
{
    // A vector to store the polynomial
    // cofficient of K-1 degree
    vector poly(K);
  
    // Randomly choose K - 1 numbers but
    // not zero and poly[0] is the secret
    // create polynomial for this
  
    poly[0] = S;
  
    for (int j = 1; j < K; ++j) {
        int p = 0;
        while (p == 0)
  
            // To keep the random values
            // in range not too high
            // we are taking mod with a
            // prime number around 1000
            p = (rand() % 997);
  
        // This is to ensure we did not
        // create a polynomial consisting
        // of zeroes.
        poly[j] = p;
    }
  
    // Generating N points from the
    // polynomial we created
    for (int j = 1; j <= N; ++j) {
        int x = j;
        int y = calculate_Y(x, poly);
  
        // Points created on sharing
        points[j - 1] = { x, y };
    }
}
  
// This structure is used for fraction
// part handling multiplication
// and addition of fractiontion
struct fraction {
    int num, den;
  
    // A fraction consists of a
    // numerator and a denominator
    fraction(int n, int d)
    {
        num = n, den = d;
    }
  
    // If the fraction is not
    // in its reduced form
    // reduce it by dividing
    // them with their GCD
    void reduce_fraction(fraction& f)
    {
        int gcd = __gcd(f.num, f.den);
        f.num /= gcd, f.den /= gcd;
    }
  
    // Performing multiplication on the
    // fraction
    fraction operator*(fraction f)
    {
        fraction temp(num * f.num, den * f.den);
        reduce_fraction(temp);
        return temp;
    }
  
    // Performing addition on the
    // fraction
    fraction operator+(fraction f)
    {
        fraction temp(num * f.den + den * f.num,
                      den * f.den);
  
        reduce_fraction(temp);
        return temp;
    }
};
  
// Function to generate the secret
// back from the given points
// This function will use Lagrange Basis Polynomial
// Instead of finding the complete Polynomial
// We only required the poly[0] as our secret code,
// thus we can get rid of x terms
int Generate_Secret(int x[], int y[], int M)
{
  
    fraction ans(0, 1);
  
    // Loop to iterate through the given
    // points
    for (int i = 0; i < M; ++i) {
  
        // Initializing the fraction
        fraction l(y[i], 1);
        for (int j = 0; j < M; ++j) {
  
            // Computing the lagrange terms
            if (i != j) {
                fraction temp(-x[j], x[i] - x[j]);
                l = l * temp;
            }
        }
        ans = ans + l;
    }
  
    // Return the secret
    return ans.num;
}
  
// Function to encode and decode the
// given secret by using the above
// defined functions
void operation(int S, int N, int K)
{
  
    // Vector to store the points
    vector > points(N);
  
    // Sharing of secret Code in N parts
    secret_sharing(S, points, N, K);
  
    cout << "Secret is divided to " << N
         << " Parts - " << endl;
  
    for (int i = 0; i < N; ++i) {
        cout << points[i].first << " "
             << points[i].second << endl;
    }
  
    cout << "We can generate Secret from any of "
         << K << " Parts" << endl;
  
    // Input any M points from these 
    // to get back our secret code.
    int M = 2;
  
    // M can be greater than or equal to threshold but
    // for this example we are taking for threshold
    if (M < K) {
        cout << "Points are less than threshold "
             << K << " Points Required" << endl;
    }
  
    int* x = new int[M];
    int* y = new int[M];
  
    // Input M points you will get the secret
    // Let these points are first M points from
    // the N points which we shared above
    // We can take any M points
  
    for (int i = 0; i < M; ++i) {
        x[i] = points[i].first;
        y[i] = points[i].second;
    }
  
    // Get back our result again.
    cout << "Our Secret Code is : "
         << Generate_Secret(x, y, M) << endl;
}
  
// Driver Code
int main()
{
    int S = 65; 
    int N = 4; 
    int K = 2; 
  
    operation(S, N, K);
    return 0;
}
输出:
Secret is divided to 4 Parts - 
1 602
2 1139
3 1676
4 2213
We can generate Secret from any of 2 Parts
Our Secret Code is : 65

参考: Shamir秘密分享