This commit is contained in:
klein panic
2025-02-01 16:14:45 -05:00
commit 3aff0baacf
82 changed files with 1694 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
#include "ecc.h"
#include <stdio.h>
#include <stdlib.h>
// Modular inverse using extended Euclidean algorithm
static uint64_t mod_inverse(uint64_t a, uint64_t m) {
int64_t m0 = m, t, q;
int64_t x0 = 0, x1 = 1;
if (m == 1)
return 0;
while (a > 1) {
q = a / m;
t = m;
m = a % m;
a = t;
t = x0;
x0 = x1 - q * x0;
x1 = t;
}
if (x1 < 0)
x1 += m0;
return x1;
}
// Modular arithmetic: Add two points P + Q
ECPoint ecc_point_add(ECPoint P, ECPoint Q, EllipticCurve curve) {
ECPoint R;
if (P.x == 0 && P.y == 0) return Q;
if (Q.x == 0 && Q.y == 0) return P;
if (P.x == Q.x && P.y == Q.y) {
return ecc_point_double(P, curve); // Doubling case
}
uint64_t lambda = ((Q.y + curve.p - P.y) * mod_inverse((Q.x + curve.p - P.x) % curve.p, curve.p)) % curve.p;
R.x = (lambda * lambda + curve.p - P.x + curve.p - Q.x) % curve.p;
R.y = (lambda * (P.x + curve.p - R.x) + curve.p - P.y) % curve.p;
return R;
}
// Doubling case: 2P
ECPoint ecc_point_double(ECPoint P, EllipticCurve curve) {
ECPoint R;
uint64_t lambda = ((3 * P.x * P.x + curve.a) * mod_inverse(2 * P.y, curve.p)) % curve.p;
R.x = (lambda * lambda + curve.p - 2 * P.x) % curve.p;
R.y = (lambda * (P.x + curve.p - R.x) + curve.p - P.y) % curve.p;
return R;
}
// Scalar multiplication: kP (repeated point addition)
ECPoint ecc_scalar_mult(uint64_t k, ECPoint P, EllipticCurve curve) {
ECPoint R = {0, 0}; // Point at infinity
ECPoint temp = P;
while (k > 0) {
if (k & 1) {
R = ecc_point_add(R, temp, curve);
}
temp = ecc_point_double(temp, curve);
k >>= 1;
}
return R;
}
// Key generation: Generate private and public key
ECCKeyPair ecc_generate_keypair(EllipticCurve curve) {
uint64_t private_key = rand() % curve.n;
ECPoint public_key = ecc_scalar_mult(private_key, curve.generator, curve);
ECCKeyPair keypair = {private_key, public_key};
return keypair;
}
// ECC encryption: Encrypts the plaintext and returns C1 (curve point) and C2 (encrypted message)
void ecc_encrypt(uint64_t plaintext, ECPoint public_key, EllipticCurve curve, ECPoint *C1, uint64_t *C2) {
uint64_t k = rand() % curve.n; // Random scalar for encryption
*C1 = ecc_scalar_mult(k, curve.generator, curve); // C1 = kG
ECPoint shared_secret = ecc_scalar_mult(k, public_key, curve); // kP
*C2 = plaintext ^ (shared_secret.x % 256); // XOR plaintext with shared secret's x-coordinate (mod 256)
}
// ECC decryption: Takes C1 and C2 to recover the original plaintext
uint64_t ecc_decrypt(ECPoint C1, uint64_t C2, uint64_t private_key, EllipticCurve curve) {
ECPoint shared_secret = ecc_scalar_mult(private_key, C1, curve); // dC1
return C2 ^ (shared_secret.x % 256); // XOR with shared secret's x-coordinate to recover plaintext
}

View File

