Загрузка данных


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// Параметры кривой secp256k1: y^2 = x^3 + 7 mod p
const char* p_hex = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F";
const char* a_hex = "0000000000000000000000000000000000000000000000000000000000000000";
const char* b_hex = "0000000000000000000000000000000000000000000000000000000000000007";

// Базовая точка G (генератор)
const char* Gx_hex = "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798";
const char* Gy_hex = "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8";

// Точка P (пример: P = G, но можно подставить другую)
const char* Px_hex = "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798";
const char* Py_hex = "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8";

// Функции для работы с 256-битными числами в hex
void add_hex(const char* a, const char* b, char* result);
void sub_hex(const char* a, const char* b, char* result);
void mul_hex(const char* a, const char* b, char* result);
void mod_hex(const char* a, const char* m, char* result);
void inverse_hex(const char* a, const char* m, char* result);
void point_add(const char* x1, const char* y1, const char* x2, const char* y2, char* x3, char* y3);
int compare_hex(const char* a, const char* b);
void trim_leading_zeros(char* str);

// Вспомогательная: преобразование hex символа в число
int hex_char_to_int(char c) {
    if (c >= '0' && c <= '9') return c - '0';
    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
    if (c >= 'A' && c <= 'F') return c - 'A' + 10;
    return 0;
}

char int_to_hex_char(int n) {
    if (n < 10) return '0' + n;
    return 'A' + (n - 10);
}

// Удаление ведущих нулей
void trim_leading_zeros(char* str) {
    int len = strlen(str);
    int start = 0;
    while (start < len - 1 && str[start] == '0') start++;
    if (start > 0) {
        for (int i = start; i <= len; i++) {
            str[i - start] = str[i];
        }
    }
}

// Сравнение двух hex строк
int compare_hex(const char* a, const char* b) {
    char a_trim[256], b_trim[256];
    strcpy(a_trim, a);
    strcpy(b_trim, b);
    trim_leading_zeros(a_trim);
    trim_leading_zeros(b_trim);
    
    int len_a = strlen(a_trim);
    int len_b = strlen(b_trim);
    
    if (len_a != len_b) return len_a - len_b;
    
    for (int i = 0; i < len_a; i++) {
        if (a_trim[i] != b_trim[i]) {
            return hex_char_to_int(a_trim[i]) - hex_char_to_int(b_trim[i]);
        }
    }
    return 0;
}

// Сложение двух hex строк
void add_hex(const char* a, const char* b, char* result) {
    char a_rev[256], b_rev[256];
    int res[256] = {0};
    int len_a = strlen(a);
    int len_b = strlen(b);
    
    // Переворачиваем строки
    for (int i = 0; i < len_a; i++) a_rev[i] = a[len_a - 1 - i];
    for (int i = 0; i < len_b; i++) b_rev[i] = b[len_b - 1 - i];
    
    int carry = 0;
    int max_len = len_a > len_b ? len_a : len_b;
    
    for (int i = 0; i < max_len; i++) {
        int da = (i < len_a) ? hex_char_to_int(a_rev[i]) : 0;
        int db = (i < len_b) ? hex_char_to_int(b_rev[i]) : 0;
        int sum = da + db + carry;
        res[i] = sum % 16;
        carry = sum / 16;
    }
    if (carry) res[max_len++] = carry;
    
    // Формируем результат
    for (int i = 0; i < max_len; i++) {
        result[i] = int_to_hex_char(res[max_len - 1 - i]);
    }
    result[max_len] = '\0';
    trim_leading_zeros(result);
}

// Вычитание (a >= b)
void sub_hex(const char* a, const char* b, char* result) {
    char a_rev[256], b_rev[256];
    int res[256] = {0};
    int len_a = strlen(a);
    int len_b = strlen(b);
    
    for (int i = 0; i < len_a; i++) a_rev[i] = a[len_a - 1 - i];
    for (int i = 0; i < len_b; i++) b_rev[i] = b[len_b - 1 - i];
    
    int borrow = 0;
    for (int i = 0; i < len_a; i++) {
        int da = hex_char_to_int(a_rev[i]);
        int db = (i < len_b) ? hex_char_to_int(b_rev[i]) : 0;
        int diff = da - db - borrow;
        if (diff < 0) {
            diff += 16;
            borrow = 1;
        } else {
            borrow = 0;
        }
        res[i] = diff;
    }
    
    int len = len_a;
    while (len > 1 && res[len - 1] == 0) len--;
    
    for (int i = 0; i < len; i++) {
        result[i] = int_to_hex_char(res[len - 1 - i]);
    }
    result[len] = '\0';
}

// Умножение двух hex чисел
void mul_hex(const char* a, const char* b, char* result) {
    int len_a = strlen(a);
    int len_b = strlen(b);
    int res[512] = {0};
    
    for (int i = len_a - 1; i >= 0; i--) {
        int da = hex_char_to_int(a[i]);
        for (int j = len_b - 1; j >= 0; j--) {
            int db = hex_char_to_int(b[j]);
            int pos = (len_a - 1 - i) + (len_b - 1 - j);
            res[pos] += da * db;
        }
    }
    
    for (int i = 0; i < 511; i++) {
        res[i + 1] += res[i] / 16;
        res[i] %= 16;
    }
    
    int len = 511;
    while (len > 0 && res[len] == 0) len--;
    
    for (int i = 0; i <= len; i++) {
        result[i] = int_to_hex_char(res[len - i]);
    }
    result[len + 1] = '\0';
}

