Untitled

 avatar
unknown
plain_text
6 months ago
10 kB
6
Indexable
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

// Número de chaves privadas a serem geradas
#define NUM_KEYS 10  // Ajuste conforme necessário

// Definição de um inteiro de 256 bits
typedef struct {
    uint32_t data[8];  // 8 * 32 bits = 256 bits
} uint256_t;

// Parâmetros da curva elíptica secp256k1
const uint256_t prime = { .data = {0xFFFFFC2F, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
                                   0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF} };

const uint256_t a_curve = { .data = {0} };
const uint256_t b_curve = { .data = {7} };

const uint256_t Gx = { .data = {0xF81798, 0xF2815B16, 0x2DCE28D9, 0xBFCDB2D,
                                0x870B070, 0xCE870B0, 0x5A06295C, 0x79BE667E} };

const uint256_t Gy = { .data = {0xB10D4B8, 0x9C47D08F, 0xA6855419, 0xFD17B448,
                                0xE1108A8, 0xDA4FBFC0, 0x3ADA7726, 0x483ADA77} };

// Função para imprimir um uint256_t em hexadecimal
void print_uint256(const uint256_t *num) {
    for (int i = 7; i >= 0; i--) {
        printf("%08x", num->data[i]);
    }
}

// Função para gerar uma chave privada aleatória
void generate_private_key(uint256_t *priv_key) {
    for (int i = 0; i < 8; i++) {
        priv_key->data[i] = rand();
    }
}

// Funções de operações aritméticas com uint256_t
void uint256_add(uint256_t *result, const uint256_t *a, const uint256_t *b) {
    uint64_t carry = 0;
    for (int i = 0; i < 8; i++) {
        uint64_t sum = (uint64_t)a->data[i] + b->data[i] + carry;
        result->data[i] = (uint32_t)sum;
        carry = sum >> 32;
    }
}

void uint256_sub(uint256_t *result, const uint256_t *a, const uint256_t *b) {
    uint64_t borrow = 0;
    for (int i = 0; i < 8; i++) {
        uint64_t diff = (uint64_t)a->data[i] - b->data[i] - borrow;
        result->data[i] = (uint32_t)diff;
        borrow = (diff >> 63) & 1;  // Correção do sinal de borrow
    }
}

void uint256_copy(uint256_t *dest, const uint256_t *src) {
    memcpy(dest->data, src->data, sizeof(uint32_t) * 8);
}

// Comparação de uint256_t
int uint256_cmp(const uint256_t *a, const uint256_t *b) {
    for (int i = 7; i >= 0; i--) {
        if (a->data[i] > b->data[i]) return 1;
        if (a->data[i] < b->data[i]) return -1;
    }
    return 0;
}

// Modulo: result = a mod mod
void uint256_mod(uint256_t *result, const uint256_t *a, const uint256_t *mod) {
    uint256_t temp;
    uint256_copy(&temp, a);
    while (uint256_cmp(&temp, mod) >= 0) {
        uint256_sub(&temp, &temp, mod);
    }
    uint256_copy(result, &temp);
}

// Multiplicação: result = (a * b) mod mod
void uint256_mul_mod(uint256_t *result, const uint256_t *a, const uint256_t *b, const uint256_t *mod) {
    uint256_t temp = {0};
    uint256_t a_copy;
    uint256_copy(&a_copy, a);

    for (int i = 0; i < 256; i++) {
        if ((b->data[i / 32] >> (i % 32)) & 1) {
            uint256_add(&temp, &temp, &a_copy);
            uint256_mod(&temp, &temp, mod);
        }
        // a_copy = (a_copy * 2) mod mod
        uint256_add(&a_copy, &a_copy, &a_copy);
        uint256_mod(&a_copy, &a_copy, mod);
    }
    uint256_copy(result, &temp);
}

