forked from NiMouh/D-RSA
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrandgen.c
More file actions
173 lines (146 loc) · 4.7 KB
/
randgen.c
File metadata and controls
173 lines (146 loc) · 4.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/**
* @file randgen.c
* @author Ana Raquel Neves Vidal (118408)
* @author Simão Augusto Ferreira Andrade (118345)
* @brief This file contains the implementation of the randgen algorithm in C.
* @date 2023-12-20
*
* @copyright Copyright (c) 2023
*
*/
// Standard libraries
#include <stdio.h>
#include <stdint.h>
#include <string.h>
// OpenSSL libraries
#include <openssl/sha.h>
#include <openssl/evp.h>
// Constants
#define SEED_SIZE 32 // bytes
#define BUFFER_SIZE 4096 // bytes
/**
* @brief Function to check if A is a subarray of B
*
* @param A reference array A
* @param a_size size of A
* @param B reference array B
* @param b_size size of B
*
* @return 1 if A is a subarray of B, 0 otherwise
*/
int pattern_found(uint8_t A[], int a_size, uint8_t B[], int b_size)
{
if (a_size > b_size)
{
fprintf(stderr, "A is longer than B\n");
return 0;
}
for (int i = 0; i <= b_size - a_size; i++)
{
int match = 1;
for (int j = 0; j < a_size; j++)
{
if (B[i + j] != A[j])
{
match = 0;
break; // mismatch
}
}
if (match)
{
return 1;
}
}
return 0; // A is not a subarray of B
}
/**
* @brief Function to use the generator to produce a pseudo-random stream of bytes
*
* @param stream a pointer to an array where the bytes will be allocated
* @param stream_size the size of the array
* @param seed value that will start the generator
*/
void generate_pseudo_random_stream(uint8_t *stream, int stream_size, uint8_t seed[SEED_SIZE])
{
uint8_t hash_output[SHA256_DIGEST_LENGTH];
for (int index = 0; index < stream_size; index += SHA256_DIGEST_LENGTH)
{
SHA256(seed, SEED_SIZE, hash_output); // hash the seed
// Copy the hash output to the stream
int bytes_to_copy = (index + SHA256_DIGEST_LENGTH <= stream_size) ? SHA256_DIGEST_LENGTH : stream_size - index;
memcpy(stream + index, hash_output, bytes_to_copy);
memcpy(seed, hash_output, SHA256_DIGEST_LENGTH); // seed = hash_output
}
}
/**
* @brief This function generates the pbkdf2
*
* @param password The password to be used
* @param salt The salt to be used
* @param iterations The number of iterations to be used
* @param key_derivator The output pbkdf2
*
* @return 1 if the pbkdf2 was generated successfully, 0 otherwise
*/
int pbkdf2(const char *password, const char *salt, int iterations, uint8_t *key_derivator)
{
if (PKCS5_PBKDF2_HMAC(password, strlen(password), (const unsigned char *)salt, strlen(salt), iterations, EVP_sha256(), SEED_SIZE + strlen(salt), key_derivator) != 1)
{
fprintf(stderr, "Error generating key derivator\n");
return 0;
}
return 1;
}
/**
* @brief This function generates arbirtary a pseudo-random byte stream
*
* @param size The size of the byte stream to be generated
* @param password The password to be used
* @param confusion_string The confusion string to be used
* @param iterations The number of iterations to be used
* @param bytes The output byte array
*
*/
void randgen(int size, const char *password, const char *confusion_string, int iterations, uint8_t *bytes)
{
uint8_t key_derivator[SEED_SIZE + strlen(confusion_string)];
if (!pbkdf2(password, confusion_string, iterations, key_derivator))
{
fprintf(stderr, "Error generating key derivator\n");
exit(EXIT_FAILURE);
}
uint8_t seed[SEED_SIZE];
uint8_t confusion_pattern[strlen(confusion_string)];
// get the seed and the confusion pattern from the key derivator
memcpy(seed, key_derivator, SEED_SIZE);
memcpy(confusion_pattern, key_derivator + SEED_SIZE, strlen(confusion_string));
for (int iteration = 0; iteration < iterations; iteration++)
{
uint8_t temp_buffer[size];
while (1)
{
generate_pseudo_random_stream(temp_buffer, size, seed);
if (pattern_found(confusion_pattern, strlen(confusion_string), temp_buffer, size))
{
break;
}
}
memcpy(bytes, temp_buffer, size);
memcpy(seed, bytes + size - SEED_SIZE, SEED_SIZE);
}
}
int main(int argc, char *argv[])
{
if (argc != 4) // ./randgen <password> <confusion_string> <iterations>
{
fprintf(stderr, "Usage: %s <password> <confusion_string> <iterations>\n", argv[0]);
exit(EXIT_FAILURE);
}
const char *password = argv[1];
const char *confusion_string = argv[2];
int iterations = atoi(argv[3]);
uint8_t bytes[BUFFER_SIZE];
randgen(BUFFER_SIZE, password, confusion_string, iterations, bytes);
fwrite(bytes, sizeof(uint8_t), BUFFER_SIZE, stdout);
return 0;
}