密码术是一种通过使用代码来保护信息和通信的技术,这样,只有那些希望获得该信息的人才能理解和处理该信息。从而防止未经授权的信息访问。前缀“ 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。
- 最初,为了加密密码,我们建立了一个次数为(K – 1)的多项式。
- 因此,令多项式为y = a + bx 。在这里,常量部分“ a”是我们的密码。
- 令b为任意随机数,例如b = 15。
- 因此,对于这个多项式y = 65 + 15x,我们从中生成N = 4个点。
- 令这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秘密分享