// Inverso modular usando o Algoritmo de Euclides Estendido
void uint256_modinv(uint256_t *result, const uint256_t *a, const uint256_t *mod) {
    uint256_t t = {0}, newt = {0};
    t.data[0] = 0;
    newt.data[0] = 1;

    uint256_t r, newr;
    uint256_copy(&r, mod);
    uint256_copy(&newr, a);

    uint256_t quotient, temp1, temp2;

    while (uint256_cmp(&newr, &(uint256_t){0}) != 0) {
        // quotient = r / newr
        // Aqui, para simplificar, assumimos que newr é menor que r e que o quociente é 1
        quotient.data[0] = 1;

        // (t, newt) = (newt, t - quotient * newt)
        uint256_copy(&temp1, &newt);
        uint256_mul_mod(&temp2, &quotient, &newt, mod);
        uint256_sub(&newt, &t, &temp2);
        uint256_copy(&t, &temp1);

        // (r, newr) = (newr, r - quotient * newr)
        uint256_copy(&temp1, &newr);
        uint256_mul_mod(&temp2, &quotient, &newr, mod);
        uint256_sub(&newr, &r, &temp2);
        uint256_copy(&r, &temp1);
    }

    if (uint256_cmp(&r, &(uint256_t){ .data = {1} }) > 0) {
        // Não invertível
        memset(result->data, 0, sizeof(uint32_t) * 8);
        return;
    }

    if (uint256_cmp(&t, &(uint256_t){0}) < 0) {
        uint256_add(&t, &t, mod);
    }

    uint256_copy(result, &t);
}

// Operações na curva elíptica
void point_double(uint256_t *Rx, uint256_t *Ry, const uint256_t *Px, const uint256_t *Py) {
    if (uint256_cmp(Py, &(uint256_t){0}) == 0) {
        memset(Rx->data, 0, sizeof(uint32_t) * 8);
        memset(Ry->data, 0, sizeof(uint32_t) * 8);
        return;
    }

    uint256_t s, tmp1, tmp2, tmp3;

    // s = (3 * Px^2) * (2 * Py)^-1 mod p
    uint256_mul_mod(&tmp1, Px, Px, &prime);          // tmp1 = Px^2
    uint256_add(&tmp2, &tmp1, &tmp1);                // tmp2 = 2 * Px^2
    uint256_add(&tmp1, &tmp1, &tmp2);                // tmp1 = 3 * Px^2

    uint256_add(&tmp2, Py, Py);                      // tmp2 = 2 * Py
    uint256_modinv(&tmp2, &tmp2, &prime);            // tmp2 = (2 * Py)^-1

    uint256_mul_mod(&s, &tmp1, &tmp2, &prime);       // s = (3 * Px^2) / (2 * Py)

    // Rx = s^2 - 2 * Px
    uint256_mul_mod(&tmp1, &s, &s, &prime);          // tmp1 = s^2
    uint256_add(&tmp2, Px, Px);                      // tmp2 = 2 * Px
    uint256_sub(&tmp1, &tmp1, &tmp2);                // tmp1 = s^2 - 2 * Px
    uint256_mod(&tmp1, &tmp1, &prime);               // tmp1 = Rx

    // Ry = s * (Px - Rx) - Py
    uint256_sub(&tmp2, Px, &tmp1);                   // tmp2 = Px - Rx
    uint256_mul_mod(&tmp2, &s, &tmp2, &prime);       // tmp2 = s * (Px - Rx)
    uint256_sub(&tmp2, &tmp2, Py);                   // tmp2 = s * (Px - Rx) - Py
    uint256_mod(&tmp2, &tmp2, &prime);               // tmp2 = Ry

    uint256_copy(Rx, &tmp1);
    uint256_copy(Ry, &tmp2);
}

void point_add(uint256_t *Rx, uint256_t *Ry,
               const uint256_t *Px, const uint256_t *Py,
               const uint256_t *Qx, const uint256_t *Qy) {
    if (uint256_cmp(Px, &(uint256_t){0}) == 0 && uint256_cmp(Py, &(uint256_t){0}) == 0) {
        uint256_copy(Rx, Qx);
        uint256_copy(Ry, Qy);
        return;
    }
    if (uint256_cmp(Qx, &(uint256_t){0}) == 0 && uint256_cmp(Qy, &(uint256_t){0}) == 0) {
        uint256_copy(Rx, Px);
        uint256_copy(Ry, Py);
        return;
    }

    uint256_t s, tmp1, tmp2;

    // s = (Qy - Py) * (Qx - Px)^-1 mod p
    uint256_sub(&tmp1, Qy, Py);                      // tmp1 = Qy - Py
    uint256_sub(&tmp2, Qx, Px);                      // tmp2 = Qx - Px
    uint256_modinv(&tmp2, &tmp2, &prime);            // tmp2 = (Qx - Px)^-1

    uint256_mul_mod(&s, &tmp1, &tmp2, &prime);       // s = (Qy - Py) / (Qx - Px)

    // Rx = s^2 - Px - Qx
    uint256_mul_mod(&tmp1, &s, &s, &prime);          // tmp1 = s^2
    uint256_sub(&tmp1, &tmp1, Px);                   // tmp1 = s^2 - Px
    uint256_sub(&tmp1, &tmp1, Qx);                   // tmp1 = s^2 - Px - Qx
    uint256_mod(&tmp1, &tmp1, &prime);               // tmp1 = Rx

    // Ry = s * (Px - Rx) - Py
    uint256_sub(&tmp2, Px, &tmp1);                   // tmp2 = Px - Rx
    uint256_mul_mod(&tmp2, &s, &tmp2, &prime);       // tmp2 = s * (Px - Rx)
    uint256_sub(&tmp2, &tmp2, Py);                   // tmp2 = s * (Px - Rx) - Py
    uint256_mod(&tmp2, &tmp2, &prime);               // tmp2 = Ry

    uint256_copy(Rx, &tmp1);
    uint256_copy(Ry, &tmp2);
}

