parent
e62232101b
commit
ef8d569966
@ -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)) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
@ -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. |
||||||
Loading…
Reference in new issue