@@ -0,0 +1,92 @@
#include "ecc.h"
#include <stdio.h>
#include <stdlib.h>
// Modular inverse using extended Euclidean algorithm
static uint64_t mod_inverse(uint64_t a, uint64_t m) {
int64_t m0 = m, t, q;
int64_t x0 = 0, x1 = 1;
if (m == 1)
return 0;
while (a > 1) {
q = a / m;
t = m;
m = a % m;
a = t;
t = x0;
x0 = x1 - q * x0;
x1 = t;
}
if (x1 < 0)
x1 += m0;
return x1;
}
// Modular arithmetic: Add two points P + Q
ECPoint ecc_point_add(ECPoint P, ECPoint Q, EllipticCurve curve) {
ECPoint R;
if (P.x == Q.x && P.y == Q.y) {
return ecc_point_double(P, curve); // Doubling case
}
uint64_t lambda = ((Q.y + curve.p - P.y) * mod_inverse((Q.x + curve.p - P.x) % curve.p, curve.p)) % curve.p;
R.x = (lambda * lambda + curve.p - P.x + curve.p - Q.x) % curve.p;
R.y = (lambda * (P.x + curve.p - R.x) + curve.p - P.y) % curve.p;
return R;
}
// Doubling case: 2P
ECPoint ecc_point_double(ECPoint P, EllipticCurve curve) {
ECPoint R;
uint64_t lambda = ((3 * P.x * P.x + curve.a) * mod_inverse(2 * P.y, curve.p)) % curve.p;
R.x = (lambda * lambda + curve.p - 2 * P.x) % curve.p;
R.y = (lambda * (P.x + curve.p - R.x) + curve.p - P.y) % curve.p;
return R;
}
// Scalar multiplication: kP (repeated point addition)
ECPoint ecc_scalar_mult(uint64_t k, ECPoint P, EllipticCurve curve) {
ECPoint R = {0, 0}; // Point at infinity
ECPoint temp = P;
while (k > 0) {
if (k & 1) {
R = ecc_point_add(R, temp, curve);
}
temp = ecc_point_double(temp, curve);
k >>= 1;
}
return R;
}
// Key generation: Generate private and public key
ECCKeyPair ecc_generate_keypair(EllipticCurve curve) {
uint64_t private_key = rand() % curve.n;
ECPoint public_key = ecc_scalar_mult(private_key, curve.generator, curve);
ECCKeyPair keypair = {private_key, public_key};
return keypair;
}
// Encryption using ECC
void ecc_encrypt(uint64_t plaintext, ECPoint public_key, EllipticCurve curve, ECPoint *C1, uint64_t *C2) {
uint64_t k = rand() % curve.n;
*C1 = ecc_scalar_mult(k, curve.generator, curve); // C1 = kG
ECPoint shared_secret = ecc_scalar_mult(k, public_key, curve); // kP
*C2 = plaintext ^ shared_secret.x; // XOR plaintext with shared secret's x-coordinate
}
// Decryption using ECC
uint64_t ecc_decrypt(ECPoint C1, uint64_t C2, uint64_t private_key, EllipticCurve curve) {
ECPoint shared_secret = ecc_scalar_mult(private_key, C1, curve); // dC1
return C2 ^ shared_secret.x; // XOR with shared secret to recover plaintext
}

View File

@@ -0,0 +1,33 @@
#include "ecc.h"
#include <stdio.h>
int main() {
// Define the elliptic curve
EllipticCurve curve = {
.a = 2,
.b = 3,
.p = 97, // Small prime for simplicity
.generator = {3, 6}, // Generator point
.n = 5 // Order of the generator
};
// Generate keypair for ECC
ECCKeyPair keypair = ecc_generate_keypair(curve);
printf("Private Key: %lu\n", keypair.private_key);
printf("Public Key: (%lu, %lu)\n", keypair.public_key.x, keypair.public_key.y);
// Encrypt a message
uint64_t plaintext = 42;
printf("Plaintext: %lu\n", plaintext);
ECPoint C1;
uint64_t C2;
ecc_encrypt(plaintext, keypair.public_key, curve, &C1, &C2);
printf("Ciphertext: (C1: %lu, %lu), C2: %lu\n", C1.x, C1.y, C2);
// Decrypt the message
uint64_t decrypted = ecc_decrypt(C1, C2, keypair.private_key, curve);
printf("Decrypted: %lu\n", decrypted);
return 0;
}