/** *--------------------------------------------------------------------\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 #include #include #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 */ } } }