You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
5.6 KiB
134 lines
5.6 KiB
/**
|
|
*--------------------------------------------------------------------\n
|
|
* HSLU T&A Hochschule Luzern Technik+Architektur \n
|
|
*--------------------------------------------------------------------\n
|
|
*
|
|
* \brief model solution for ASYD assignment crypto 04
|
|
* \file
|
|
* \author Stefano Nicora, stefano.nicora@hslu.ch
|
|
* \date 03.02.23
|
|
*
|
|
*--------------------------------------------------------------------
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include "DSA.h"
|
|
#include "encryptionArithmetic.h"
|
|
|
|
/* https://de.wikipedia.org/wiki/Digital_Signature_Algorithm#Parameter_erzeugen */
|
|
|
|
/* based on the square and multiply algorithm */
|
|
/* https://www.biancahoegel.de/mathe/zahl/primitivwurzel.html */
|
|
/* https://www.practicalnetworking.net/stand-alone/square-and-multiply/ */
|
|
/* https://math.stackexchange.com/questions/1472480/learning-square-and-multiply-algorithm */
|
|
|
|
void moduloOperation(t_encryptionArithmetic* result, t_encryptionArithmetic* modulo, uint32_t keyLength);
|
|
|
|
void squareAndMultiply(t_encryptionArithmetic* base, t_encryptionArithmetic* exponent, t_encryptionArithmetic* modulo, t_encryptionArithmetic* result, uint32_t keyLength) {
|
|
|
|
/* assign base to result as the first step defined in the square & multply algorithm */
|
|
for (uint8_t i = 0; i < (keyLength / 32); i++) {
|
|
*(result->number + i) = *(base->number + i);
|
|
}
|
|
|
|
/* get amount of bits representing the exponent */
|
|
uint16_t numberOfBits = encryptionArithmetic_numberSize(exponent->number, keyLength);
|
|
|
|
/* execute square and multiply algorithm */
|
|
for (int i = 0; i < numberOfBits - 1; i++) {
|
|
/* -2 as we already did store the base inside our number and therefore skip the MSB */
|
|
if (*(exponent->number) >> (numberOfBits - i - 2) & 1) /* if bit is 1 => multiply number with itself as well as with base */
|
|
{
|
|
encryptionArithmetic(result->number, result->number, result, keyLength, MUL); /* square */
|
|
encryptionArithmetic(result->number, base->number, result, keyLength, MUL); /* multiply */
|
|
}
|
|
else /* if bit is 0 => multiply number with itself */
|
|
{
|
|
encryptionArithmetic(result->number, result->number, result, keyLength, MUL); /* square */
|
|
}
|
|
moduloOperation(result, modulo, keyLength);
|
|
}
|
|
printf("Square and Multiply result: %u\n", *result->number);
|
|
}
|
|
|
|
void moduloOperation(t_encryptionArithmetic* number, t_encryptionArithmetic* moduloValue, uint32_t keyLength) {
|
|
/* number % moduloValue */
|
|
/* https://www.geeksforgeeks.org/program-to-find-remainder-without-using-modulo-or-operator/ */
|
|
|
|
/* allocate memory */
|
|
t_encryptionArithmetic mulRes, divRes;
|
|
encryptionArithmetic_Init(&mulRes, keyLength);
|
|
encryptionArithmetic_Init(&divRes, keyLength);
|
|
|
|
/* perform modulo operation */
|
|
encryptionArithmetic(number->number, moduloValue->number, &divRes, keyLength, DIV);
|
|
encryptionArithmetic(moduloValue->number, divRes.number, &mulRes, keyLength, MUL);
|
|
encryptionArithmetic(number->number, mulRes.number, number, keyLength, SUB);
|
|
|
|
/* free memory */
|
|
encryptionArithmetic_DeInit(&mulRes);
|
|
encryptionArithmetic_DeInit(&divRes);
|
|
}
|
|
|
|
void modInverse(t_encryptionArithmetic* number, t_encryptionArithmetic* modValue, t_encryptionArithmetic* result, uint32_t keyLength) {
|
|
/* https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/ */
|
|
/* allocate memory */
|
|
t_encryptionArithmetic modRes1, modRes2, mulRes, counter, one;
|
|
encryptionArithmetic_Init(&modRes1, keyLength);
|
|
encryptionArithmetic_Init(&modRes2, keyLength);
|
|
encryptionArithmetic_Init(&mulRes, keyLength);
|
|
encryptionArithmetic_Init(&counter, keyLength);
|
|
encryptionArithmetic_Init(&one, keyLength);
|
|
*counter.number = 1;
|
|
*one.number = 1;
|
|
for (*counter.number; !encryptionArithmetic_isLarger(counter.number, modValue->number, keyLength); encryptionArithmetic(counter.number, one.number, &counter, keyLength, ADD)) {
|
|
/* number % modValue */
|
|
encryptionArithmetic_copyNumber(number->number, modRes1.number, keyLength);
|
|
moduloOperation(&modRes1, modValue, keyLength);
|
|
|
|
/* counter % modValue */
|
|
encryptionArithmetic_copyNumber(counter.number, modRes2.number, keyLength);
|
|
moduloOperation(&modRes2, modValue, keyLength);
|
|
|
|
/* modRes1 * modRes2 */
|
|
encryptionArithmetic(modRes1.number, modRes2.number, &mulRes, keyLength, MUL);
|
|
|
|
/* mulRes % modValue */
|
|
moduloOperation(&mulRes, modValue, keyLength);
|
|
|
|
if (*(mulRes.number) == 1) {
|
|
encryptionArithmetic_copyNumber(counter.number, result->number, keyLength);
|
|
}
|
|
}
|
|
encryptionArithmetic_DeInit(&modRes1);
|
|
encryptionArithmetic_DeInit(&modRes2);
|
|
encryptionArithmetic_DeInit(&mulRes);
|
|
encryptionArithmetic_DeInit(&counter);
|
|
}
|
|
|
|
void square(t_encryptionArithmetic* base, t_encryptionArithmetic* exponent, t_encryptionArithmetic* result, uint32_t keyLength) {
|
|
|
|
/* assign base to result as the first step defined in the square & multply algorithm */
|
|
for (uint8_t i = 0; i < (keyLength / 32); i++) {
|
|
*(result->number + i) = *(base->number + i);
|
|
}
|
|
|
|
/* get amount of bits representing the exponent */
|
|
uint16_t numberOfBits = encryptionArithmetic_numberSize(exponent->number, keyLength);
|
|
|
|
/* execute square and multiply algorithm */
|
|
for (int i = 0; i < numberOfBits - 1; i++) {
|
|
/* -2 as we already did store the base inside our number and therefore skip the MSB */
|
|
if (*(exponent->number) >> (numberOfBits - i - 2) & 1) /* if bit is 1 => multiply number with itself as well as with base */
|
|
{
|
|
encryptionArithmetic(result->number, result->number, result, keyLength, MUL); /* square */
|
|
encryptionArithmetic(result->number, base->number, result, keyLength, MUL); /* multiply */
|
|
}
|
|
else /* if bit is 0 => multiply number with itself */
|
|
{
|
|
encryptionArithmetic(result->number, result->number, result, keyLength, MUL); /* square */
|
|
}
|
|
}
|
|
} |