#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
typedef long long ll;
typedef unsigned long long ull;
// 定义椭圆曲线点结构
typedef struct {
ll x;
ll y;
bool is_infinity; // 标记是否为无穷远点
} ECPoint;
// 定义椭圆曲线参数
typedef struct {
ll p; // 素数模数
ll a; // 曲线参数a
ll b; // 曲线参数b
ECPoint G; // 生成点
ll n; // G的阶
} ECC_Params;
// 函数声明
ll mod(ll a, ll m);// 计算a mod m
ll mod_inverse(ll a, ll m);// 扩展欧几里得算法计算模逆元
ECPoint point_add(ECPoint P, ECPoint Q, ECC_Params params);// 椭圆曲线点加法
ECPoint point_multiply(ll k, ECPoint P, ECC_Params params);// 椭圆曲线点乘法
int is_prime(ll n);// 检查是否为质数
ull hash(char *message);// 简单哈希函数
void ecdsa_init(ECC_Params *params);// 初始化椭圆曲线参数
void generate_keypair(ECC_Params params, ll *private_key, ECPoint *public_key);// 生成Schnorr密钥对
void schnorr_sign(ECC_Params params,ll private_key, ECPoint public_key, char *msg,ECPoint *R, ll *s);// Schnorr签名生成
int schnorr_verify(ECC_Params params, char *msg, ECPoint R, ECPoint public_key, ll s);// Schnorr签名验证
void aggregate_sign(ECC_Params params, char *msg,ECPoint *ag_P, ECPoint *ag_R, ll *ag_s);// 组签名
void aggregate_verify(ECC_Params params,char *msg, ECPoint ag_R, ECPoint ag_P, ll ag_s);//聚合签名验证
// 计算a mod m,确保结果为正数
ll mod(ll a, ll m) {
ll result = a % m;
if (result < 0)
result += m;
return result;
}
// 扩展欧几里得算法计算模逆元
ll mod_inverse(ll a, ll m) {
ll m0 = m, t, q;
ll y = 0, x = 1;
if (m == 1) return 0;
while (a > 1) {
q = a / m;
t = m;
m = a % m;
a = t;
t = y;
y = x - q * y;
x = t;
}
// 确保x为正数
if (x < 0)x += m0;
return x;
}
// 椭圆曲线点加法 P + Q
ECPoint point_add(ECPoint P, ECPoint Q, ECC_Params params) {
ECPoint R;
R.is_infinity = false;
// 处理无穷远点情况
if (P.is_infinity) return Q;
if (Q.is_infinity) return P;
// 如果P和Q是互逆点,结果为无穷远点
if (P.x == Q.x && mod(P.y + Q.y, params.p) == 0) {
R.is_infinity = true;
return R;
}
ll lambda; // 斜率
// 计算lambda
if (P.x == Q.x && P.y == Q.y) {
// 点加倍,P = Q
if (P.y == 0) {
R.is_infinity = true;
return R;// 无穷远点
}
ll numerator = mod(3 * P.x * P.x + params.a, params.p);
ll denominator = mod(2 * P.y, params.p);
lambda = mod(numerator * mod_inverse(denominator, params.p), params.p);
} else {
// 不同点,P != Q
ll numerator = mod(Q.y - P.y, params.p);
ll denominator = mod(Q.x - P.x, params.p);
lambda = mod(numerator * mod_inverse(denominator, params.p), params.p);
}
// 计算结果点坐标
R.x = mod(lambda * lambda - P.x - Q.x, params.p);
R.y = mod(lambda * (P.x - R.x) - P.y, params.p);
return R;
}
// 椭圆曲线点乘法 k*P(使用快速加倍-加法算法)
ECPoint point_multiply(ll k, ECPoint P, ECC_Params params) {
ECPoint R;
R.is_infinity = true; // 初始化为无穷远点(单位元)
k = mod(k, params.n); // 由于n是G的阶,k可以简化为k mod n
while (k > 0) {
if (k % 2 == 1) {
// 如果当前位为1,将current加到result上
if (R.is_infinity == true) {R = P;}
else R = point_add(R, P, params);
}
// 加倍
P = point_add(P,P,params);
// 右移k
k = k / 2;
}
return R;
}
// 检查是否为质数
int is_prime(ll n) {
if (n <= 1) return 0;
if (n <= 3) return 1;
if (n % 2 == 0 || n % 3 == 0) return 0;
for (ll i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0)
return 0;
}
return 1;
}
// 简单哈希函数
ull hash(char *message) {
ull hash = 5381;
int c;
while ((c = *message++))
hash = ((hash << 5) + hash) + c; // hash * 33 + c
return hash;
}
// 初始化椭圆曲线参数
void ecdsa_init(ECC_Params *params) {
params->p = 23; // 素数模数
params->a = 1; // 曲线参数a
params->b = 4; // 曲线参数b,曲线方程: y² = x³ + x + 4 mod 23
params->G.x = 0; // 生成点x坐标
params->G.y = 2; // 生成点y坐标
params->G.is_infinity = false;
params->n = 29; // G的阶
printf("椭圆曲线参数初始化:\n");
printf("p = %lld, a = %lld, b = %lld\n", params->p, params->a, params->b);
printf("生成点G: (%lld, %lld)\t", params->G.x, params->G.y);
printf("n = %lld\n", params->n);
}
// 生成Schnorr密钥对
void generate_keypair(ECC_Params params, ll *private_key, ECPoint *public_key) {
// 私钥d: 1 < d < n
*private_key = rand() % (params.n - 2) + 2;
// 公钥Q = d * G
*public_key = point_multiply(*private_key, params.G, params);
printf("生成密钥对:\n");
printf("私钥 d = %lld\n", *private_key);
printf("公钥 Q = (%lld, %lld)\n", public_key->x, public_key->y);
}
// Schnorr签名生成
// 选择一个随机数k,令R=kG
// 令s=k+xH(m||R||P)
void schnorr_sign(ECC_Params params,ll private_key, ECPoint public_key, char *msg,ECPoint *R, ll *s) {
ll k = rand() % (params.n - 1) + 1; // 随机数k
*R = point_multiply(k, params.G, params);
// 计算 e = H(m || R.x || R.y || P.x || P.y) mod n
char buffer[1024];
sprintf(buffer, "%s%lld%lld%lld%lld", msg, (*R).x, (*R).y,public_key.x,public_key.y);
ll e = hash(buffer) % params.n;
*s = mod((k + private_key * e), params.n);
printf("签名生成\n");
// printf("随机数 k: %lld\n", k);
printf("临时点 R: (%lld, %lld)\n", (*R).x, (*R).y);
// printf("哈希值 e: %lld\n", e);
printf("签名值 s: %lld\n", *s);
}
// Schnorr签名验证
//sG=R+P⋅H(m||R||P)
int schnorr_verify(ECC_Params params, char *msg, ECPoint R, ECPoint public_key, ll s) {
// 计算 e = H(m || R.x || R.y || P.x || P.y) mod n
char buffer[1024];
sprintf(buffer, "%s%lld%lld%lld%lld", msg, R.x,R.y,public_key.x,public_key.y);
ll e = hash(buffer) % params.n;
ECPoint sG = point_multiply(s,params.G,params);
ECPoint eP = point_multiply(e, public_key, params);
ECPoint reP = point_add(R, eP, params);
// printf("验证过程\n");
// printf("计算 sG: (%lld, %lld)\n", sG.x, sG.y);
// printf("计算 eP: (%lld, %lld)\n", eP.x, eP.y);
// printf("计算 reP: (%lld, %lld)\n", reP.x, reP.y);
// 验证 sG == R + eP
bool valid = false;
if (sG.is_infinity && reP.is_infinity) {
valid = true; // 两者都是无穷远点
} else if (!sG.is_infinity && !reP.is_infinity) {
valid = (sG.x == reP.x) && (sG.y == reP.y);
}
printf("验证结果: %s\n", valid ? "成功" : "失败");
return valid;
}
// 组签名
// 私钥:x_1,x_2,对应的公钥P_1=x_1 G,P_2=x_2 G,
// 随机数:k_1,k_2,并有R_1=k_1 G,R_2=k_2 G,
// 组公钥:P=P_1+P_2
// 组签名:(R, s) R = R_1 + R_2, s = s_1 + s_2
void aggregate_sign(ECC_Params params, char *msg,ECPoint *ag_P, ECPoint *ag_R, ll *ag_s) {
printf("聚合签名\n");
printf("message : %s\n", msg);
ll x_1, x_2, s_1, s_2, k_1, k_2;
ECPoint P_1, P_2, R_1, R_2;
generate_keypair(params, &x_1, &P_1);
generate_keypair(params, &x_2, &P_2);
// 计算组公钥 P = P1 + P2
*ag_P = point_add(P_1, P_2 ,params);//组公钥
printf("ag_P = (%lld,%lld)\n",(*ag_P).x,(*ag_P).y);
// 生成随机数并计算 R1 和 R2
k_1 = rand() % (params.n - 1) + 1;
R_1 = point_multiply(k_1, params.G, params);
k_2 = rand() % (params.n - 1) + 1;
R_2 = point_multiply(k_2, params.G, params);
*ag_R = point_add(R_1, R_2, params);
printf("ag_R = (%lld,%lld)\n",(*ag_R).x,(*ag_R).y);
// 计算 e = H(m || R.x || R.y || P.x || P.y) mod n
char buffer[1024];
sprintf(buffer, "%s%lld%lld%lld%lld", msg, (*ag_R).x, (*ag_R).y,(*ag_P).x,(*ag_P).y);
ll e = hash(buffer) % params.n;
// printf("聚合哈希 e: %lld\n", e);
// 计算各签名者s值并聚合
s_1 = mod(k_1 + e * x_1, params.n);
s_2 = mod(k_2 + e * x_2, params.n);
*ag_s = mod(s_1 + s_2, params.n);
printf("ag_s = %lld\n", *ag_s);
}
//聚合签名验证
void aggregate_verify(ECC_Params params,char *msg, ECPoint ag_R, ECPoint ag_P, ll ag_s) {
int valid = schnorr_verify(params, msg, ag_R, ag_P, ag_s); // 验证
printf("聚合签名最终验证结果: %s\n", valid ? "签名有效" : "签名无效");
}
int main() {
// 初始化随机数生成器
srand(time(NULL));
// 1. 初始化椭圆曲线参数
ECC_Params params;
ecdsa_init(¶ms);
// 2. 生成密钥对
ll private_key;
ECPoint public_key;
generate_keypair(params, &private_key, &public_key);
// 3. 待签名的消息
char original_message[] = "测试消息,用于签名演示";
// char original_message[1024] = {0}; //明文
// printf("请输入要加密的信息: ");
// fgets(original_message, sizeof(original_message), stdin);
// original_message[strcspn(original_message, "\n")] = '\0';// 去除换行符
printf("原始消息: %s\n", original_message);
// 4. 对消息进行签名
ll s;
ECPoint R;
schnorr_sign(params, private_key,public_key,original_message, &R, &s); // 生成签名
int valid = schnorr_verify(params, original_message, R, public_key, s); // 验证
printf("最终验证结果: %s\n\n", valid ? "签名有效" : "签名无效");
ECPoint ag_P, ag_R;
ll ag_s;
aggregate_sign(params, original_message, &ag_P, &ag_R, &ag_s);
aggregate_verify(params, original_message, ag_R, ag_P, ag_s);
return 0;
}
已知上述代码,使用上述代码并进行简单编程,完成ZSS签名,ZSS中 双线性配对模拟 详细执行 使用c语言实现过程
最新发布