Initial commit
[pwdhash.git] / hmacmd5.c
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <time.h>
4 #include <string.h>
5 #include <stdbool.h>
6
7 #include "cencode.h"
8 #include "md5.h"
9
10 #include "hmacmd5.h"
11
12 #define SPH_kkPasswordPrefixLength (2)
13
14 void md5print(unsigned char digest[DIGEST_SIZE]) {
15 int pos;
16
17 for (pos = 0; pos < DIGEST_SIZE; pos++) {
18 printf ("%02x", digest[pos]);
19 }
20 }
21
22 void writeHexByte(unsigned char byte, unsigned char * hex) {
23 static char number[] = "0123456789abcdef";
24
25 hex[0] = number[(byte >> 4)];
26 hex[1] = number[(byte % 16)];
27 }
28
29 void md5hmac(unsigned char * key, unsigned char * inString, unsigned char digest[DIGEST_SIZE]) {
30 mbedtls_md5_context mdContext;
31 unsigned int keylen;
32 int pos;
33 unsigned char ipad[BLOCK_SIZE];
34 unsigned char opad[BLOCK_SIZE];
35 unsigned char hash[DIGEST_SIZE];
36
37 // Ensure key length is exaclty 16 bytes
38 keylen = strlen(key);
39 if (keylen > BLOCK_SIZE) {
40 mbedtls_md5(key, keylen, hash);
41 memcpy(ipad, hash, DIGEST_SIZE);
42 memcpy(opad, hash, DIGEST_SIZE);
43 keylen = DIGEST_SIZE;
44 }
45 else {
46 memcpy(ipad, key, keylen);
47 memcpy(opad, key, keylen);
48 }
49 for (pos = keylen; pos < BLOCK_SIZE; pos++) {
50 ipad[pos] = '\0';
51 opad[pos] = '\0';
52 }
53
54 for (pos = 0; pos < BLOCK_SIZE; pos++) {
55 ipad[pos] ^= 0x36;
56 opad[pos] ^= 0x5C;
57 }
58
59 mbedtls_md5_init(& mdContext);
60 mbedtls_md5_starts(& mdContext);
61 mbedtls_md5_update(& mdContext, ipad, BLOCK_SIZE);
62 mbedtls_md5_update(& mdContext, inString, strlen(inString));
63 mbedtls_md5_finish(& mdContext, hash);
64 mbedtls_md5_free(& mdContext);
65
66 mbedtls_md5_init(& mdContext);
67 mbedtls_md5_starts(& mdContext);
68 mbedtls_md5_update(& mdContext, opad, BLOCK_SIZE);
69 mbedtls_md5_update(& mdContext, hash, DIGEST_SIZE);
70 mbedtls_md5_finish(& mdContext, digest);
71 mbedtls_md5_free(& mdContext);
72 }
73
74 static void md5hmactest() {
75 unsigned char digest[DIGEST_SIZE];
76 //unsigned char output[DIGEST_SIZE];
77 //mbedtls_md5("Hello", 5, output);
78 //md5print(output);
79 //printf ("\n");
80
81 md5hmac("key", "The quick brown fox jumps over the lazy dog", digest);
82 md5print(digest);
83 printf ("\n");
84 }
85
86 bool containsnonalphanumeric(unsigned char * password, int length) {
87 bool nonalphanumeric;
88 unsigned int pos;
89 char check;
90 int startingSize;
91
92 nonalphanumeric = false;
93 for (pos = 0; (pos < length) && !nonalphanumeric; pos++) {
94 check = password[pos];
95 if (!((check >= 'a') && (check <= 'z'))
96 && !((check >= 'A') && (check <= 'Z'))
97 && !((check >= '0') && (check <= '9'))
98 && !(check == '_')) {
99 nonalphanumeric = true;
100 }
101 }
102
103 return nonalphanumeric;
104 }
105
106 bool contains(unsigned char * password, int length, char start, char end) {
107 bool doescontain = false;
108 unsigned int pos;
109
110 for (pos = 0; (pos < length) && (doescontain == false); pos++) {
111 if ((password[pos] >= start) && (password[pos] <= end)) {
112 doescontain = true;
113 }
114 }
115
116 return doescontain;
117 }
118
119 void rotate(unsigned char * torotate, int length, int steps) {
120 char scratch[RESULT_MAX];
121 unsigned int pos;
122
123 for (pos = 0; pos < length; pos++) {
124 scratch[pos] = torotate[(pos + steps) % length];
125 }
126
127 for (pos = 0; pos < length; pos++) {
128 torotate[pos] = scratch[pos];
129 }
130 }
131
132 void SPH_HashedPassowrd(unsigned char * password, unsigned char * realm, unsigned char result[RESULT_MAX]) {
133 unsigned char digest[DIGEST_SIZE];
134 base64_encodestate state_in;
135 size_t size;
136 unsigned char hash[25];
137 int extraSize = 0;
138 bool nonalphanumeric;
139 int startingSize;
140 int extraPos;
141 char next;
142 unsigned int pos;
143
144 md5hmac(password, realm, digest);
145
146 base64_init_encodestate(& state_in);
147 size = base64_encode_block(digest, DIGEST_SIZE, hash, & state_in);
148 size += base64_encode_blockend(hash + size, & state_in);
149 hash[24] = '\0';
150 hash[23] = '\0';
151 hash[22] = '\0';
152 extraSize = strlen(hash);
153
154 size = strlen(password) + SPH_kkPasswordPrefixLength;
155
156 nonalphanumeric = containsnonalphanumeric(password, strlen(password));
157 startingSize = size - 4;
158
159 startingSize = startingSize < extraSize ? startingSize : extraSize;
160 memcpy(result, hash, startingSize);
161 extraPos = startingSize;
162
163 // Add the extras
164 next = (extraPos < extraSize) ? hash[extraPos] : 0;
165 extraPos++;
166 if (!contains(result, startingSize, 'A', 'Z')) {
167 next = 'A' + (next % ('Z' - 'A' + 1));
168 }
169 result[startingSize] = next;
170 startingSize++;
171
172 next = (extraPos < extraSize) ? hash[extraPos] : 0;
173 extraPos++;
174 if (!contains(result, startingSize, 'a', 'z')) {
175 next = 'a' + (next % ('z' - 'a' + 1));
176 }
177 result[startingSize] = next;
178 startingSize++;
179
180 next = (extraPos < extraSize) ? hash[extraPos] : 0;
181 extraPos++;
182 if (!contains(result, startingSize, '0', '9')) {
183 next = '0' + (next % ('9' - '0' + 1));
184 }
185 result[startingSize] = next;
186 startingSize++;
187
188 if (containsnonalphanumeric(result, startingSize) && nonalphanumeric) {
189 next = (extraPos < extraSize) ? hash[extraPos] : 0;
190 extraPos++;
191 }
192 else {
193 next = '+';
194 }
195 result[startingSize] = next;
196 startingSize++;
197
198 if (!nonalphanumeric) {
199 for (pos = 0; pos < startingSize; pos++) {
200 if (containsnonalphanumeric(result + pos, 1)) {
201 next = (extraPos < extraSize) ? hash[extraPos] : 0;
202 extraPos++;
203 next = 'A' + (next % ('Z' - 'A' + 1));
204 result[pos] = next;
205 }
206 }
207 }
208
209 next = (extraPos < extraSize) ? hash[extraPos] : 0;
210 rotate(result, startingSize, next);
211 result[startingSize] = '\0';
212 }
213
214 //int main(int argc, char * argv[]) {
215 // SPH_HashedPassowrd("lsksjfjsdfsjdflsksjfjsdfsjdflsksjfjsdfsjdflsksjfjsdfsjdf", "flypig.co.uk");
216 //
217 // return 0;
218 //}
219