comparison src/protocols/yahoo/crypt.c @ 10684:72a5babfa8b4

[gaim-migrate @ 12231] the cipher api that grim has been working on for ages is finally done!! big congrats and thanks to him!! lots of modified files in this commit. it builds here. moved the md5 files to src/protocols/oscar so that it continues to depend on nothing in gaim. everything else uses the new centralized cipher api. I'm not sure if src/md5.* needs to be removed or not, so I left it there. someone let me know or do it directly. someone check if these need to be added to potfiles.in and let there be much rejoicing! committer: Tailor Script <tailor@pidgin.im>
author Luke Schierer <lschiere@pidgin.im>
date Fri, 11 Mar 2005 13:05:31 +0000
parents e46efd264489
children b256ce6b85b8
comparison
equal deleted inserted replaced
10683:e11f3e1599d4 10684:72a5babfa8b4
24 24
25 #include <string.h> 25 #include <string.h>
26 #include <stdlib.h> 26 #include <stdlib.h>
27 #include <glib.h> 27 #include <glib.h>
28 28
29 #include "md5.h" 29 #include "cipher.h"
30 30
31 /* Define our magic string to mark salt for MD5 "encryption" 31 /* Define our magic string to mark salt for MD5 "encryption"
32 replacement. This is meant to be the same as for other MD5 based 32 replacement. This is meant to be the same as for other MD5 based
33 encryption implementations. */ 33 encryption implementations. */
34 static const char md5_salt_prefix[] = "$1$"; 34 static const char md5_salt_prefix[] = "$1$";
37 static const char b64t[64] = 37 static const char b64t[64] =
38 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 38 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
39 39
40 char *yahoo_crypt(const char *key, const char *salt) 40 char *yahoo_crypt(const char *key, const char *salt)
41 { 41 {
42 GaimCipher *cipher;
43 GaimCipherContext *context1, *context2;
44 guint8 digest[16];
42 static char *buffer = NULL; 45 static char *buffer = NULL;
43 static int buflen = 0; 46 static int buflen = 0;
44 int needed = 3 + strlen (salt) + 1 + 26 + 1; 47 int needed = 3 + strlen (salt) + 1 + 26 + 1;
45 48
46 md5_byte_t alt_result[16];
47 md5_state_t ctx;
48 md5_state_t alt_ctx;
49 size_t salt_len; 49 size_t salt_len;
50 size_t key_len; 50 size_t key_len;
51 size_t cnt; 51 size_t cnt;
52 char *cp; 52 char *cp;
53 53
55 buflen = needed; 55 buflen = needed;
56 if ((buffer = g_realloc(buffer, buflen)) == NULL) 56 if ((buffer = g_realloc(buffer, buflen)) == NULL)
57 return NULL; 57 return NULL;
58 } 58 }
59 59
60 cipher = gaim_ciphers_find_cipher("md5");
61 context1 = gaim_cipher_context_new(cipher, NULL);
62 context2 = gaim_cipher_context_new(cipher, NULL);
63
60 /* Find beginning of salt string. The prefix should normally always 64 /* Find beginning of salt string. The prefix should normally always
61 be present. Just in case it is not. */ 65 * be present. Just in case it is not.
66 */
62 if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0) 67 if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
63 /* Skip salt prefix. */ 68 /* Skip salt prefix. */
64 salt += sizeof (md5_salt_prefix) - 1; 69 salt += sizeof (md5_salt_prefix) - 1;
65 70
66 salt_len = MIN (strcspn (salt, "$"), 8); 71 salt_len = MIN (strcspn (salt, "$"), 8);
67 key_len = strlen (key); 72 key_len = strlen (key);
68 73
69 /* Prepare for the real work. */
70 md5_init(&ctx);
71
72 /* Add the key string. */ 74 /* Add the key string. */
73 md5_append(&ctx, key, key_len); 75 gaim_cipher_context_append(context1, key, key_len);
74 76
75 /* Because the SALT argument need not always have the salt prefix we 77 /* Because the SALT argument need not always have the salt prefix we
76 add it separately. */ 78 * add it separately.
77 md5_append(&ctx, md5_salt_prefix, sizeof (md5_salt_prefix) - 1); 79 */
80 gaim_cipher_context_append(context1, md5_salt_prefix,
81 sizeof(md5_salt_prefix) - 1);
78 82
79 /* The last part is the salt string. This must be at most 8 83 /* The last part is the salt string. This must be at most 8
80 characters and it ends at the first `$' character (for 84 * characters and it ends at the first `$' character (for
81 compatibility which existing solutions). */ 85 * compatibility which existing solutions).
82 md5_append(&ctx, salt, salt_len); 86 */
87 gaim_cipher_context_append(context1, salt, salt_len);
83 88
84 /* Compute alternate MD5 sum with input KEY, SALT, and KEY. The 89 /* Compute alternate MD5 sum with input KEY, SALT, and KEY. The
85 final result will be added to the first context. */ 90 * final result will be added to the first context.
86 md5_init(&alt_ctx); 91 */
87 92
88 /* Add key. */ 93 /* Add key. */
89 md5_append(&alt_ctx, key, key_len); 94 gaim_cipher_context_append(context2, key, key_len);
90 95
91 /* Add salt. */ 96 /* Add salt. */
92 md5_append(&alt_ctx, salt, salt_len); 97 gaim_cipher_context_append(context2, salt, salt_len);
93 98
94 /* Add key again. */ 99 /* Add key again. */
95 md5_append(&alt_ctx, key, key_len); 100 gaim_cipher_context_append(context2, key, key_len);
96 101
97 /* Now get result of this (16 bytes) and add it to the other 102 /* Now get result of this (16 bytes) and add it to the other context. */
98 context. */ 103 gaim_cipher_context_digest(context2, NULL, digest);
99 md5_finish(&alt_ctx, alt_result);
100 104
101 /* Add for any character in the key one byte of the alternate sum. */ 105 /* Add for any character in the key one byte of the alternate sum. */
102 for (cnt = key_len; cnt > 16; cnt -= 16) 106 for (cnt = key_len; cnt > 16; cnt -= 16)
103 md5_append(&ctx, alt_result, 16); 107 gaim_cipher_context_append(context1, digest, 16);
104 md5_append(&ctx, alt_result, cnt); 108 gaim_cipher_context_append(context1, digest, cnt);
105 109
106 /* For the following code we need a NUL byte. */ 110 /* For the following code we need a NUL byte. */
107 alt_result[0] = '\0'; 111 digest[0] = '\0';
108 112
109 /* The original implementation now does something weird: for every 1 113 /* The original implementation now does something weird: for every 1
110 bit in the key the first 0 is added to the buffer, for every 0 114 * bit in the key the first 0 is added to the buffer, for every 0
111 bit the first character of the key. This does not seem to be 115 * bit the first character of the key. This does not seem to be
112 what was intended but we have to follow this to be compatible. */ 116 * what was intended but we have to follow this to be compatible.
117 */
113 for (cnt = key_len; cnt > 0; cnt >>= 1) 118 for (cnt = key_len; cnt > 0; cnt >>= 1)
114 md5_append(&ctx, (cnt & 1) != 0 ? alt_result : (md5_byte_t *)key, 1); 119 gaim_cipher_context_append(context1,
120 (cnt & 1) != 0 ? digest : (guint8 *)key, 1);
115 121
116 /* Create intermediate result. */ 122 /* Create intermediate result. */
117 md5_finish(&ctx, alt_result); 123 gaim_cipher_context_digest(context1, NULL, digest);
118 124
119 /* Now comes another weirdness. In fear of password crackers here 125 /* Now comes another weirdness. In fear of password crackers here
120 comes a quite long loop which just processes the output of the 126 * comes a quite long loop which just processes the output of the
121 previous round again. We cannot ignore this here. */ 127 * previous round again. We cannot ignore this here.
128 */
122 for (cnt = 0; cnt < 1000; ++cnt) { 129 for (cnt = 0; cnt < 1000; ++cnt) {
123 /* New context. */ 130 /* New context. */
124 md5_init(&ctx); 131 gaim_cipher_context_reset(context2, NULL);
125 132
126 /* Add key or last result. */ 133 /* Add key or last result. */
127 if ((cnt & 1) != 0) 134 if ((cnt & 1) != 0)
128 md5_append(&ctx, key, key_len); 135 gaim_cipher_context_append(context2, key, key_len);
129 else 136 else
130 md5_append(&ctx, alt_result, 16); 137 gaim_cipher_context_append(context2, digest, 16);
131 138
132 /* Add salt for numbers not divisible by 3. */ 139 /* Add salt for numbers not divisible by 3. */
133 if (cnt % 3 != 0) 140 if (cnt % 3 != 0)
134 md5_append(&ctx, salt, salt_len); 141 gaim_cipher_context_append(context2, salt, salt_len);
135 142
136 /* Add key for numbers not divisible by 7. */ 143 /* Add key for numbers not divisible by 7. */
137 if (cnt % 7 != 0) 144 if (cnt % 7 != 0)
138 md5_append(&ctx, key, key_len); 145 gaim_cipher_context_append(context2, key, key_len);
139 146
140 /* Add key or last result. */ 147 /* Add key or last result. */
141 if ((cnt & 1) != 0) 148 if ((cnt & 1) != 0)
142 md5_append(&ctx, alt_result, 16); 149 gaim_cipher_context_append(context2, digest, 16);
143 else 150 else
144 md5_append(&ctx, key, key_len); 151 gaim_cipher_context_append(context2, key, key_len);
145 152
146 /* Create intermediate result. */ 153 /* Create intermediate result. */
147 md5_finish(&ctx, alt_result); 154 gaim_cipher_context_digest(context2, NULL, digest);
148 } 155 }
149 156
150 /* Now we can construct the result string. It consists of three 157 /* Now we can construct the result string. It consists of three parts. */
151 parts. */
152
153 strncpy(buffer, md5_salt_prefix, MAX (0, buflen)); 158 strncpy(buffer, md5_salt_prefix, MAX (0, buflen));
154 cp = buffer + strlen(buffer); 159 cp = buffer + strlen(buffer);
155 buflen -= sizeof (md5_salt_prefix); 160 buflen -= sizeof (md5_salt_prefix);
156 161
157 strncpy(cp, salt, MIN ((size_t) buflen, salt_len)); 162 strncpy(cp, salt, MIN ((size_t) buflen, salt_len));
172 --buflen; \ 177 --buflen; \
173 w >>= 6; \ 178 w >>= 6; \
174 }\ 179 }\
175 } while (0) 180 } while (0)
176 181
177 b64_from_24bit (alt_result[0], alt_result[6], alt_result[12], 4); 182 b64_from_24bit (digest[0], digest[6], digest[12], 4);
178 b64_from_24bit (alt_result[1], alt_result[7], alt_result[13], 4); 183 b64_from_24bit (digest[1], digest[7], digest[13], 4);
179 b64_from_24bit (alt_result[2], alt_result[8], alt_result[14], 4); 184 b64_from_24bit (digest[2], digest[8], digest[14], 4);
180 b64_from_24bit (alt_result[3], alt_result[9], alt_result[15], 4); 185 b64_from_24bit (digest[3], digest[9], digest[15], 4);
181 b64_from_24bit (alt_result[4], alt_result[10], alt_result[5], 4); 186 b64_from_24bit (digest[4], digest[10], digest[5], 4);
182 b64_from_24bit (0, 0, alt_result[11], 2); 187 b64_from_24bit (0, 0, digest[11], 2);
183 if (buflen <= 0) { 188 if (buflen <= 0) {
184 g_free(buffer); 189 g_free(buffer);
185 buffer = NULL; 190 buffer = NULL;
186 } else 191 } else
187 *cp = '\0'; /* Terminate the string. */ 192 *cp = '\0'; /* Terminate the string. */
188 193
189 /* Clear the buffer for the intermediate result so that people 194 /* Clear the buffer for the intermediate result so that people
190 attaching to processes or reading core dumps cannot get any 195 * attaching to processes or reading core dumps cannot get any
191 information. We do it in this way to clear correct_words[] 196 * information. We do it in this way to clear correct_words[]
192 inside the MD5 implementation as well. */ 197 * inside the MD5 implementation as well.
193 md5_init(&ctx); 198 */
194 md5_finish(&ctx, alt_result); 199 gaim_cipher_context_reset(context1, NULL);
195 memset (&ctx, '\0', sizeof (ctx)); 200 gaim_cipher_context_digest(context1, NULL, digest);
196 memset (&alt_ctx, '\0', sizeof (alt_ctx)); 201 gaim_cipher_context_destroy(context1);
202 gaim_cipher_context_destroy(context2);
197 203
198 return buffer; 204 return buffer;
199 } 205 }