// Деление и остаток (для модуля)
void divmod_hex(const char* a, const char* b, char* quotient, char* remainder) {
    char temp[512];
    strcpy(temp, a);
    trim_leading_zeros(temp);
    
    int q_pos = 0;
    char current[512] = "";
    
    for (int i = 0; i < strlen(temp); i++) {
        int len = strlen(current);
        current[len] = temp[i];
        current[len + 1] = '\0';
        trim_leading_zeros(current);
        
        int digit = 0;
        while (compare_hex(current, b) >= 0) {
            char temp_sub[512];
            sub_hex(current, b, temp_sub);
            strcpy(current, temp_sub);
            digit++;
        }
        if (digit >= 0 || q_pos > 0) {
            quotient[q_pos++] = int_to_hex_char(digit);
        }
    }
    if (q_pos == 0) quotient[q_pos++] = '0';
    quotient[q_pos] = '\0';
    strcpy(remainder, current);
    if (strlen(remainder) == 0) strcpy(remainder, "0");
}

// Модуль числа
void mod_hex(const char* a, const char* m, char* result) {
    char q[512], r[512];
    divmod_hex(a, m, q, r);
    strcpy(result, r);
}

// Расширенный алгоритм Евклида для обратного элемента
void inverse_hex(const char* a, const char* m, char* result) {
    char t[512], newt[512];
    char r[512], newr[512];
    strcpy(t, "0");
    strcpy(newt, "1");
    strcpy(r, m);
    strcpy(newr, a);
    
    char quotient[512], temp[512];
    
    while (compare_hex(newr, "0") != 0) {
        char q[512];
        divmod_hex(r, newr, q, temp);
        strcpy(quotient, q);
        
        // t, newt = newt, t - quotient * newt
        char mul_temp[512], sub_temp[512];
        mul_hex(quotient, newt, mul_temp);
        sub_hex(t, mul_temp, sub_temp);
        strcpy(t, newt);
        strcpy(newt, sub_temp);
        
        // r, newr = newr, r - quotient * newr
        mul_hex(quotient, newr, mul_temp);
        sub_hex(r, mul_temp, sub_temp);
        strcpy(r, newr);
        strcpy(newr, sub_temp);
        
        trim_leading_zeros(t);
        trim_leading_zeros(newt);
        trim_leading_zeros(r);
        trim_leading_zeros(newr);
    }
    
    while (compare_hex(t, "0") < 0) {
        char add_temp[512];
        add_hex(t, m, add_temp);
        strcpy(t, add_temp);
    }
    mod_hex(t, m, result);
}

// Сложение двух точек на эллиптической кривой
void point_add(const char* x1, const char* y1, const char* x2, const char* y2, char* x3, char* y3, const char* p) {
    if (strcmp(x1, "0") == 0 && strcmp(y1, "0") == 0) {
        strcpy(x3, x2);
        strcpy(y3, y2);
        return;
    }
    if (strcmp(x2, "0") == 0 && strcmp(y2, "0") == 0) {
        strcpy(x3, x1);
        strcpy(y3, y1);
        return;
    }
    
    char lambda[512], temp1[512], temp2[512], temp3[512], inv[512];
    
    if (strcmp(x1, x2) == 0 && strcmp(y1, y2) == 0) {
        // Удвоение: lambda = (3*x1^2 + a) / (2*y1)
        char x1_sq[512], three_x1_sq[512], two_y1[512];
        mul_hex(x1, x1, x1_sq);
        mul_hex(x1_sq, "3", three_x1_sq);
        add_hex(three_x1_sq, "0", temp1);  // a = 0
        mul_hex(y1, "2", two_y1);
        inverse_hex(two_y1, p, inv);
        mul_hex(temp1, inv, lambda);
    } else {
        // Сложение: lambda = (y2 - y1) / (x2 - x1)
        char dy[512], dx[512];
        sub_hex(y2, y1, dy);
        sub_hex(x2, x1, dx);
        inverse_hex(dx, p, inv);
        mul_hex(dy, inv, lambda);
    }
    mod_hex(lambda, p, lambda);
    
    // x3 = lambda^2 - x1 - x2
    char lambda_sq[512];
    mul_hex(lambda, lambda, lambda_sq);
    sub_hex(lambda_sq, x1, temp1);
    sub_hex(temp1, x2, x3);
    mod_hex(x3, p, x3);
    
    // y3 = lambda * (x1 - x3) - y1
    char x1_minus_x3[512];
    sub_hex(x1, x3, x1_minus_x3);
    mul_hex(lambda, x1_minus_x3, temp1);
    sub_hex(temp1, y1, y3);
    mod_hex(y3, p, y3);
}

int main() {
    printf("=== Задание №5: Сложение точек G + P ===\n");
    printf("Полная реализация арифметики эллиптической кривой secp256k1\n\n");
    
    printf("Параметры кривой:\n");
    printf("p = %s\n", p_hex);
    printf("a = %s\n", a_hex);
    printf("b = %s\n\n", b_hex);
    
    printf("Точка G (генератор):\n");
    printf("x = %s\n", Gx_hex);
    printf("y = %s\n\n", Gy_hex);
    
    printf("Точка P:\n");
    printf("x = %s\n", Px_hex);
    printf("y = %s\n\n", Py_hex);
    
    char Rx[512], Ry[512];
    point_add(Gx_hex, Gy_hex, Px_hex, Py_hex, Rx, Ry, p_hex);
    
    printf("Результат G + P:\n");
    printf("x = %s\n", Rx);
    printf("y = %s\n", Ry);
    
    return 0;
}