added assignment 05 filesmain
parent
473f7e785f
commit
e5b69b386e
@ -0,0 +1,216 @@ |
|||||||
|
/**
|
||||||
|
*--------------------------------------------------------------------\n |
||||||
|
* HSLU T&A Hochschule Luzern Technik+Architektur \n |
||||||
|
*--------------------------------------------------------------------\n |
||||||
|
* |
||||||
|
* \brief ASYD assignment crypto 05 |
||||||
|
* \file |
||||||
|
* \author Basil Estermann, basil.estermann@stud.hslu.ch |
||||||
|
* Simon Frei, simon.frei@stud.hslu.ch |
||||||
|
* Jonas Arnold, jonas.arnold@stud.hslu.ch |
||||||
|
* \date 23.03.2023 |
||||||
|
* |
||||||
|
*-------------------------------------------------------------------- |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <string.h> |
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
#define VALUE_LENGTH 32 |
||||||
|
#define MESSAGE_DIGEST_LENGTH 160 |
||||||
|
#define BLOCK_LENGTH (512/8) |
||||||
|
#define INPUT_MESSAGE ("Lorem ipsum dolor sit amet, consetetur sadipscing.") |
||||||
|
|
||||||
|
#pragma region Macros |
||||||
|
#define INT_64_LOW_BYTE(input) (input & 0xff) |
||||||
|
#define INT_64_HIGH_BYTE(input) ((input>>8) & 0xff) |
||||||
|
#pragma endregion |
||||||
|
|
||||||
|
#pragma region SHA1-Constants |
||||||
|
// initial hash values
|
||||||
|
#define H0 0x67452301 |
||||||
|
#define H1 0xEFCDAB89 |
||||||
|
#define H2 0x98BADCFE |
||||||
|
#define H3 0x10325476 |
||||||
|
#define H4 0xC3D2E1F0 |
||||||
|
// constants Kt
|
||||||
|
#define K1 0x5A827999 |
||||||
|
#define K2 0x6ED9EBA1 |
||||||
|
#define K3 0x8F1BBCDC |
||||||
|
#define K4 0xCA62C1D6 |
||||||
|
#pragma endregion |
||||||
|
|
||||||
|
void printBits(size_t const size, void const* const ptr); |
||||||
|
uint32_t leftRotate(uint32_t n, uint32_t d); |
||||||
|
uint32_t SHA1_f1(uint32_t b, uint32_t c, uint32_t d); |
||||||
|
uint32_t SHA1_f2(uint32_t b, uint32_t c, uint32_t d); |
||||||
|
uint32_t SHA1_f3(uint32_t b, uint32_t c, uint32_t d); |
||||||
|
uint32_t SHA1_f4(uint32_t b, uint32_t c, uint32_t d); |
||||||
|
|
||||||
|
void main(void) { |
||||||
|
|
||||||
|
int result = 0; |
||||||
|
|
||||||
|
printf("****** SHA1 preprocessing ******\n\n"); |
||||||
|
#pragma region Preprocessing |
||||||
|
|
||||||
|
printf("------ Set initial hash value ------\n\n"); |
||||||
|
#pragma region Initial Hash values |
||||||
|
uint32_t a, b, c, d, e; |
||||||
|
uint32_t h[5] = { H0, H1, H2, H3, H4 }; |
||||||
|
uint32_t k[5] = { 0, K1, K2, K3, K4 }; // 5 so the array can be accessed by 1, 2, 3, 4
|
||||||
|
a = h[0]; |
||||||
|
b = h[1]; |
||||||
|
c = h[2]; |
||||||
|
d = h[3]; |
||||||
|
e = h[4]; |
||||||
|
|
||||||
|
#pragma endregion |
||||||
|
|
||||||
|
if (sizeof(INPUT_MESSAGE) * 8 > 447) { |
||||||
|
printf("Message too long!"); |
||||||
|
return 1000002; |
||||||
|
} |
||||||
|
|
||||||
|
printf("------ Padding message ------\n\n"); |
||||||
|
#pragma region Padding |
||||||
|
// print information about message without padding
|
||||||
|
unsigned char messageNoPadding[] = INPUT_MESSAGE; |
||||||
|
int numBytesMessage = (sizeof(INPUT_MESSAGE) - 1); // -1 because of '\0' at end of the string
|
||||||
|
printf("Size of message without padding: %i bits\n", numBytesMessage*8); |
||||||
|
printf("Message without padding\n"); |
||||||
|
printBits(sizeof(messageNoPadding), &messageNoPadding); |
||||||
|
|
||||||
|
unsigned char message[BLOCK_LENGTH] = ""; |
||||||
|
// fill in message
|
||||||
|
for (uint32_t i = 0; i < numBytesMessage; i++) |
||||||
|
{ |
||||||
|
message[i] = INPUT_MESSAGE[i]; |
||||||
|
} |
||||||
|
// set bit
|
||||||
|
message[numBytesMessage] = 0b10000000; |
||||||
|
printf("\nMessage after adding 1: \n"); |
||||||
|
printBits(sizeof(message), &message); |
||||||
|
// add length with high and low byte (length is 64bit)
|
||||||
|
message[BLOCK_LENGTH - 1] = INT_64_LOW_BYTE(numBytesMessage * 8); |
||||||
|
message[BLOCK_LENGTH - 2] = INT_64_HIGH_BYTE(numBytesMessage * 8); |
||||||
|
printf("\nMessage after adding length: \n"); |
||||||
|
printBits(sizeof(message), &message); |
||||||
|
#pragma endregion |
||||||
|
|
||||||
|
#pragma endregion |
||||||
|
|
||||||
|
printf("\n\n****** Hash computation ******\n\n"); |
||||||
|
#pragma region Hash computation |
||||||
|
|
||||||
|
printf("\n------ Prepare message schedule ------\n\n"); |
||||||
|
#pragma region Prepare message schedule |
||||||
|
uint32_t WordArray[80] = { 0 }; |
||||||
|
for (uint32_t i = 0; i < 16; i++) { |
||||||
|
uint32_t currentbyte = message[i] << 24; |
||||||
|
uint32_t tmp = (uint32_t)(((uint8_t)(message[i * 4]) << 24) + ((uint8_t)(message[4 * i + 1]) << 16) + ((uint8_t)(message[4 * i + 2]) << 8) + (uint8_t)(message[4 * i + 3])); |
||||||
|
WordArray[i] = tmp; |
||||||
|
} |
||||||
|
for (uint32_t i = 16; i < 80; i++) { |
||||||
|
WordArray[i] = leftRotate((WordArray[i - 3] ^ WordArray[i - 8] ^ WordArray[i - 14] ^ WordArray[i - 16]), 1); |
||||||
|
} |
||||||
|
#pragma endregion |
||||||
|
|
||||||
|
printf("\n------ Stages ------\n\n"); |
||||||
|
#pragma region Stages calculations |
||||||
|
uint32_t (*f_ptr)(uint32_t, uint32_t, uint32_t) = &SHA1_f1; // use: (*f_ptr)(b,c,d);
|
||||||
|
uint8_t stage = 1; |
||||||
|
// print header row
|
||||||
|
printf("\tA\t\tB\t\tC\t\tD\t\tE\n"); |
||||||
|
|
||||||
|
// stage 1...4
|
||||||
|
for (uint32_t t = 0; t < 80; t++) { |
||||||
|
uint32_t T = leftRotate(a, 5) + ((*f_ptr)(b, c, d)) + e + k[stage] + WordArray[t]; |
||||||
|
e = d; |
||||||
|
d = c; |
||||||
|
c = leftRotate(b, 30); |
||||||
|
b = a; |
||||||
|
a = T; |
||||||
|
|
||||||
|
// print row
|
||||||
|
printf("t= %02d:\t%08X\t%08X\t%08X\t%08X\t%08X\t\n", t, a, b, c, d, e); |
||||||
|
|
||||||
|
// switch stages
|
||||||
|
if (t == 19) { f_ptr = SHA1_f2; stage = 2; printf("Switched to stage 2.\n"); } |
||||||
|
else if (t == 39) { f_ptr = SHA1_f3; stage = 3; printf("Switched to stage 3.\n"); } |
||||||
|
else if (t == 59) { f_ptr = SHA1_f4; stage = 4; printf("Switched to stage 4.\n"); } |
||||||
|
} |
||||||
|
#pragma endregion |
||||||
|
|
||||||
|
printf("\n------ Intermediate hash calculation ------\n\n"); |
||||||
|
#pragma region intermediate hash calculation |
||||||
|
uint32_t summand[5] = { a, b, c, d, e }; |
||||||
|
for (uint8_t i = 0; i < 5; i++) { |
||||||
|
// calculate
|
||||||
|
uint32_t h_new = summand[i] + h[i]; |
||||||
|
// print
|
||||||
|
printf("H[%i] = %08X + %08X = %08X\n", i, summand[i], h[i], h_new); |
||||||
|
// set value
|
||||||
|
h[i] = h_new; |
||||||
|
} |
||||||
|
|
||||||
|
#pragma endregion |
||||||
|
#pragma endregion |
||||||
|
|
||||||
|
printf("\n****** Resulting hash ******\n\n"); |
||||||
|
for (uint8_t i = 0; i < 5; i++) { |
||||||
|
printf("%X ", h[i]); |
||||||
|
} |
||||||
|
printf("\n\n"); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t SHA1_f1(uint32_t b, uint32_t c, uint32_t d) { |
||||||
|
return (b & c) | (~b & d); |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t SHA1_f2(uint32_t b, uint32_t c, uint32_t d) { |
||||||
|
return b ^ c ^ d; |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t SHA1_f3(uint32_t b, uint32_t c, uint32_t d) { |
||||||
|
return (b & c) | (b & d) | (c & d); |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t SHA1_f4(uint32_t b, uint32_t c, uint32_t d) { |
||||||
|
return b ^ c ^ d; |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t leftRotate(uint32_t n, uint32_t d) |
||||||
|
{ |
||||||
|
/* In n<<d, last d bits are 0. To put first 3 bits of n at
|
||||||
|
last, do bitwise or of n<<d with n >>(INT_BITS - d) */ |
||||||
|
return (n << d) | (n >> (VALUE_LENGTH - d)); |
||||||
|
} |
||||||
|
|
||||||
|
// Assumes little endian
|
||||||
|
void printBits(size_t const size, void const* const ptr) |
||||||
|
{ |
||||||
|
unsigned char* b = (unsigned char*)ptr; |
||||||
|
unsigned char byte; |
||||||
|
int i, j; |
||||||
|
|
||||||
|
for (i = 0; i < size; i++) { |
||||||
|
for (j = 7; j >= 0; j--) { |
||||||
|
byte = (b[i] >> j) & 1; |
||||||
|
printf("%u", byte); |
||||||
|
} |
||||||
|
} |
||||||
|
/*original:
|
||||||
|
for (i = size - 1; i >= 0; i--) { |
||||||
|
for (j = 7; j >= 0; j--) { |
||||||
|
byte = (b[i] >> j) & 1; |
||||||
|
printf("%u", byte); |
||||||
|
} |
||||||
|
}*/ |
||||||
|
puts(""); |
||||||
|
} |
||||||
@ -0,0 +1,11 @@ |
|||||||
|
Assignment crypto 05 |
||||||
|
Gruppenmitglieder: Basil Estermann, Jonas Arnold, Simon Frei |
||||||
|
|
||||||
|
Wir konnten erfolgreich einen SHA-1 Hash Generator implementieren. Wie vorgesehen lässt sich der SHA-1 mit den verhältnismässig kleinen Zahlen (32bit) gut implementieren, auch beispielsweise auf Embedded Systemen mit der Programmiersprache C. |
||||||
|
Bei der Implementierung haben wir uns hauptsächlich auf das Dokument der NIST gestützt. Das Preprocessing bzw. Padding der Nachricht haben wir gemäss Abschnitt 5.1.1. implementiert. Aktuell kann unser Programm nur den Hash von eine Nachricht (1 Block a 512bit, mit Padding also maxima 447bit für Nachricht bzw. 55 ASCII Zeichen) berechnen. Dies wäre einfach erweiterbar gemäss Abschnitt 5.2.1. Die Hash Berechnung, welche wir anhand Abschnitt 6.1.2 implementiert haben, müsste ebenfalls um eine for-schleife von "i=1 bis N" erweitert werden. |
||||||
|
|
||||||
|
Verifiziert haben wir unseren Generator einerseits mit den hilfreichen SHA1_DebugHelp.pdf von ILIAS. Damit war einfach nachvollziehbar wo unser Programm falsch rechnet. Ausserdem haben wir einen online SHA-1 Generator (http://www.sha1-online.com/) verwendet, um weitere Nachrichten zu testen. |
||||||
|
Mithilfe dieser Verifikation war es möglich den Algorithmus zum Laufen zu bringen. Ein Prolglem bei der Implementierung war, dass wir erst den String-Ende Indikator ('\0') auch in den Hash integriert hatten, was dann zu anderen Hashes geführt hat als z.B. dem online SHA-1 Generator. Dieses Problem konnte jedoch rasch behoben werden, indem das '\0' einfach nicht miteinbezogen wird. |
||||||
|
|
||||||
|
Beim Testen vom Hash einer Gruppen auf Ilias mussten wir jedoch feststellen, dass unser SHA-1 Generator nur bis zu einer Nachrichtengrösse von 32 Zeichen funktioniert. Der Grund dafür war, dass wir lediglich das Low-Byte der Länge der Nachricht in das Padding der Nachricht integriert hatten. Nachdem wir auch das High-Byte integrierten (nun also volle 64bit für die Länge der Nachricht am Ende des Message Blocks) konnten wir den SHA-1 Hash der anderen Gruppe OdermattStefan/PfrennigerDavid auch erfolgreich generieren. |
||||||
|
Leider war zum Zeitpunkt dieses Berichts auch nur ein einziges Testfile einer anderen Gruppe im Austausch-Ordner. |
||||||
@ -0,0 +1,4 @@ |
|||||||
|
Message: |
||||||
|
Lorem ipsum dolor sit amet, consetetur sadipscing. |
||||||
|
Hash: |
||||||
|
95A2B0D2 1278E3CB EF1D6F24 59366764 D0648AA7 |
||||||
Loading…
Reference in new issue