cs-3333: add rsa project
This commit is contained in:
parent
7bba42bf07
commit
e08b77cb1b
244
Fall-2024/CS-3333/Assignments/RSA-Project/.clang-format
Normal file
244
Fall-2024/CS-3333/Assignments/RSA-Project/.clang-format
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
# BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -2
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignArrayOfStructures: None
|
||||||
|
AlignConsecutiveAssignments:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: true
|
||||||
|
AlignConsecutiveBitFields:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: false
|
||||||
|
AlignConsecutiveDeclarations:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: false
|
||||||
|
AlignConsecutiveMacros:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: false
|
||||||
|
AlignConsecutiveShortCaseStatements:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCaseColons: false
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: Align
|
||||||
|
AlignTrailingComments:
|
||||||
|
Kind: Always
|
||||||
|
OverEmptyLines: 0
|
||||||
|
AllowAllArgumentsOnNextLine: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowBreakBeforeNoexceptSpecifier: Never
|
||||||
|
AllowShortBlocksOnASingleLine: Never
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortCompoundRequirementOnASingleLine: true
|
||||||
|
AllowShortEnumsOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLambdasOnASingleLine: All
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: MultiLine
|
||||||
|
AttributeMacros:
|
||||||
|
- __capability
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BitFieldColonSpacing: Both
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: Never
|
||||||
|
AfterEnum: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
BeforeLambdaBody: false
|
||||||
|
BeforeWhile: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakAdjacentStringLiterals: true
|
||||||
|
BreakAfterAttributes: Leave
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakArrays: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeConceptDeclarations: Always
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeInlineASMColon: OnlyMultiline
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 80
|
||||||
|
CommentPragmas: "^ IWYU pragma:"
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
EmptyLineAfterAccessModifier: Never
|
||||||
|
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IfMacros:
|
||||||
|
- KJ_IF_MAYBE
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||||
|
Priority: 2
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||||
|
Priority: 3
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: ".*"
|
||||||
|
Priority: 1
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
IncludeIsMainRegex: "(Test)?$"
|
||||||
|
IncludeIsMainSourceRegex: ""
|
||||||
|
IndentAccessModifiers: false
|
||||||
|
IndentCaseBlocks: false
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentExternBlock: AfterExternBlock
|
||||||
|
IndentGotoLabels: true
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentRequiresClause: true
|
||||||
|
IndentWidth: 4
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
InsertBraces: false
|
||||||
|
InsertNewlineAtEOF: false
|
||||||
|
InsertTrailingCommas: None
|
||||||
|
IntegerLiteralSeparator:
|
||||||
|
Binary: 0
|
||||||
|
BinaryMinDigits: 0
|
||||||
|
Decimal: 0
|
||||||
|
DecimalMinDigits: 0
|
||||||
|
Hex: 0
|
||||||
|
HexMinDigits: 0
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
KeepEmptyLinesAtEOF: false
|
||||||
|
LambdaBodyIndentation: Signature
|
||||||
|
LineEnding: DeriveLF
|
||||||
|
MacroBlockBegin: ""
|
||||||
|
MacroBlockEnd: ""
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBinPackProtocolList: Auto
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCBreakBeforeNestedBlockParam: true
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PackConstructorInitializers: BinPack
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakOpenParenthesis: 0
|
||||||
|
PenaltyBreakScopeResolution: 500
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyIndentedWhitespace: 0
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
PointerAlignment: Right
|
||||||
|
PPIndentWidth: -1
|
||||||
|
QualifierAlignment: Leave
|
||||||
|
ReferenceAlignment: Pointer
|
||||||
|
ReflowComments: true
|
||||||
|
RemoveBracesLLVM: false
|
||||||
|
RemoveParentheses: Leave
|
||||||
|
RemoveSemicolon: false
|
||||||
|
RequiresClausePosition: OwnLine
|
||||||
|
RequiresExpressionIndentation: OuterScope
|
||||||
|
SeparateDefinitionBlocks: Leave
|
||||||
|
ShortNamespaceLines: 1
|
||||||
|
SkipMacroDefinitionBody: false
|
||||||
|
SortIncludes: CaseSensitive
|
||||||
|
SortJavaStaticImport: Before
|
||||||
|
SortUsingDeclarations: LexicographicNumeric
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceAroundPointerQualifiers: Default
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCaseColon: false
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeJsonColon: false
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeParensOptions:
|
||||||
|
AfterControlStatements: true
|
||||||
|
AfterForeachMacros: true
|
||||||
|
AfterFunctionDefinitionName: false
|
||||||
|
AfterFunctionDeclarationName: false
|
||||||
|
AfterIfMacros: true
|
||||||
|
AfterOverloadedOperator: false
|
||||||
|
AfterPlacementOperator: true
|
||||||
|
AfterRequiresInClause: false
|
||||||
|
AfterRequiresInExpression: false
|
||||||
|
BeforeNonEmptyParentheses: false
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceBeforeSquareBrackets: false
|
||||||
|
SpaceInEmptyBlock: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: Never
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInLineCommentPrefix:
|
||||||
|
Minimum: 1
|
||||||
|
Maximum: -1
|
||||||
|
SpacesInParens: Never
|
||||||
|
SpacesInParensOptions:
|
||||||
|
InCStyleCasts: false
|
||||||
|
InConditionalStatements: false
|
||||||
|
InEmptyParentheses: false
|
||||||
|
Other: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Latest
|
||||||
|
StatementAttributeLikeMacros:
|
||||||
|
- Q_EMIT
|
||||||
|
StatementMacros:
|
||||||
|
- Q_UNUSED
|
||||||
|
- QT_REQUIRE_VERSION
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: Never
|
||||||
|
VerilogBreakBetweenInstancePorts: true
|
||||||
|
WhitespaceSensitiveMacros:
|
||||||
|
- BOOST_PP_STRINGIZE
|
||||||
|
- CF_SWIFT_NAME
|
||||||
|
- NS_SWIFT_NAME
|
||||||
|
- PP_STRINGIZE
|
||||||
|
- STRINGIZE
|
Binary file not shown.
Binary file not shown.
BIN
Fall-2024/CS-3333/Assignments/RSA-Project/docs/RSA Project.pdf
Normal file
BIN
Fall-2024/CS-3333/Assignments/RSA-Project/docs/RSA Project.pdf
Normal file
Binary file not shown.
213
Fall-2024/CS-3333/Assignments/RSA-Project/src/main.c
Normal file
213
Fall-2024/CS-3333/Assignments/RSA-Project/src/main.c
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
bool isPrime(unsigned long num) {
|
||||||
|
for (int i = 2; i * i <= num; i++) {
|
||||||
|
if (num % i == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the great common divisor (GCD) of two numbers recursively
|
||||||
|
*
|
||||||
|
* @param a first number
|
||||||
|
* @param b second number
|
||||||
|
* @return the gcd of both numbers
|
||||||
|
*/
|
||||||
|
unsigned long gcd(unsigned long a, unsigned long b) {
|
||||||
|
// NOTE: This really should be iterative with a while loop, recursion here
|
||||||
|
// is not ideal
|
||||||
|
return (b == 0) ? a : gcd(b, a % b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the great common divisor (GCD) of two numbers recursively
|
||||||
|
* via the Extended Euclidean Algorithm
|
||||||
|
*
|
||||||
|
* @param a First number to find GCD against b
|
||||||
|
* @param b Second number to find GCD against a
|
||||||
|
* @return the gcd of both numbers
|
||||||
|
*/
|
||||||
|
signed long long gcdExtended(signed long long a, signed long long b,
|
||||||
|
signed long long *x, signed long long *y) {
|
||||||
|
|
||||||
|
// Base Case
|
||||||
|
if (a == 0) {
|
||||||
|
*x = 0, *y = 1;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// To store results of recursive call
|
||||||
|
signed long long x1, y1;
|
||||||
|
signed long long gcd = gcdExtended(b % a, a, &x1, &y1);
|
||||||
|
|
||||||
|
// Update x and y using results of recursive
|
||||||
|
// call
|
||||||
|
*x = y1 - (b / a) * x1;
|
||||||
|
*y = x1;
|
||||||
|
|
||||||
|
return gcd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the modulo inverse using the extended Euclidean Algorithm
|
||||||
|
*
|
||||||
|
* @param a The value to be inverted mod a
|
||||||
|
* @param m The modulus, a positive integer greater than 1
|
||||||
|
*/
|
||||||
|
unsigned long modInverse(unsigned long a, unsigned long m) {
|
||||||
|
// You might notice the evil casting going on below. There's a really good
|
||||||
|
// reason for that! The extended euclidean algo. pretty much has a hard
|
||||||
|
// requirement on using signed integers. To satisfy this condition, we're
|
||||||
|
// using `signed long long` so we can safely fit the *unsigned long* value
|
||||||
|
// within. This allows "safe" casts back and forth without any loss.
|
||||||
|
//
|
||||||
|
// Some more enlightening information on this problem can be found at
|
||||||
|
// https://jeffhurchalla.com/2018/10/13/implementing-the-extended-euclidean-algorithm-with-unsigned-inputs/
|
||||||
|
//
|
||||||
|
// Frankly, there are much, MUCH, faster ways of doing this if we didn't
|
||||||
|
// *have* to use the extended euclidean algo. (mostly in the form of cursed
|
||||||
|
// bitshifting which FIPS-186-5 has some resources on 😉).
|
||||||
|
signed long long x, y, a_0 = (signed long long)a, m_0 = (signed long long)m;
|
||||||
|
signed long long g = gcdExtended(a_0, m_0, &x, &y);
|
||||||
|
if (g != 1) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to determine modular inverse for `%lu` and `%lu`, they "
|
||||||
|
"may not be coprime!\n",
|
||||||
|
a, m);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return (unsigned long)((x % m_0 + m_0) % m_0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Modular Exponentiation
|
||||||
|
*
|
||||||
|
* See
|
||||||
|
* https://www.cs.ucf.edu/~dmarino/ucf/cis3362/lectures/newlecs/FastModExpo.pdf
|
||||||
|
* for more information
|
||||||
|
*/
|
||||||
|
unsigned long modExp(unsigned long base, unsigned long exp, unsigned long num) {
|
||||||
|
if (exp == 0)
|
||||||
|
return 1;
|
||||||
|
if (exp == 1)
|
||||||
|
return base % num;
|
||||||
|
if (exp % 2 == 0) {
|
||||||
|
int t = modExp(base, exp / 2, num);
|
||||||
|
return (t * t) % num;
|
||||||
|
}
|
||||||
|
return (base * modExp(base, exp - 1, num)) % num;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long rprime(unsigned n) {
|
||||||
|
unsigned r = rand(), t;
|
||||||
|
while ((t = gcd(r, n)) > 1) {
|
||||||
|
r /= t;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate keys for RSA encryption given some p & q primes
|
||||||
|
*
|
||||||
|
* @param p first secret large prime number
|
||||||
|
* @param q second secret large primer number
|
||||||
|
* @param n will be set to the result of p * q
|
||||||
|
* @param e randomly chosen such that e < φ(n) and e & φ (n) are coprime
|
||||||
|
* @param d the mod inverse of e % φ(n), where e*d ≡ 1 (mod φ(n))
|
||||||
|
*/
|
||||||
|
void generateKeys(unsigned long p, unsigned long q, unsigned long *n,
|
||||||
|
unsigned long *e, unsigned long *d) {
|
||||||
|
*n = p * q;
|
||||||
|
unsigned long phi = (p - 1) * (q - 1);
|
||||||
|
|
||||||
|
while (gcd(*e, phi) != 1 && *e < phi) {
|
||||||
|
(*e)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*e >= phi) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to find valid `e` value for given `phi` value! `e`: "
|
||||||
|
"'%lu' | `phi`: '%lu'\n",
|
||||||
|
*e, phi);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
*d = modInverse(*e, phi);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Encrypt plaintext with RSA
|
||||||
|
*
|
||||||
|
* @param plaintext
|
||||||
|
* @param e Encryption key
|
||||||
|
* @param n Combined secret values
|
||||||
|
*/
|
||||||
|
unsigned long encrypt(unsigned long plaintext, unsigned long e,
|
||||||
|
unsigned long n) {
|
||||||
|
return modExp(plaintext, e, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to decrypt ciphertext using RSA
|
||||||
|
/**
|
||||||
|
* @brief Decrypt RSA encrypted ciphertext
|
||||||
|
*
|
||||||
|
* @param ciphertext The text to decrypt
|
||||||
|
* @param d Decryption key
|
||||||
|
* @param n Combined secret values
|
||||||
|
*/
|
||||||
|
unsigned long decrypt(unsigned long ciphertext, unsigned long d,
|
||||||
|
unsigned long n) {
|
||||||
|
return modExp(ciphertext, d, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
unsigned long p = 7; // prime number, try 3, 5, 7, 11, 13, ...
|
||||||
|
unsigned long q = 541; // prime number, try 3, 5, 7, 11, 13, ...
|
||||||
|
unsigned long e = 7;
|
||||||
|
|
||||||
|
unsigned long n, d;
|
||||||
|
|
||||||
|
// printf("Enter p and q: ");
|
||||||
|
// scanf("%lu %lu", &p, &q);
|
||||||
|
// Generate RSA keys
|
||||||
|
generateKeys(p, q, &n, &e, &d);
|
||||||
|
|
||||||
|
if (!isPrime(p)) {
|
||||||
|
fprintf(stderr, "Given `p` value was not prime, received '%lu'!\n", p);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPrime(q)) {
|
||||||
|
fprintf(stderr, "Given `q` value was not prime, received '%lu'!\n", q);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Public key (e, n): (%lu, %lu)\n", e, n);
|
||||||
|
printf("Private key (d, n): (%lu, %lu)\n\n", d, n);
|
||||||
|
|
||||||
|
// Encrypt and decrypt a sample plaintext, which we assume is given as an
|
||||||
|
// integer value
|
||||||
|
unsigned long plaintext;
|
||||||
|
printf("Enter an integer between 0 and %lu as plain text to be encrypted: ",
|
||||||
|
n - 1);
|
||||||
|
int _ = scanf("%lu", &plaintext);
|
||||||
|
if (plaintext > n - 1) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Unable to RSA encrypt & decrypt given `plaintext`: "
|
||||||
|
"'%lu'!\nPlaintext value was more than `n-1`: '%lu'\n",
|
||||||
|
plaintext, n - 1);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
printf("Original plaintext: %lu\n", plaintext);
|
||||||
|
unsigned long ciphertext = encrypt(plaintext, e, n);
|
||||||
|
printf("Encrypted ciphertext: %lu\n", ciphertext);
|
||||||
|
unsigned long decrypted = decrypt(ciphertext, d, n);
|
||||||
|
printf("Decrypted plaintext: %lu\n\n", decrypted);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user