Last active
January 21, 2021 15:00
-
-
Save Fighter19/d40e77c8fe572d2faf8542bb63885918 to your computer and use it in GitHub Desktop.
Simple RSA implementation for encrypting 16-bit values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright 2021 Patrick Zacharias | |
// Do what you want with it, no guarantees given. | |
// Provided under MIT or BSD-2 license, if required by law. | |
#include <time.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <math.h> | |
// This doesn't implement real RSA, rather a simpler version with a much smaller keysize | |
// Only really used for very simple signings. Easily bruteforced. Do NOT use for sensitive information or similar. | |
struct rsa_public_key { | |
uint32_t modulus; // n | |
uint16_t pub_exp; // e | |
}; | |
struct rsa_priv_key { | |
struct rsa_public_key pub_key; | |
uint16_t priv_exp; // d | |
uint16_t prime1; // p | |
uint16_t prime2; // q | |
}; | |
int gcd(int a, int b) { | |
int gcd = 0; | |
while(b != 0){ | |
gcd = a % b; | |
a = b; | |
b = gcd; | |
} | |
return a; | |
} | |
int main() { | |
uint16_t timestamp; | |
// Used for key generation | |
uint32_t phi; | |
uint32_t remainder; | |
timestamp = time(0) / 65536; | |
struct rsa_priv_key priv_key; | |
// Chose two prime numbers of your choice here, make them big enough, as they will influence modulus, | |
// thus the maximum size of the encryptable content | |
priv_key.prime1 = 0; | |
priv_key.prime2 = 0; | |
// These two must be calculated using the commented blocks below | |
priv_key.pub_key.pub_exp = 0; | |
priv_key.priv_exp = 0; | |
priv_key.pub_key.modulus = priv_key.prime1 * priv_key.prime2; | |
printf("Current time: %d\n", timestamp); | |
printf("Private key: %d\n", priv_key.priv_exp); | |
printf("Public key: %d\n", priv_key.pub_key.pub_exp); | |
printf("Modulus: %d\n", priv_key.pub_key.modulus); | |
phi = (priv_key.prime1-1) * (priv_key.prime2-1); | |
printf("Phi: %d\n", phi); | |
// Use this to get the value for e => when gcd(e,phi) = 1 | |
/* | |
for (int i = 1; i < phi; i++) { | |
remainder = gcd(i, phi); | |
if (remainder == 1) { | |
printf("Found gcd: %d\n", i); | |
} | |
} | |
*/ | |
// result is priv_exp | |
/* | |
for (int i = 1; i < phi; i++) { | |
remainder = (i*priv_key.priv_exp) % phi; | |
if (remainder == 1) { | |
printf("Found d: %d\n", i); | |
} | |
} | |
*/ | |
// d is public_exp | |
printf("RSA Test\n"); | |
printf("Test %llu\n", (long long unsigned int)priv_key.pub_key.pub_exp*(long long unsigned int)priv_key.priv_exp); | |
long long unsigned int result = 1; | |
// Instead of | |
#ifdef DO_TEST | |
long long unsigned int biggest_result = 0; | |
/* pow(timestamp, priv_key.pub_key.pub_exp*priv_key.priv_exp); */ | |
for (long long unsigned int i = 0; i < priv_key.pub_key.pub_exp*priv_key.priv_exp; i++) { | |
result *= timestamp; | |
if (result > biggest_result) | |
biggest_result = result; | |
result = result % priv_key.pub_key.modulus; | |
} | |
uint64_t test1 = result % priv_key.pub_key.modulus; | |
uint64_t test2 = timestamp % priv_key.pub_key.modulus; | |
printf("big r: %llu\n", biggest_result); | |
printf("Test1: %lu\n", test1); | |
printf("Test2: %lu\n", test2); | |
#endif | |
uint64_t encrypted = 1; | |
for (long long unsigned int i = 0; i < priv_key.priv_exp; i++) { | |
encrypted *= timestamp; | |
encrypted = encrypted % priv_key.pub_key.modulus; | |
} | |
uint64_t decrypted = 1; | |
for (long long unsigned int i = 0; i < priv_key.pub_key.pub_exp; i++) { | |
decrypted *= encrypted; | |
decrypted = decrypted % priv_key.pub_key.modulus; | |
} | |
printf("Enc: %lu\n", encrypted); | |
printf("Dec: %lu\n", decrypted); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment