ass04 DSA, not working (C / python)

devel_freefall
Simon Frei 3 years ago
parent e62232101b
commit ef8d569966
  1. 59
      ASYD_Cryptograhpy/SW04-DSA/DSA.py
  2. BIN
      ASYD_Cryptograhpy/SW04-DSA/assignment/ass03_ArnoldJonas_EstermannBasil_FreiSimon.zip
  3. 134
      ASYD_Cryptograhpy/SW04-DSA/assignment/ass03_ArnoldJonas_EstermannBasil_FreiSimon/C/DSA.c
  4. 31
      ASYD_Cryptograhpy/SW04-DSA/assignment/ass03_ArnoldJonas_EstermannBasil_FreiSimon/C/DSA.h
  5. 937
      ASYD_Cryptograhpy/SW04-DSA/assignment/ass03_ArnoldJonas_EstermannBasil_FreiSimon/C/encryptionArithmetic.c
  6. 70
      ASYD_Cryptograhpy/SW04-DSA/assignment/ass03_ArnoldJonas_EstermannBasil_FreiSimon/C/encryptionArithmetic.h
  7. 129
      ASYD_Cryptograhpy/SW04-DSA/assignment/ass03_ArnoldJonas_EstermannBasil_FreiSimon/C/main.c
  8. 59
      ASYD_Cryptograhpy/SW04-DSA/assignment/ass03_ArnoldJonas_EstermannBasil_FreiSimon/Python/DSA.py
  9. 13
      ASYD_Cryptograhpy/SW04-DSA/assignment/ass04_ArnoldJonas_EstermannBasil_SimonFrei.txt
  10. 72
      ASYD_Cryptograhpy/SW04-DSA/main.c

@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
"""
Created on Sun Mar 19 17:32:56 2023
@author: simon
"""
from Crypto.PublicKey import DSA
import random
DSAkey=DSA.generate(int(1024))
p = DSAkey.p
q = DSAkey.q
print("p = {}".format(hex(p)))
print("q = {}".format(hex(q)))
#p = 59
#q = 29
foundAlpha = True
while not foundAlpha:
#for alpha in range(2,p-1):
alpha = random.randint(2,p-1)
#alpha = DSAkey.y
if pow(alpha,q,p) == 1:
# check if smaller integer k exists
for k in range(1,q):
if pow(alpha,k,p) == 1:
if k == q:
foundAlpha = True
break
else:
break
if foundAlpha == True:
break
alpha = DSAkey.y
if foundAlpha:
print("found alpha={}, where ord(alpha)=q".format(alpha))
else:
print("unable to find alpha")
exit(1)
d = random.randint(1, q-1)
#d = 7
print("d={}".format(d))
for beta in range(1,p):
if (beta % p) == pow(alpha,d,p):
break
print("beta={}".format(beta))
ke = random.randint(1, q-1)
ke = 10
for r in range(1,p-1):
if pow(pow(alpha,ke,p),1,q) == pow(r,1,q):
break
print("r={}".format(r))

@ -0,0 +1,134 @@
/**
*--------------------------------------------------------------------\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 */
}
}
}

@ -0,0 +1,31 @@
/**
*--------------------------------------------------------------------\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
*
*--------------------------------------------------------------------
*/
#ifndef DSA_H_
#define DSA_H_
#define _CRT_SECURE_NO_WARININGS
#include <stdint.h>
#include <stdio.h>
#include "DSA.h"
#include "encryptionArithmetic.h"
void squareAndMultiply(t_encryptionArithmetic* base, t_encryptionArithmetic* exponent, t_encryptionArithmetic* modulo, t_encryptionArithmetic* result, uint32_t keyLength);
void square(t_encryptionArithmetic* base, t_encryptionArithmetic* exponent, t_encryptionArithmetic* result, uint32_t keyLength);
void moduloOperation(t_encryptionArithmetic* number, t_encryptionArithmetic* moduloValue, uint32_t keyLength);
void modInverse(t_encryptionArithmetic* number, t_encryptionArithmetic* modValue, t_encryptionArithmetic* result, uint32_t keyLength);
#endif // !RSA_H_

@ -0,0 +1,937 @@
/**
*--------------------------------------------------------------------\n
* HSLU T&A Hochschule Luzern Technik+Architektur \n
*--------------------------------------------------------------------\n
*
* \brief n size number computation - ASYD
* \file
* \author Stefano Nicora, stefano.nicora@hslu.ch
* \date 17.05.2022
*
*--------------------------------------------------------------------
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> /* calloc, malloc, free, etc. */
#include <stdbool.h>
#include <string.h>
#include "encryptionArithmetic.h"
/* link two numbers via a mathematical addition */
t_encryptionArithmetic* encryptionArithmetic_ADD(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* link two numbers via a mathematical subtraction */
t_encryptionArithmetic* encryptionArithmetic_SUB(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* link two numbers via a mathematical division */
t_encryptionArithmetic* encryptionArithmetic_DIV(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* link two numbers via a mathematical multiplication */
t_encryptionArithmetic* encryptionArithmetic_MUL(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* link two numbers via logical AND */
t_encryptionArithmetic* encryptionArithmetic_AND(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* link two numbers via logical OR */
t_encryptionArithmetic* encryptionArithmetic_OR(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* link two numbers via logical XOR */
t_encryptionArithmetic* encryptionArithmetic_XOR(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* shift number by amount to the left */
void encryptionArithmetic_LSL(uint32_t* number, uint8_t amount, uint16_t size);
/* empty an existing number of its content */
void encryptionArithmetic_clearNumber(uint32_t* number, uint16_t size);
/**
* Computes the computed result of two numbers while specifying the operation with an OPCODE
*
* Usage:
* Arrays with uint32_t sized entries (number1 and number2) hold the wanted values which get computed bitwise
* from LSB to MSB starting at index 0. Data gets stored as "little Endian".
* array[0] = [X X X X X X X X X]
* MSB LSB
*
* Example:
* uint32_t Number1[10] = { Number };
* uint32_t Number2[10] = { Number };
* t_encryptionArithmetic *result, number;
* result = &number;
* encryptionArithmetic_Init(result, size);
* encryptionArithmetic(Number1, Number2, result, size, ADD);
* encryptionArithmetic_DeInit(result->number);
*
* @param [in] number1
* pointer to the memory location of the first number (stored in 32bit-chunks)
* @param [in] number2
* pointer to the memory location of the second number (stored in 32bit-chunks)
* @param [in] result
* pointer to the memory location of the address which holds the computed number afterwards
* @param [in] size
* Size is in bits
* @param [in] OPCODE
* defines the desired operation that gets computed
* Available operand: ADD, SUB, DIV, MUL, AND, OR, XOR
* @return
* pointer to the memory address of the struct
*/
/* Important: The library takes massively advantage of pointers and memory allocation
* Even though there has been done a lot of testing in regard to memory & buffer overflows
* they might still happen if you aren't careful. You should rather allocate too much memory than
* too little and risk the corruption of data outside your desired working area.
*/
//03.02: deinit-counter added
uint16_t deinitCounter = 0;
t_encryptionArithmetic* encryptionArithmetic(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size, t_operation OPCODE)
{
switch (OPCODE)
{
case ADD: return encryptionArithmetic_ADD(&(*number1), &(*number2), &(*result), size); break;
case SUB: return encryptionArithmetic_SUB(&(*number1), &(*number2), &(*result), size); break;
case DIV: return encryptionArithmetic_DIV(&(*number1), &(*number2), &(*result), size); break;
case MUL: return encryptionArithmetic_MUL(&(*number1), &(*number2), &(*result), size); break;
case AND: return encryptionArithmetic_AND(&(*number1), &(*number2), &(*result), size); break;
case OR: return encryptionArithmetic_OR(&(*number1), &(*number2), &(*result), size); break;
case XOR: return encryptionArithmetic_XOR(&(*number1), &(*number2), &(*result), size); break;
default: printf("OPCODE not recognized. Please select an available one\n"); return 0; break;
}
}
t_encryptionArithmetic* encryptionArithmetic_AND(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size)
{
uint8_t imm = 0;
uint32_t lsl1;
uint32_t lsl2;
uint32_t lsr1;
uint32_t lsr2;
for (uint16_t j = 0; j < size / 32; j++)
{
for (uint8_t i = 0; i < 32; i++)
{
lsl1 = (*(number1 + imm)) << (31 - i);
lsl2 = (*(number2 + imm)) << (31 - i);
lsr1 = lsl1 >> (31);
lsr2 = lsl2 >> (31);
if (lsr1 & lsr2)
{
*(result->number + imm) |= 1 << i;
}
}
imm++;
}
result->compSuccess = true;
return result;
}
t_encryptionArithmetic* encryptionArithmetic_XOR(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size)
{
uint8_t imm = 0;
uint32_t lsl1;
uint32_t lsl2;
uint32_t lsr1;
uint32_t lsr2;
for (uint16_t j = 0; j < size / 32; j++)
{
for (uint8_t i = 0; i < 32; i++)
{
lsl1 = (*(number1 + imm)) << (31 - i);
lsl2 = (*(number2 + imm)) << (31 - i);
lsr1 = lsl1 >> (31);
lsr2 = lsl2 >> (31);
if (lsr1 ^ lsr2)
{
*(result->number + imm) |= 1 << i;
}
}
imm++;
}
result->compSuccess = true;
return result;
}
t_encryptionArithmetic* encryptionArithmetic_OR(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size)
{
uint8_t imm = 0;
uint32_t lsl1;
uint32_t lsl2;
uint32_t lsr1;
uint32_t lsr2;
for (uint16_t j = 0; j < size / 32; j++)
{
for (uint8_t i = 0; i < 32; i++)
{
lsl1 = (*(number1 + imm)) << (31 - i);
lsl2 = (*(number2 + imm)) << (31 - i);
lsr1 = lsl1 >> (31);
lsr2 = lsl2 >> (31);
if (lsr1 | lsr2)
{
*(result->number + imm) |= 1 << i;
}
}
imm++;
}
result->compSuccess = true;
return result;
}
t_encryptionArithmetic* encryptionArithmetic_ADD(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size)
{
uint8_t imm = 0;
/* allocate memory */
result->remainder = 0;
if (result->memAllocSuccess == false) {
result->number = (uint32_t*)calloc(size / 32 + 1, sizeof(uint32_t));
}
if (result->number == NULL)
{
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
result->memAllocSuccess = true;
/* Add the first 32 bits together while omitting the carry bit */
*(result->number + imm) = *(number1 + imm) + *(number2 + imm);
imm++;
for (uint16_t j = 1; j < size / 32 + 1; j++)
{
if (*(result->number + imm - 1) < *(number1 + imm - 1)) /* check for omitted carry bit */
{
result->hasOverflown = true;
}
else
{
result->hasOverflown = false;
}
*(result->number + imm) = *(number1 + imm) + *(number2 + imm); //Adds the next 32 bit chunk of numbers together
*(result->number + imm) = *(result->number + imm) + result->hasOverflown; //checks for the presence of a carry bit and adds it to the number
imm++;
}
result->compSuccess = true;
return result;
}
t_encryptionArithmetic* encryptionArithmetic_SUB(uint32_t* minuend, uint32_t* subtrahend, t_encryptionArithmetic* result, uint16_t size)
{
/* based on the 1's complement subtraction */
/* https://electricalbaba.com/1s-complement-subtraction-explained-with-examples/ */
/* https://atozmath.com/NumberSubComp.aspx */
/* allocate memory */
if (result->memAllocSuccess == false) {
result->number = (uint32_t*)calloc(size / 32 + 1, sizeof(uint32_t));
}
if (result->number == NULL)
{
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
result->memAllocSuccess = true;
/* get actual size of the subtrahend */
uint16_t subtrahendSize = encryptionArithmetic_numberSize(subtrahend, size);
/* get actual size of the minuend */
uint16_t minuendSize = encryptionArithmetic_numberSize(minuend, size);
/* allocate memory */
/* in order to facilitate the iterative usage of the function we need to make sure
* that the result is always empty when doing the calculations. Therefore both temp-pointers are needed */
uint32_t* tempMinuend = (uint32_t*)calloc((minuendSize) / 32 + 3, sizeof(uint32_t)); /* + 2 to handle the possible overflow */ //02.02: size -> minuendSize //03.02: 32 + 2 -> 32 + 3
uint32_t* tempSubtrahend = (uint32_t*)calloc((subtrahendSize) / 32 + 3, sizeof(uint32_t)); /* + 2 to handle the possible overflow */ //02.02: size -> subtrahendSize
if (tempMinuend == NULL || tempSubtrahend == NULL)
{
if (tempMinuend != NULL) {
free(tempMinuend);
}
if (tempSubtrahend != NULL) {
free(tempSubtrahend);
}
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
memmove(tempMinuend, minuend, (minuendSize <= 4) ? (1) : (minuendSize / 8) + 1); /* size / 8 + 1 = number of bytes including error for int calulation */
memmove(tempSubtrahend, subtrahend, (subtrahendSize <= 4) ? (1) : (subtrahendSize / 8) + 1);/* size / 8 + 1 = number of bytes including error for int calulation */
result->memAllocSuccess = true;
/* there is no sense in generating the 1's complement if we substract 0 from another number */
if (!subtrahendSize || !minuendSize) {
if (!subtrahendSize) {
/* copy number from minuend into result */
for (uint8_t imm = 0; imm < (minuendSize / 32 + 1); imm++) { //02.02: (size / 32) -> (minuendSize / 32 + 1)
*(result->number + imm) = *(tempMinuend + imm);
}
}
else {
/* copy number from subtrahend into result */
for (uint8_t imm = 0; imm < (subtrahendSize / 32 + 1); imm++) { //02.02: (size / 32) -> (subtrahendSize / 32 + 1)
*(result->number + imm) = *(tempSubtrahend + imm);
}
}
free(tempMinuend);
free(tempSubtrahend);
result->compSuccess = true;
return result;
}
/* generate the 1's complement out of the subtrahend */
uint8_t cnt = 0;
for (uint8_t i = 0; i < (subtrahendSize / 32) + 1; i++) { /* +1 to circumvent division by 0 */
*(tempSubtrahend + i) = ~(*(subtrahend + i));
cnt++;
}
/* clear any false set bit that occurs during 1's complement generation */
if (subtrahendSize == 32 * (cnt - 1)) {
*(tempSubtrahend + cnt - 1) = 0;
}
else if (subtrahendSize >= 32) {
*(tempSubtrahend + cnt - 1) = *(tempSubtrahend + cnt - 1) & (0xFFFFFFFF >> ((32 * cnt) - subtrahendSize));
}
else {
*(tempSubtrahend + cnt - 1) = *(tempSubtrahend + cnt - 1) & (0xFFFFFFFF >> (32 - subtrahendSize));
}
/* Add the first 32 bits together while omitting the carry bit */
encryptionArithmetic_clearNumber(result->number, size);
*(result->number) = *(tempMinuend) + *(tempSubtrahend);
uint8_t imm = 1;
for (uint16_t j = 1; j < minuendSize / 32 + 1; j++) // 02.02: +1 -> +2 | size -> minuendSize
{
if (*(result->number + imm - 1) < *(tempMinuend + imm - 1)) /* check for omitted carry bit */
{
result->hasOverflown = true;
}
else
{
result->hasOverflown = false;
}
*(result->number + imm) = *(tempMinuend + imm) + *(tempSubtrahend + imm); /* Adds the next 32 bit chunk of numbers together */
*(result->number + imm) = *(result->number + imm) + result->hasOverflown; /* checks for the presence of a carry bit and adds it to the number */
imm++;
}
/* get actual size of the number to catch overflows */
uint16_t numberSize = encryptionArithmetic_numberSize(result->number, size);
if (numberSize > minuendSize || numberSize > subtrahendSize) {
result->hasOverflown = true;
}
else {
result->hasOverflown = false;
}
/* if an overflow has occured (= result is positive), we need to add that bit to the LSB while omitting it as the MSB */
if (result->hasOverflown)
{
/* can't simply be a single uint32_t variable, as there would be out of boundary memory access through the ADD function */
uint32_t* carry = (uint32_t*)calloc((numberSize) / 32 + 2, sizeof(uint32_t)); //02.02: size -> numberSize
uint32_t* cache = (uint32_t*)calloc((numberSize) / 32 + 2, sizeof(uint32_t)); //02.02: size -> numberSize
if (cache == NULL || carry == NULL)
{
if (cache != NULL) {
free(cache);
}
if (carry != NULL) {
free(carry);
}
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
*carry = 1;
result->memAllocSuccess = true;
for (int i = 0; i < (numberSize / 32) + 1; i++)
{
*(cache + i) = *(result->number + i);
}
/* remove overflow-MSB */
if (numberSize <= 32)
{
*(cache) ^= 1 << (numberSize - 1);
}
else
{
if (!(numberSize % 32)) /* numberSize is a multiple of 32 */
{
*(cache + (numberSize / 32) - 1) ^= 1 << 31;
}
else
{
*(cache + (numberSize / 32)) ^= 1 << (numberSize - 1 - ((numberSize / 32) * 32));
}
}
encryptionArithmetic_clearNumber(result->number, size);
encryptionArithmetic_ADD(&(*cache), &(*carry), &(*result), size);
free(cache);
free(carry);
}
else {
/* generate the 1's complement out of the result as it is negative */
cnt = 0;
for (uint8_t i = 0; i < (numberSize / 32) + 1; i++)
{ /* +1 to circumvent division by 0 */
*(result->number + i) = ~(*(result->number + i));
cnt++;
}
if (numberSize == 32 * (cnt - 1))
{
*(result->number + cnt - 1) = 0;
}
else if (numberSize >= 32)
{
*(result->number + cnt - 1) = *(result->number + cnt - 1) & (0xFFFFFFFF >> ((32 * cnt) - numberSize));
}
else
{
*(result->number + cnt - 1) = *(result->number + cnt - 1) & (0xFFFFFFFF >> (32 - numberSize));
}
}
free(tempMinuend);
free(tempSubtrahend);
result->compSuccess = true;
return result;
}
t_encryptionArithmetic* encryptionArithmetic_DIV(uint32_t* dividend, uint32_t* divisor, t_encryptionArithmetic* result, uint16_t size)
{
/* based on long division */
/* https://www.cuemath.com/numbers/long-division/ */
/* allocate memory */
t_encryptionArithmetic* remainder, remainder2;
remainder = &remainder2;
encryptionArithmetic_Init(remainder, size);
result->remainder = 0;
bool stateFloat = false, state1 = false, isLarger = false, isEqual = false;
/* get actual size of dividend */
uint16_t dividendSize = encryptionArithmetic_numberSize(dividend, size);
/* get actual size of divisor */
uint16_t divisorSize = encryptionArithmetic_numberSize(divisor, size);
/* basic tests to catch unwanted states */
if (divisorSize == 0)
{
printf("Divisor is 0!\n");
result->compSuccess = false;
return result;
}
//for (uint16_t i = 0; i < (dividendSize > divisorSize ? dividendSize / 32 + 1 : divisorSize / 32 + 1); i++)
for (int16_t i = (dividendSize > divisorSize ? dividendSize / 32 : divisorSize / 32); i >= 0 ; i--)
{
/* division result = 1 */
if (*(divisor + i) == *(dividend + i))
{
state1 = true;
stateFloat = false;
}
/* would result in floating point operation */
else if (*(dividend + i) < *(divisor + i))
{
state1 = false;
stateFloat = true;
break;
}
else
{
state1 = false;
stateFloat = false;
break;
}
}
if (state1)
{ /* division result = 1 */
*(result->number) = 1;
result->remainder = 0;
encryptionArithmetic_DeInit(remainder);
result->compSuccess = true;
return result;
}
else if (stateFloat)
{ /* would result in floating point operation */
printf("Divisor is larger than dividend. Floating point operations aren't supported. Result = 0\n");
*(result->number) = 0;
result->remainder = 0;
encryptionArithmetic_DeInit(remainder);
result->compSuccess = true;
return result;
}
/* get the bit we are currently focused on (move from MSB to LSB) */
/* get the offset and focused bit inside the right data chunk */
uint16_t focusPos = 0; /* holds the current "active" bit position we add to our remainder */
uint8_t imm = 0; /* holds the offset relative to the size of our data */
uint8_t focusPosInsideDataChunk = 0; /* holds the read position relative to the address (imm) offset */
uint8_t cnt = 0; /* holds the number of '0' that have to be added to the result starting from the LSB */
uint16_t loopDivisorSize = 0; /* holds the the loop value to catch the wrong state if divisorSize % 32 == 0 */
if (divisorSize % 32 == 0)
{
loopDivisorSize = (divisorSize / 32) - 1;
}
else
{
loopDivisorSize = divisorSize / 32;
}
for (uint16_t k = 0; k < dividendSize; k++)
{
focusPos = dividendSize - 1 - k; /* -1 is needed, as the nth bit sits at position n-1 */
imm = focusPos / 32;
focusPosInsideDataChunk = focusPos - imm * 32;
/* if the remainder is larger than the divisor, we can safely conduct the subtraction w/o the need to check for an over/underflow */
//if (*(remainder->number + (divisorSize / 32)) >= *(divisor + (divisorSize / 32)))
//if (*(remainder->number + (divisorSize / 32)) > *(divisor + (divisorSize / 32)))
if (*(remainder->number + loopDivisorSize) > *(divisor + loopDivisorSize) || *(remainder->number + loopDivisorSize + 1) > *(divisor + loopDivisorSize + 1))
/* TODO: work here -> check why it fails here */
{
encryptionArithmetic_SUB(remainder->number, divisor, remainder, size); /* store subtraction of remainder and divisor inside remainder */
encryptionArithmetic_LSL(result->number, cnt, size); /* shift data to the left to add the next bit */
*(result->number) |= 1; /* add a logical "1" as LSB to the result */
k--; /* keep the read position on the same level, as it would skip one otherwise */
cnt = 0;
}
else if (*(remainder->number + loopDivisorSize) == *(divisor + loopDivisorSize) && *(remainder->number + loopDivisorSize + 1) == *(divisor + loopDivisorSize + 1))
{ /* check if both numbers are actually equal and not only the MSB-chunks of data */
isEqual = false;
for (uint16_t i = 0; i <= loopDivisorSize; i++)
{
if (*(remainder->number + i) == *(divisor + i))
{ /* add a logical "1" as LSB to the result */
isEqual = true;
}
else
{
/* remainder isn't == divisor and we need to execute the "else" part of the first if-statement */
encryptionArithmetic_LSL(remainder->number, 1, size); /* shift data one step to the left to add the next bit */
*remainder->number |= ((*(dividend + imm) >> (focusPosInsideDataChunk) & 1) ? 1 : 0); /* add next bit (0 or 1) to existing remainder */
cnt++;
isEqual = false;
break;
}
}
if (isEqual)
{ /* remainder == divisor and therefore the result is 1 */
encryptionArithmetic_clearNumber(remainder->number, size);
*(remainder->number) = 1;
}
}
/* as the remainder is smaller than the divisor, we would get an overflow when subtracting.
* Put next bit from the dividend at the end of remainder (new LSB) and try again */
else
{
encryptionArithmetic_LSL(remainder->number, 1, size); /* shift data one step to the left to add the next bit */
*remainder->number |= ((*(dividend + imm) >> (focusPosInsideDataChunk) & 1) ? 1 : 0); /* add next bit (0 or 1) to existing remainder */
cnt++;
}
}
/* legacy code */
//for (uint16_t k = 0; k < dividendSize; k++)
//{
// focusPos = dividendSize - 1 - k; /* -1 is needed, as the nth bit sits at position n-1 */
// imm = focusPos / 32;
// focusPosInsideDataChunk = focusPos - imm * 32;
// /* if the remainder is larger than the divisor, we can safely conduct the subtraction w/o the need to check for an over/underflow */
// if (result->remainder >= *divisor)
// {
// result->remainder = result->remainder - *divisor; /* store subtraction of remainder and divisor inside remainder */
// *(result->number + imm) = *(result->number + imm) << cnt | 1; /* add a logical "1" as LSB to the result */
// k--; /* keep the read position on the same level, as it would skip one otherwise */
// cnt = 0;
// }
// /* as the remainder is smaller than the divisor, we would get an overflow when subtracting.
// * Put next bit from the dividend at the end of remainder (new LSB) and try again */
// else
// {
// result->remainder = (result->remainder << 1) /* shift data each cycle one step to the left to add the next bit */
// | ((*(dividend + imm) >> (focusPosInsideDataChunk) & 1) ? 1 : 0); /* add next bit (0 or 1) to existing remainder */
// cnt++;
// }
//}
/* legacy code end */
/* get actual size of the temporary remainder */
uint16_t remainderSize = encryptionArithmetic_numberSize(remainder->number, size);
/* defines the amounts of loops necessary */
uint16_t loopLength = 0;
if (remainderSize > divisorSize)
{
if (!(remainderSize % 32)) /* remainder is a multiple of 32 */
{
loopLength = remainderSize / 32 - 1;
}
else
{
loopLength = remainderSize / 32;
}
}
else
{
if (!(divisorSize % 32)) /* remainder is a multiple of 32 */
{
loopLength = divisorSize / 32 - 1;
}
else
{
loopLength = divisorSize / 32;
}
}
isLarger = false;
isEqual = false;
for (uint16_t i = 0; i <= loopLength; i++)
{
if (*(remainder->number + i) > *(divisor + i))
{ /* store subtraction of remainder and divisor inside remainder */
isLarger = true;
isEqual = false;
}
else if (*(remainder->number + i) == *(divisor + i))
{ /* add a logical "1" as LSB to the result */
isLarger = false;
isEqual = true;
}
}
encryptionArithmetic_LSL(result->number, cnt, size); /* shift data cnt-amount to the left */
if (isLarger && !isEqual) /* store subtraction of remainder and divisor inside remainder */
{
encryptionArithmetic_SUB(remainder->number, divisor, remainder, size);
result->remainder = *remainder->number; /* store subtraction of remainder and divisor inside remainder */
*(result->number) |= 1; /* add a logical "1" as LSB to the result */
}
else if (!isLarger && isEqual) /* add a logical "1" as LSB to the result */
{
result->remainder = 0; /* no remainder left */
*(result->number) |= 1; /* add a logical "1" as LSB to the result */
}
else
{
result->remainder = *remainder->number; /* store local remainder inside outbound remainder */
}
encryptionArithmetic_DeInit(remainder);
result->compSuccess = true;
return result;
}
t_encryptionArithmetic* encryptionArithmetic_MUL(uint32_t* multiplicand, uint32_t* multiplier, t_encryptionArithmetic* result, uint16_t size)
{
/* based on the shift and add algorithm https://users.utcluj.ro/~baruch/book_ssce/SSCE-Shift-Mult.pdf */
uint8_t imm = 0; /* holds the immediate value to keep track of how many chunks of data we traversed */
uint8_t readPos = 0; /* current readable bit position */
/* get actual size of the multiplicand */
uint16_t multiplicandSize = encryptionArithmetic_numberSize(multiplicand, size);
/* get actual size of the multiplier */
uint16_t multiplierSize = encryptionArithmetic_numberSize(multiplier, size);
/* allocate memory */
/* in order to facilitate the iterative usage of the function we need to make sure
* that the result is always empty when doing the calculations. Therefore both temp-pointers are needed */
uint32_t* cache = (uint32_t*)calloc((size) / 32 * 3 + 2, sizeof(uint32_t)); /* Has to be double the size to be able to store all bits + 2 to handle the possible overflow */
uint32_t* tempMultiplicand; /* allocation is done below */
uint32_t* tempMultiplier; /* allocation is done below */
/* for some reason (has to be investigated in the future) multiplying a number with a smaller number results in a limited amount of flipped bits
* current workaround: swap multiplier and multiplicand if multiplicand > multiplier */
if (multiplicandSize + 4 > multiplierSize) {
tempMultiplicand = (uint32_t*)calloc((multiplicandSize) / 32 * 4 + 2, sizeof(uint32_t)); /* Has to be double the size to be able to store all bits + 2 to handle the possible overflow */ //02.02: size -> multiplicandSize
tempMultiplier = (uint32_t*)calloc((multiplicandSize) / 32 * 4 + 2, sizeof(uint32_t)); /* Has to be double the size to be able to store all bits + 2 to handle the possible overflow */ //02.02: size -> multiplierSize
if (cache == NULL || tempMultiplicand == NULL || tempMultiplier == NULL)
{
if (cache != NULL) {
free(cache);
}
if (tempMultiplicand != NULL) {
free(tempMultiplicand);
}
if (tempMultiplier != NULL) {
free(tempMultiplier);
}
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
memmove(tempMultiplier, multiplicand, (multiplicandSize <= 4) ? (1) : (multiplicandSize / 8) + 1); /* size / 8 = number of bytes */
memmove(tempMultiplicand, multiplier, (multiplicandSize <= 4) ? (1) : (multiplicandSize / 8) + 1); /* size / 8 = number of bytes */
/* as the numbers have swapped places, a size recalculation is needed */
multiplicandSize = encryptionArithmetic_numberSize(multiplier, size);
multiplierSize = encryptionArithmetic_numberSize(multiplicand, size);
}
else { /* used to be the default way */
tempMultiplicand = (uint32_t*)calloc((multiplicandSize) / 32 * 4 + 2, sizeof(uint32_t)); /* Has to be double the size to be able to store all bits + 2 to handle the possible overflow */ //02.02: size -> multiplicandSize
tempMultiplier = (uint32_t*)calloc((multiplierSize) / 32 * 4 + 2, sizeof(uint32_t)); /* Has to be double the size to be able to store all bits + 2 to handle the possible overflow */ //02.02: size -> multiplierSize
if (cache == NULL || tempMultiplicand == NULL || tempMultiplier == NULL)
{
if (cache != NULL) {
free(cache);
}
if (tempMultiplicand != NULL) {
free(tempMultiplicand);
}
if (tempMultiplier != NULL) {
free(tempMultiplier);
}
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
memmove(tempMultiplicand, multiplicand, (multiplicandSize <= 4) ? (1) : (multiplicandSize / 8) + 1); /* size / 8 = number of bytes */
memmove(tempMultiplier, multiplier, (multiplierSize <= 4) ? (1) : (multiplierSize / 8) + 1); /* size / 8 = number of bytes */
}
//memmove(tempMultiplicand, multiplicand, (multiplicandSize <= 4) ? (1) : (multiplicandSize / 8) + 1); /* size / 8 = number of bytes */
//memmove(tempMultiplier, multiplier, (multiplierSize <= 4) ? (1) : (multiplierSize / 8) + 1); /* size / 8 = number of bytes */
result->memAllocSuccess = true;
/* clear result for next operation */
encryptionArithmetic_clearNumber(result->number, size);
/* traverse the saved number in 32bit chunks */
for (uint16_t j = 0; j <= multiplierSize; j++) //02.02: size -> multiplierSize
{
if ((j / (imm + 1)) == 32) { /* +1 to prevent division by 0 */
readPos = 0;
imm++;
}
/* check if the current LSB is '1', skip if not */
if ((*(tempMultiplier + imm) >> readPos) & 1)
{
//for (uint8_t m = 0; m <= ((multiplicandSize > multiplierSize) ? (multiplicandSize / 32 + 1) : (multiplierSize / 32 + 1)); m++) //02.02: /32 -> /32 + 1 & size -> ?:
//for (uint8_t m = 0; m <= 7; m++)
for (uint8_t m = 0; m <= ((multiplicandSize + multiplierSize) / 32); m++)
{
/* shift the 32bit number "chunk" according the the layer of addition we are currently on and store in cache */
if (readPos == 0) {
*(cache + (m + (j / 32))) += *(tempMultiplicand + m); /* assign bits depending on current readPos */
}
else {
*(cache + (m + j / 32)) += *(tempMultiplicand + m) << readPos; /* assign bits depending on current readPos */
*(cache + (m + j / 32) + 1) += *(tempMultiplicand + m) >> (32 - readPos); /* assign bits that would be lost in shift operation to the next "chunk" */
}
/* add the previous result to the new layer including any overflowing that might occur */
*(result->number + m) += *(cache + m) + result->hasOverflown;
//*(result->number + m + (j / 32)) += *(cache + m + (j / 32)) + result->hasOverflown; //03.02
/* if the addition generated an overflow, the stored result will be smaller than the number we added to it */
if ((*(result->number + m) < *(cache + m))) {
//if ((*(result->number + m) < *(cache + m)) || (*(result->number + m) == 0xFFFFFFFF) && (*(cache + m) == 0xFFFFFFFF)) { //03.02
//if ((*(result->number + m + (j / 32)) < *(cache + m + (j / 32))) || (*(result->number + m + (j / 32)) == 0xFFFFFFFF) && (*(cache + m + (j / 32)) == 0xFFFFFFFF)) { //03.02
//if ((*(result->number + m + (j / 32)) < *(cache + m)) || (*(result->number + m + (j / 32)) == 0xFFFFFFFF) && (*(cache + m) == 0xFFFFFFFF)) { //04.02
//if ((*(result->number + m) < *(cache + m)) || (*(result->number + m + 1) == 0xFFFFFFFF) && (*(cache + m + 1) == 0xFFFFFFFF)) { //05.02 +m -> m + 1
result->hasOverflown = true;
}
else {
result->hasOverflown = false;
}
}
/* clearing the cache for the next addition operation */
encryptionArithmetic_clearNumber(cache, size);
}
readPos++;
}
free(cache);
free(tempMultiplicand);
free(tempMultiplier);
result->compSuccess = true;
return result;
}
void encryptionArithmetic_LSL(uint32_t* number, uint8_t amount, uint16_t size)
{
uint32_t overflowBit1 = 0, overflowBit2 = 0;
/* get actual size of number */
uint16_t numberSize = encryptionArithmetic_numberSize(number, size);
overflowBit1 = *number >> (32 - amount); /* store MSB from first block */
*number = *number << amount; /* perform lsl-operation of first block */
if (numberSize + amount >= 32)
{
for (uint8_t i = 1; i <= (numberSize + amount) / 32; i++)
{
overflowBit2 = *(number + i) >> (32 - amount); /* store MSB from current block */
*(number + i) = *(number + i) << amount; /* perform lsl-operation of current block */
*(number + i) |= overflowBit1; /* add MSB of last block to current block */
overflowBit1 = overflowBit2; /* store current MSB for next iteration */
}
}
}
t_encryptionArithmetic* encryptionArithmetic_Init(t_encryptionArithmetic* result, uint16_t size)
{
result->number = (uint32_t*)calloc((size) / 32 * 4 + 1, sizeof(uint32_t)); /* has to be this size to accommodate all types of computations, including multiplication */
if (result->number == NULL)
{
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
result->memAllocSuccess = true;
result->compSuccess = false;
*(result->number) = 0;
result->remainder = 0;
result->hasOverflown = false;
return result;
}
void encryptionArithmetic_DeInit(t_encryptionArithmetic* ptr)
{
deinitCounter++;
free(ptr->number);
}
uint16_t encryptionArithmetic_numberSize(uint32_t *number, uint16_t size) {
uint8_t cnt = 0;
uint16_t sizeCache = size * 3, actualLength = size * 3; //02.02: *2 -> *3
while ((*(number + (sizeCache / 32) - 1)) >> (31 - cnt) != 1)
{
cnt++;
actualLength--;
if (cnt == 32)
{
cnt = 0;
sizeCache -= 32;
}
if (!actualLength) {
break;
}
}
return actualLength;
}
void encryptionArithmetic_clearNumber(uint32_t* number, uint16_t size) {
uint16_t numberSize = encryptionArithmetic_numberSize(number, size);
uint16_t loopNumberSize = 0;
if (numberSize % 32)
{
loopNumberSize = numberSize - 1;
}
else
{
loopNumberSize = numberSize;
}
for (uint16_t i = 0; i <= loopNumberSize / 32; i++) {
*(number + i) = 0;
}
}
/* returns true if first number is larger than the second one */
bool encryptionArithmetic_isLarger(uint32_t* number1, uint32_t* number2, uint16_t size) {
uint16_t divisorSize = encryptionArithmetic_numberSize(number2, size);
bool isLarger = false;
for (int16_t i = (divisorSize / 32); i >= 0; i--)
{ /* i has to be signed to access 0 */
if (*(number1 + i) > *(number2 + i))
{
isLarger = true;
}
else
{
isLarger = false;
}
}
return isLarger;
}
bool encryptionArithmetic_stringToHex(char* src, uint32_t* dest, uint16_t length) {
/* holds the amount of characters that are stored in src */
uint16_t stringLength = 0;
/* clear destination in order to facilitate iterative use or generally the same pointer */
encryptionArithmetic_clearNumber(dest, length);
/* get actual string length without the '\0' character and convert any lowercase characters */
for (stringLength = 0; src[stringLength] != '\0'; ++stringLength)
{
switch (src[stringLength]) {
case 'a': src[stringLength] = 'A'; break;
case 'b': src[stringLength] = 'B'; break;
case 'c': src[stringLength] = 'C'; break;
case 'd': src[stringLength] = 'D'; break;
case 'e': src[stringLength] = 'E'; break;
case 'f': src[stringLength] = 'F'; break;
default: break;
}
if (src[stringLength] < 48 || (src[stringLength] > 57 && src[stringLength] < 65) || src[stringLength] > 70)
{ /* 0...9, A...F */
printf("Abort, as input string contains values other than 0-9, A-F\n");
return false;
}
}
if (!stringLength)
{ /* string is empty */
return false;
}
if (stringLength * 4 > length)
{
printf("Abort, as stringLength > maxAllocatedSpace and would result in faulty memory access\n");
return false;
}
/* store conversion of string in destination while reversing the sequence */
uint16_t imm = stringLength / 8; /* 8*char == 32 bit */
uint8_t cnt;
if (!(stringLength % 8))
{
imm = stringLength / 8 - 1;
}
else
{
imm = stringLength / 8;
}
cnt = stringLength - (imm * 8) - 1;
for (uint16_t cntUp = 0; cntUp < stringLength; cntUp++)
{
if (src[cntUp] >= 48 && src[cntUp] <= 57)
{ /* 0...9 */
*(dest + imm) |= (src[cntUp] - 0x30) << (cnt * 4);
}
else
{ /* A...F */
*(dest + imm) |= (src[cntUp] - 0x37) << (cnt * 4);
}
if (cnt == 0)
{
cnt = 8;
imm--;
}
cnt--;
}
return true;
}
void encryptionArithmetic_copyNumber(uint32_t* src, uint32_t* dest, uint16_t length) {
encryptionArithmetic_clearNumber(dest, length);
uint32_t srcSize = encryptionArithmetic_numberSize(src, length);
memmove(dest, src, (srcSize <= 4) ? (1) : (srcSize / 8) + 1); /* size / 8 + 1 = number of bytes including error for int calulation */ //06.02: +1 -> + 0
}

@ -0,0 +1,70 @@
/**
*--------------------------------------------------------------------\n
* HSLU T&A Hochschule Luzern Technik+Architektur \n
*--------------------------------------------------------------------\n
*
* \brief n size number computation - ASYD
* \file
* \author Stefano Nicora, stefano.nicora@hslu.ch
* \date 07.03.2022
*
*--------------------------------------------------------------------
*/
#ifndef _ENCRYPTIONARITHMETIC_H_
#define _ENCRYPTIONARITHMETIC_H_
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct encryptArithmetic {
bool hasOverflown; /* whether or not the computation has generated a overflow */
bool memAllocSuccess; /* whether or not the calloc call has been successful */
bool compSuccess; /* whether or not the desired computation has been successful */
uint32_t remainder; /* holds the remainder(if available) of the division */
uint32_t* number; /* holds the address of the computed number */
}t_encryptionArithmetic;
typedef enum {
ADD,
SUB,
DIV,
MUL,
AND,
OR,
XOR
}t_operation;
/* Computes the result of two numbers while specifying the operation with an OPCODE
*
* Usage:
* Arrays with uint32_t sized entries (number1 and number2) hold the wanted values which get computed bitwise
* from LSB to MSB starting at index 0. Data gets stored as "little Endian".
* array[0] = [X X X X X X X X X]
* MSB LSB
* */
t_encryptionArithmetic* encryptionArithmetic(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size, t_operation OPCODE);
/* initialize the module */
t_encryptionArithmetic* encryptionArithmetic_Init(t_encryptionArithmetic* result, uint16_t size);
/* deinitialize the module and free the allocated no longer needed memory */
void encryptionArithmetic_DeInit(t_encryptionArithmetic* ptr);
/* returns the number of bits representing the number */
uint16_t encryptionArithmetic_numberSize(uint32_t* number, uint16_t size);
/* returns true if first number is larger than the second one */
bool encryptionArithmetic_isLarger(uint32_t* number1, uint32_t* number2, uint16_t size);
/*
turns a number in a string-format in hex into a regular number inside the library
returns true if successful
*/
bool encryptionArithmetic_stringToHex(char* src, uint32_t* dest, uint16_t length);
void encryptionArithmetic_copyNumber(uint32_t* src, uint32_t* dest, uint16_t length);
#endif /* _ENCRYPTIONARITHMETIC_H_ */

@ -0,0 +1,129 @@
/**
*--------------------------------------------------------------------\n
* HSLU T&A Hochschule Luzern Technik+Architektur \n
*--------------------------------------------------------------------\n
*
* \brief ASYD assignment crypto 04
* \file
* \author Basil Estermann, basil.estermann@stud.hslu.ch
* Simon Frei, simon.frei@stud.hslu.ch
* Jonas Arnold, jonas.arnold@stud.hslu.ch
* \date 16.03.2023
*
*--------------------------------------------------------------------
*/
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "encryptionArithmetic.h"
#include "DSA.h"
#define KEY_LENGTH 16
#define DIVISOR 160
int generateDsaKey(void);
int calculateSessionKey(void);
void printLargeNumberLine(char* descriptor, t_encryptionArithmetic* number, uint16_t size);
void main(void) {
int result = 0;
printf("------ Generate DSA Key ------\n\n");
result = generateDsaKey();
if (result != 0) {
return result;
}
/*printf("------ Calculate Sessionkey ------\n\n");
result = calculateSessionKey();
if (result != 0) {
return result;
}*/
return 0;
}
int generateDsaKey(void) {
/*const char* p_string = "C8462B074900AD6622E5FE3F945BD2C6D570FAFF63BDCF4287AAC84DEF28BA0D7BF3EF9D3FF4A5D0821BDB1FBEED32CA5DE56B1832B648F40C5C205EA8694F828DF9C1583E284AC773F595809E442BB7D5E256B1C68E7E80C782D9469D351D5E9C434A2CBD2A1AB4527B11B405128A2146F12882742A732EADE720ECE2BC1B4D";
const char* q_string = "810E78D2D6C8B0BB8A15FFEA19EBED45D6CB0495";
const char* d_string = "9778729279583412";*/
const char* p_string = "3B";
const char* q_string = "1D";
const char* d_string = "10";
// P has to be a prime number!
t_encryptionArithmetic p;
encryptionArithmetic_Init(&p, KEY_LENGTH);
if (encryptionArithmetic_stringToHex(p_string, p.number, KEY_LENGTH) == false) {
printf("ERROR: Creating p.");
return 1000000;
}
t_encryptionArithmetic q;
encryptionArithmetic_Init(&q, KEY_LENGTH);
if (encryptionArithmetic_stringToHex(q_string, q.number, KEY_LENGTH) == false) {
printf("ERROR: Creating q.");
return 1000001;
}
// ord(a) = k = q
t_encryptionArithmetic alpha_k;
encryptionArithmetic_Init(&alpha_k, KEY_LENGTH);
t_encryptionArithmetic alpha;
encryptionArithmetic_Init(&alpha, 64);
const char* alpha_string = "20000000";
if (encryptionArithmetic_stringToHex(alpha_string, alpha.number, 64) == false) {
printf("ERROR: Creating q.");
return 1000001;
}
moduloOperation(&alpha, &q, KEY_LENGTH);
//for (*alpha.number = 2; *alpha.number < *p.number; *alpha.number = *alpha.number + 1) {
////for(uint32_t i = 2; i < UINT32_MAX; i++){
// //encryptionArithmetic_copyNumber(&i, alpha.number, KEY_LENGTH);
// square(&alpha, &q, &alpha_k, KEY_LENGTH);
// moduloOperation(&alpha_k, &q, KEY_LENGTH);
// if (*alpha_k.number == 1) {
// printf("Found alpha k where = 1");
// break;
// }
//}
t_encryptionArithmetic d;
encryptionArithmetic_Init(&d, KEY_LENGTH);
if (encryptionArithmetic_stringToHex(d_string, d.number, KEY_LENGTH) == false) {
printf("ERROR: Creating d.");
return 1000003;
}
/* initialize and calculate beta */
t_encryptionArithmetic beta;
encryptionArithmetic_Init(&beta, KEY_LENGTH);
squareAndMultiply(&alpha, &d, &p, &beta, KEY_LENGTH);
printf("-- public key --");
printLargeNumberLine("p", &p, KEY_LENGTH);
printLargeNumberLine("q", &q, KEY_LENGTH);
printLargeNumberLine("alpha", &alpha, KEY_LENGTH);
printLargeNumberLine("beta", &beta, KEY_LENGTH);
return 0;
}
int calculateSessionKey(void) {
return 0;
}
void printLargeNumberLine(char* descriptor, t_encryptionArithmetic* number, uint16_t size)
{
uint16_t numLength = encryptionArithmetic_numberSize((*number).number, size);
printf("\n%s:\t0x", descriptor);
for (int16_t i = numLength / 32; i >= 0; i--) {
printf("%X", *((*number).number + i));
}
printf("\n");
}

@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
"""
Created on Sun Mar 19 17:32:56 2023
@author: simon
"""
from Crypto.PublicKey import DSA
import random
DSAkey=DSA.generate(int(1024))
p = DSAkey.p
q = DSAkey.q
print("p = {}".format(hex(p)))
print("q = {}".format(hex(q)))
#p = 59
#q = 29
foundAlpha = True
while not foundAlpha:
#for alpha in range(2,p-1):
alpha = random.randint(2,p-1)
#alpha = DSAkey.y
if pow(alpha,q,p) == 1:
# check if smaller integer k exists
for k in range(1,q):
if pow(alpha,k,p) == 1:
if k == q:
foundAlpha = True
break
else:
break
if foundAlpha == True:
break
alpha = DSAkey.y
if foundAlpha:
print("found alpha={}, where ord(alpha)=q".format(alpha))
else:
print("unable to find alpha")
exit(1)
d = random.randint(1, q-1)
#d = 7
print("d={}".format(d))
for beta in range(1,p):
if (beta % p) == pow(alpha,d,p):
break
print("beta={}".format(beta))
ke = random.randint(1, q-1)
ke = 10
for r in range(1,p-1):
if pow(pow(alpha,ke,p),1,q) == pow(r,1,q):
break
print("r={}".format(r))

@ -0,0 +1,13 @@
Assignment crypto 04
Gruppenmitglieder: Basil Estermann, Jonas Arnold, Simon Frei
Wir konnten die Aufgabe leider nicht lösen. Wir hatten bereits grosse Probleme eine 1024 Bit
Primzahl zu finden und einen Prim-Divisor mit 160 bit. Letztendlich haben wir das über ein
Python Package (Crypto) gelöst. Im C- Programm, erhielten wir immer wieder den Fehler, dass
unzulässiger Speicher beschrieben wurde oder dass eine Rechnung nicht aufging. (Beim Modulo
rechnen, die Subtraktion vergrösserte den Remainder auf einmal immer um 3 und kam nicht zu einem
Ende.) Also haben wir versucht das Assignment in Python zu lösen.
Da konnte, dann das Beispiel aus den Folien mit p=59, q=29 reproduziert werden. Allerdings funktionierte
dies für die 1024/160 Bit variante wieder nicht. Das Programm war mehrere Stunden am rechnen ohne auf
Lösung zu kommen. Ebenfalls war uns dann nicht ganz klar wie die SHA(x) funktion zu realisieren ist.
Ebenso hatten wir einige Mühe die Rechnungen nachvollziehen zu können.

@ -21,7 +21,7 @@
#include "encryptionArithmetic.h"
#include "DSA.h"
#define KEY_LENGTH 1024
#define KEY_LENGTH 16
#define DIVISOR 160
int generateDsaKey(void);
@ -48,9 +48,12 @@ void main(void) {
}
int generateDsaKey(void) {
const char* p_string = "9999999999999999";
const char* q_string = "AFFE12345678AFFE";
const char* d_string = "9778729279583412";
/*const char* p_string = "C8462B074900AD6622E5FE3F945BD2C6D570FAFF63BDCF4287AAC84DEF28BA0D7BF3EF9D3FF4A5D0821BDB1FBEED32CA5DE56B1832B648F40C5C205EA8694F828DF9C1583E284AC773F595809E442BB7D5E256B1C68E7E80C782D9469D351D5E9C434A2CBD2A1AB4527B11B405128A2146F12882742A732EADE720ECE2BC1B4D";
const char* q_string = "810E78D2D6C8B0BB8A15FFEA19EBED45D6CB0495";
const char* d_string = "9778729279583412";*/
const char* p_string = "3B";
const char* q_string = "1D";
const char* d_string = "10";
// P has to be a prime number!
t_encryptionArithmetic p;
@ -71,15 +74,23 @@ int generateDsaKey(void) {
t_encryptionArithmetic alpha_k;
encryptionArithmetic_Init(&alpha_k, KEY_LENGTH);
t_encryptionArithmetic alpha;
encryptionArithmetic_Init(&alpha, KEY_LENGTH);
for (uint32_t i = 0; i < UINT32_MAX; i++) {
square(&alpha, &q, &alpha_k, KEY_LENGTH);
moduloOperation(&alpha_k, &q, KEY_LENGTH);
if (alpha.number == 1) {
printf("Found alpha k where = 1");
break;
}
encryptionArithmetic_Init(&alpha, 64);
const char* alpha_string = "20000000";
if (encryptionArithmetic_stringToHex(alpha_string, alpha.number, 64) == false) {
printf("ERROR: Creating q.");
return 1000001;
}
moduloOperation(&alpha, &q, KEY_LENGTH);
//for (*alpha.number = 2; *alpha.number < *p.number; *alpha.number = *alpha.number + 1) {
////for(uint32_t i = 2; i < UINT32_MAX; i++){
// //encryptionArithmetic_copyNumber(&i, alpha.number, KEY_LENGTH);
// square(&alpha, &q, &alpha_k, KEY_LENGTH);
// moduloOperation(&alpha_k, &q, KEY_LENGTH);
// if (*alpha_k.number == 1) {
// printf("Found alpha k where = 1");
// break;
// }
//}
t_encryptionArithmetic d;
encryptionArithmetic_Init(&d, KEY_LENGTH);
@ -104,43 +115,6 @@ int generateDsaKey(void) {
int calculateSessionKey(void) {
/*** Calculate Session Key ***/
const char* P_string = "3203431780337000";
const char* Priv_a_string = "9778729279583412";
const char* Pub_b_string = "13BED5BE5045000";
// P has to be a prime number! Large prime number (64bit): 3203431780337000
t_encryptionArithmetic P;
encryptionArithmetic_Init(&P, KEY_LENGTH);
if (encryptionArithmetic_stringToHex(P_string, P.number, KEY_LENGTH) == false) {
printf("ERROR: Creating P.");
return 1100000;
}
t_encryptionArithmetic priv_a;
encryptionArithmetic_Init(&priv_a, KEY_LENGTH);
if (encryptionArithmetic_stringToHex(Priv_a_string, priv_a.number, KEY_LENGTH) == false) {
printf("ERROR: Creating priv a.");
return 1100003;
}
t_encryptionArithmetic pub_b;
encryptionArithmetic_Init(&pub_b, KEY_LENGTH);
if (encryptionArithmetic_stringToHex(Pub_b_string, pub_b.number, KEY_LENGTH) == false) {
printf("ERROR: Creating pub b.");
return 1100004;
}
/* initialize and calculate session key for person a */
t_encryptionArithmetic session_key_a;
encryptionArithmetic_Init(&session_key_a, KEY_LENGTH);
squareAndMultiply(&pub_b, &priv_a, &P, &session_key_a, KEY_LENGTH);
printf("Calculated session key for person A: 0x");
for (int num_bytes = KEY_LENGTH / 64; num_bytes >= 0; num_bytes--) {
printf("%X", *((uint32_t*)(session_key_a.number + num_bytes)));
}
printf("\n");
return 0;
}

Loading…
Cancel
Save