Загрузка данных
// task5.c - Сложение точек G + P на эллиптической кривой secp256k1
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define MaxDig 1000
#define Osn 0x100
#define mm 8
typedef struct{
int lm[MaxDig];
int len;
int sign;
} LDig;
// ============ ФУНКЦИИ ИЗ larif16-2.c ============
void InitLong(LDig *A){
int i;
for (i=0; i<MaxDig; i++) A->lm[i]=0;
A->len=1; A->sign=1;
}
void Read16Long(LDig *A, char *S){
char chs[3];
int i,len, b[100],ch,k=0;
if (S[0]=='-'){ A->sign = -1; k=1; }
strcpy(chs,"");
len= strlen(S);
A->len = len/2;
for (i=k;i<len;i+=2){
chs[0]=S[i]; chs[1]=S[i+1]; chs[2]='\0';
sscanf(chs,"%02x",&ch);
b[i/2]=ch;
}
for(i=0; i<A->len;i++) A->lm[A->len-1-i]=b[i];
}
void Write16Long(LDig *A, char *S){
char s[10];
int i;
if (A->sign<0) strcpy(S,"-");
else strcpy(S,"");
for (i=A->len-1;i>=0;i--){
sprintf(s,"%02x", A->lm[i]);
strcat(S,s);
}
}
void ShowLongS(LDig *A){
char S[256];
Write16Long(A, S);
printf("%s\n",S);
}
int IsNulLong(LDig *A){
return ((A->len==1)&&(A->lm[0]==0));
}
void DigToArray(int k, LDig *A){
int res, i=0, sign=1;
if (k<0) sign=-1;
res = (k<0)?-k:k;
while (res>0){
A->lm[i]=res%Osn;
res/=Osn;
i++;
}
A->len=i;
if(i==0){ A->len=1; A->lm[0]=0; }
A->sign=sign;
}
int Eq(LDig *A, LDig *B){
int i;
if((A->len!=B->len)||(A->sign!=B->sign)) return 0;
for(i=0;i<A->len;i++) if(A->lm[i]!=B->lm[i]) return 0;
return 1;
}
int More(LDig *A, LDig *B){
int i;
if(A->len>B->len) return 1;
if(A->len<B->len) return 0;
for(i=A->len-1;i>=0;i--){
if(A->lm[i]>B->lm[i]) return 1;
if(A->lm[i]<B->lm[i]) return 0;
}
return 0;
}
int More_Shift(LDig *A, LDig *B, int sp){
int i;
if(A->len > B->len+sp) return 0;
if(A->len < B->len+sp) return 1;
for(i=A->len-1;i>=sp;i--){
if(A->lm[i] > B->lm[i-sp]) return 0;
if(A->lm[i] < B->lm[i-sp]) return 1;
}
for(i=0;i<sp;i++) if(A->lm[i]>0) return 0;
return 2;
}
void Sum_Shift(LDig *A, LDig *B, int sp){
int i,k;
if(A->len > B->len+sp) k=A->len;
else k=B->len+sp;
for(i=0;i<k;i++){
A->lm[i+sp+1] += (A->lm[i+sp]+B->lm[i])/Osn;
A->lm[i+sp] = (A->lm[i+sp]+B->lm[i])%Osn;
}
if(A->lm[k]==0) A->len=k;
else A->len=k+1;
}
void Sub_Shift(LDig *A, LDig *B, int sp){
int i,j;
for(i=0;i<B->len;i++){
A->lm[i+sp] -= B->lm[i];
j=i;
while((A->lm[j+sp]<0)&&(j<A->len-1)){
A->lm[j+sp] += Osn;
A->lm[j+sp+1]--;
j++;
}
}
i=A->len-1;
while((i>0)&&(A->lm[i]==0)) i--;
A->len=i+1;
}
void SumTwo(LDig *A, LDig *B, LDig *C){
*C=*A;
Sum_Shift(C,B,0);
}
void SubTwo(LDig *A, LDig *B, LDig *C){
*C=*A;
Sub_Shift(C,B,0);
}
void SumLong(LDig *A, LDig *B, LDig *C){
if(A->sign==B->sign){
SumTwo(A,B,C);
C->sign=A->sign;
} else {
if(More(A,B)){
SubTwo(A,B,C);
C->sign=A->sign;
} else {
SubTwo(B,A,C);
C->sign=B->sign;
}
}
}
void SumLongA(LDig *A, LDig *B){
LDig C;
InitLong(&C);
SumLong(A,B,&C);
*A=C;
}
void SubLong(LDig *A, LDig *B, LDig *C){
if(A->sign!=B->sign){
SumTwo(A,B,C);
C->sign=A->sign;
} else {
if(More(A,B)){
SubTwo(A,B,C);
C->sign=A->sign;
} else {
SubTwo(B,A,C);
C->sign=-B->sign;
}
}
}
void Mul(LDig *A, int K, LDig *C){
int i;
InitLong(C);
if(K!=0){
for(i=0;i<A->len;i++){
C->lm[i+1] = (C->lm[i]+A->lm[i]*(K>0?K:-K))/Osn;
C->lm[i] = (C->lm[i]+A->lm[i]*(K>0?K:-K))%Osn;
}
if(C->lm[A->len]>0) C->len=A->len+1;
else C->len=A->len;
}
C->sign = A->sign * ((K>0)?1:-1);
}
void MulA(LDig *A, int K){
LDig C;
InitLong(&C);
Mul(A,K,&C);
*A=C;
}
void MulTwoLong(LDig *A, LDig *B, LDig *C){
int i;
LDig C1;
InitLong(C);
for(i=0;i<B->len;i++){
Mul(A, B->lm[i], &C1);
Sum_Shift(C, &C1, i);
}
C->sign = A->sign * B->sign;
}
void LongDivLong(LDig *A, LDig *B, LDig *Res, LDig *Ost){
int sp, Down, Up, k;
LDig C;
*Ost = *A;
sp = A->len - B->len;
if(More_Shift(A,B,sp)==1) sp--;
Res->len = sp+1;
while(sp>=0){
Down=0; Up=Osn;
while(Up-1>Down){
InitLong(&C);
Mul(B, (Up+Down)/2, &C);
k = More_Shift(Ost, &C, sp);
if(k==0) Down = (Down+Up)/2;
else if(k==1) Up = (Up+Down)/2;
else { Up = (Up+Down)/2; Down = Up; }
}
InitLong(&C);
Mul(B, (Up+Down)/2, &C);
if(More_Shift(Ost, &C, 0)==0) Sub_Shift(Ost, &C, sp);
else { Sub_Shift(&C, Ost, sp); *Ost = C; }
Res->lm[sp] = (Up+Down)/2;
sp--;
}
Res->sign = A->sign * B->sign;
Ost->sign = A->sign;
}
void OstLong(LDig *A, LDig *Ost, LDig *P){
LDig Res;
InitLong(&Res);
LongDivLong(A, P, &Res, Ost);
if((Ost->sign<0)&&!IsNulLong(Ost)) SumLongA(Ost, P);
}
void OstLongA(LDig *A, LDig *P){
LDig Ost;
InitLong(&Ost);
OstLong(A, &Ost, P);
*A = Ost;
}
// ============ ФУНКЦИИ ИЗ EllipLong.c ============
char ps[] = "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f";
int a = 0;
int b = 7;
char xGs[] = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798";
char yGs[] = "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8";
LDig P, xG, yG, n;
void InitPar(){
InitLong(&P);
InitLong(&n);
InitLong(&xG);
InitLong(&yG);
Read16Long(&P, ps);
Read16Long(&n, ns);
Read16Long(&xG, xGs);
Read16Long(&yG, yGs);
}
// Расширенный алгоритм Евклида
void LongEnhEvklid(LDig *A, LDig *B, LDig *t, LDig *nod){
LDig r1, r2, t1, t2, r, q, tt, C;
InitLong(&r1); InitLong(&r2);
InitLong(&t1); InitLong(&t2);
InitLong(&q); InitLong(&r);
InitLong(&tt); InitLong(&C);
r1 = *A; r2 = *B;
DigToArray(0, &t1);
DigToArray(1, &t2);
while(!IsNulLong(&r2)){
LongDivLong(&r1, &r2, &q, &r);
r1 = r2; r2 = r;
MulTwoLong(&q, &t2, &C);
SubLong(&t1, &C, &tt);
t1 = t2; t2 = tt;
}
*nod = r1;
*t = t1;
}
void invA(LDig *A, LDig *T, LDig *P){
LDig t, nod, Ed;
InitLong(&t); InitLong(&nod); InitLong(&Ed);
Ed.lm[0]=1;
LongEnhEvklid(P, A, &t, &nod);
if(!Eq(&nod, &Ed)) printf("Ошибка: нет обратного элемента\n");
*T = t;
}
// Сложение двух точек
void AddPoint(LDig *xP, LDig *yP, LDig *xQ, LDig *yQ, LDig *xR, LDig *yR, LDig *p){
LDig m, s1, s2, C1, C2, C3;
InitLong(&m); InitLong(&s1); InitLong(&s2);
InitLong(&C1); InitLong(&C2); InitLong(&C3);
SubLong(xP, xQ, &C1);
OstLongA(&C1, p);
SubLong(yP, yQ, &C2);
OstLongA(&C2, p);
// Проверка на особые точки
if(IsNulLong(xP) && IsNulLong(yP)){
*xR = *xQ; *yR = *yQ;
return;
}
if(IsNulLong(xQ) && IsNulLong(yQ)){
*xR = *xP; *yR = *yP;
return;
}
if(IsNulLong(&C1) && IsNulLong(&C2)){
// Удвоение
MulTwoLong(xP, xP, &C1);
OstLongA(&C1, p);
MulA(&C1, 3);
DigToArray(a, &C2);
SumLongA(&C1, &C2);
OstLong(&C1, &s1, p);
Mul(yP, 2, &C1);
OstLong(&C1, &C2, p);
invA(&C2, &s2, p);
OstLongA(&s2, p);
} else {
// Обычное сложение
OstLong(&C2, &s1, p);
OstLong(&C1, &C3, p);
invA(&C3, &s2, p);
OstLongA(&s2, p);
}
MulTwoLong(&s1, &s2, &m);
OstLongA(&m, p);
MulTwoLong(&m, &m, &C1);
OstLongA(&C1, p);
SumLong(xP, xQ, &C2);
OstLongA(&C2, p);
SubLong(&C1, &C2, xR);
OstLongA(xR, p);
SubLong(xR, xP, &C1);
OstLongA(&C1, p);
MulTwoLong(&C1, &m, &C2);
OstLongA(&C2, p);
SumLong(yP, &C2, yR);
OstLongA(yR, p);
yR->sign = -yR->sign;
OstLongA(yR, p);
}
// ============ MAIN ============
int main() {
LDig xG, yG, xP, yP, xR, yR;
LDig p_mod;
printf("=== Задание №5: Сложение точек G + P ===\n\n");
// Инициализация модуля p
InitLong(&p_mod);
Read16Long(&p_mod, ps);
// Инициализация точки G
InitLong(&xG);
InitLong(&yG);
Read16Long(&xG, xGs);
Read16Long(&yG, yGs);
// Инициализация точки P (из задания)
InitLong(&xP);
InitLong(&yP);
Read16Long(&xP, "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9");
Read16Long(&yP, "388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672");
printf("Параметры кривой:\n");
printf("p = %s\n", ps);
printf("a = %d\n", a);
printf("b = %d\n\n", b);
printf("Точка G:\n");
printf("xG = "); ShowLongS(&xG);
printf("yG = "); ShowLongS(&yG);
printf("\n");
printf("Точка P:\n");
printf("xP = "); ShowLongS(&xP);
printf("yP = "); ShowLongS(&yP);
printf("\n");
// Вычисляем G + P
InitLong(&xR);
InitLong(&yR);
AddPoint(&xG, &yG, &xP, &yP, &xR, &yR, &p_mod);
printf("Результат G + P:\n");
printf("xR = "); ShowLongS(&xR);
printf("yR = "); ShowLongS(&yR);
return 0;
}