// Multiplicação escalar: R = k * P
void scalar_mult(uint256_t *Rx, uint256_t *Ry, const uint256_t *k, const uint256_t *Px, const uint256_t *Py) {
    uint256_t Qx = {0}, Qy = {0};
    uint256_t Px_copy, Py_copy;
    uint256_copy(&Px_copy, Px);
    uint256_copy(&Py_copy, Py);

    for (int i = 0; i < 256; i++) {
        if ((k->data[i / 32] >> (i % 32)) & 1) {
            point_add(&Qx, &Qy, &Qx, &Qy, &Px_copy, &Py_copy);
        }
        point_double(&Px_copy, &Py_copy, &Px_copy, &Py_copy);
    }
    uint256_copy(Rx, &Qx);
    uint256_copy(Ry, &Qy);
}

// Função de hash Keccak-256 simplificada (não é uma implementação real)
void keccak_256(const uint8_t *input, size_t input_len, uint8_t *output) {
    // Implementação simplificada - preenche output com zeros
    memset(output, 0, 32);
}

// Converter chave pública em endereço Ethereum
void public_key_to_address(uint8_t *public_key, uint8_t *address) {
    uint8_t hash[32];
    keccak_256(public_key + 1, 64, hash); // Ignora o byte 0x04
    memcpy(address, hash + 12, 20);
}

// Função principal
int main() {
    srand(time(NULL));

    clock_t start_time = clock();

    for (int i = 0; i < NUM_KEYS; i++) {
        // Gerar chave privada aleatória
        uint256_t priv_key;
        generate_private_key(&priv_key);

        // Calcular a chave pública
        uint256_t pub_x, pub_y;
        scalar_mult(&pub_x, &pub_y, &priv_key, &Gx, &Gy);

        // Converter chave pública para bytes
        uint8_t public_key[65];
        public_key[0] = 0x04;

        for (int j = 0; j < 8; j++) {
            public_key[1 + j * 4 + 0] = (pub_x.data[7 - j] >> 24) & 0xFF;
            public_key[1 + j * 4 + 1] = (pub_x.data[7 - j] >> 16) & 0xFF;
            public_key[1 + j * 4 + 2] = (pub_x.data[7 - j] >> 8) & 0xFF;
            public_key[1 + j * 4 + 3] = (pub_x.data[7 - j] >> 0) & 0xFF;
        }

        for (int j = 0; j < 8; j++) {
            public_key[33 + j * 4 + 0] = (pub_y.data[7 - j] >> 24) & 0xFF;
            public_key[33 + j * 4 + 1] = (pub_y.data[7 - j] >> 16) & 0xFF;
            public_key[33 + j * 4 + 2] = (pub_y.data[7 - j] >> 8) & 0xFF;
            public_key[33 + j * 4 + 3] = (pub_y.data[7 - j] >> 0) & 0xFF;
        }

        // Calcular o endereço Ethereum
        uint8_t address[20];
        public_key_to_address(public_key, address);

        // Opcional: imprimir o endereço
        // printf("Endereço Ethereum: 0x");
        // for (int j = 0; j < 20; j++) {
        //     printf("%02x", address[j]);
        // }
        // printf("\n");
    }

    clock_t end_time = clock();

    double time_spent = (double)(end_time - start_time) / CLOCKS_PER_SEC;
    printf("Tempo total de execução para %d chaves: %.2f segundos\n", NUM_KEYS, time_spent);
    printf("Chaves geradas por segundo: %.2f\n", NUM_KEYS / time_spent);

    return 0;
}
Editor is loading...
Leave a Comment