00001
00002
00003
00004
00005
00006
00007 #include "wvcrypto.h"
00008 #include "strutils.h"
00009 #include <assert.h>
00010 #include <blowfish.h>
00011 #include <rsa.h>
00012 #include <md5.h>
00013
00014
00016
00017
00018
00019 WvCryptoStream::WvCryptoStream(WvStream *_slave) : WvStreamClone(&slave)
00020 {
00021 slave = _slave;
00022 my_cryptbuf = NULL;
00023 cryptbuf_size = 0;
00024 }
00025
00026
00027 WvCryptoStream::~WvCryptoStream()
00028 {
00029
00030 }
00031
00032
00033 unsigned char *WvCryptoStream::cryptbuf(size_t size)
00034 {
00035 if (size > cryptbuf_size)
00036 {
00037 if (my_cryptbuf)
00038 delete[] my_cryptbuf;
00039 cryptbuf_size = size;
00040 my_cryptbuf = new unsigned char[size];
00041 }
00042
00043 return my_cryptbuf;
00044 }
00045
00046
00048
00049
00050
00051 WvXORStream::WvXORStream(WvStream *_slave, unsigned char _xorvalue)
00052 : WvCryptoStream(_slave)
00053 {
00054 xorvalue = _xorvalue;
00055 }
00056
00057
00058 size_t WvXORStream::uwrite(const void *buf, size_t size)
00059 {
00060 unsigned char *out = cryptbuf(size);
00061 const unsigned char *i = (const unsigned char *)buf;
00062 unsigned char *o = out;
00063 size_t count;
00064
00065 for (count = 0; count < size; count++)
00066 *o++ = (*i++) ^ xorvalue;
00067
00068 return WvCryptoStream::uwrite(out, size);
00069 }
00070
00071
00072 size_t WvXORStream::uread(void *buf, size_t size)
00073 {
00074 unsigned char *in = cryptbuf(size);
00075 const unsigned char *i = (const unsigned char *)in;
00076 unsigned char *o = (unsigned char *)buf;
00077 size_t count;
00078
00079 size = WvCryptoStream::uread(in, size);
00080
00081 for (count = 0; count < size; count++)
00082 *o++ = (*i++) ^ xorvalue;
00083 return size;
00084 }
00085
00086
00087
00089
00090
00091
00092 WvBlowfishStream::WvBlowfishStream(WvStream *_slave, const void *_key,
00093 size_t keysize)
00094 : WvCryptoStream(_slave)
00095 {
00096 key = new BF_KEY;
00097 BF_set_key(key, keysize, (unsigned char *)_key);
00098 ennum = denum = 0;
00099 memset(envec, 0, sizeof(envec));
00100 memset(devec, 0, sizeof(devec));
00101 }
00102
00103
00104 size_t WvBlowfishStream::uwrite(const void *buf, size_t size)
00105 {
00106 void *out = cryptbuf(size);
00107
00108 BF_cfb64_encrypt((unsigned char *)buf,
00109 (unsigned char *)out, size, key,
00110 envec, &ennum, BF_ENCRYPT);
00111
00112 return WvCryptoStream::uwrite(out, size);
00113 }
00114
00115
00116 size_t WvBlowfishStream::uread(void *buf, size_t size)
00117 {
00118 void *in = cryptbuf(size);
00119 size = WvCryptoStream::uread(in, size);
00120
00121 BF_cfb64_encrypt((unsigned char *)in,
00122 (unsigned char *)buf, size, key,
00123 devec, &denum, BF_DECRYPT);
00124
00125 return size;
00126 }
00127
00128
00129 WvBlowfishStream::~WvBlowfishStream()
00130 {
00131 delete key;
00132 }
00133
00134
00135
00137
00138
00139
00140 WvRSAKey::WvRSAKey(const char *_keystr, bool priv)
00141 {
00142
00143
00144
00145 int hexbytes = strlen(_keystr);
00146 int bufsize = ((hexbytes < 2048) ? 2048 : hexbytes) + 16;
00147
00148
00149 unsigned char *keybuf = new unsigned char[bufsize], *bufp;
00150 char *keystr;
00151 RSA *rp;
00152
00153 keystr = strdup(_keystr);
00154
00155 memset(keybuf, 0, bufsize);
00156 unhexify(keybuf, keystr);
00157 bufp = keybuf;
00158 rp = rsa = RSA_new();
00159
00160 if (priv)
00161 {
00162 rsa = d2i_RSAPrivateKey(&rp, &bufp, hexbytes/2);
00163 prv = keystr;
00164
00165 size_t size;
00166 unsigned char *iend = keybuf;
00167 size = i2d_RSAPublicKey(rsa, &iend);
00168 pub = (char *)malloc(size * 2 + 1);
00169 hexify(pub, keybuf, size);
00170 }
00171 else
00172 {
00173 rsa = d2i_RSAPublicKey(&rp, &bufp, hexbytes/2);
00174 prv = NULL;
00175 pub = keystr;
00176 }
00177
00178 delete[] keybuf;
00179 }
00180
00181
00182 WvRSAKey::WvRSAKey(int bits)
00183 {
00184 size_t size;
00185 unsigned char *keybuf, *iend;
00186
00187 rsa = RSA_generate_key(bits, 3, NULL, NULL);
00188
00189 size = i2d_RSAPrivateKey(rsa, NULL);
00190 iend = keybuf = new unsigned char[size];
00191 i2d_RSAPrivateKey(rsa, &iend);
00192
00193 prv = (char *)malloc(size * 2 + 1);
00194 hexify(prv, keybuf, size);
00195
00196 iend = keybuf;
00197 size = i2d_RSAPublicKey(rsa, &iend);
00198
00199 pub = (char *)malloc(size * 2 + 1);
00200 hexify(pub, keybuf, size);
00201
00202 delete[] keybuf;
00203 }
00204
00205
00206 WvRSAKey::~WvRSAKey()
00207 {
00208 if (prv)
00209 free(prv);
00210 if (pub)
00211 free(pub);
00212 if (rsa)
00213 RSA_free(rsa);
00214 }
00215
00216
00217
00219
00220
00221
00222 WvRSAStream::WvRSAStream(WvStream *_slave,
00223 WvRSAKey &_my_key, WvRSAKey &_their_key)
00224 : WvCryptoStream(_slave),
00225 my_key(_my_key.private_str(), true),
00226 their_key(_their_key.public_str(), false)
00227 {
00228
00229 if (my_key.rsa)
00230 slave->queuemin(RSA_size(my_key.rsa));
00231 }
00232
00233
00234 WvRSAStream::~WvRSAStream()
00235 {
00236
00237 slave->queuemin(0);
00238 }
00239
00240
00241
00242
00243 size_t WvRSAStream::uread(void *buf, size_t size)
00244 {
00245 unsigned char *in = cryptbuf(size);
00246
00247 if (!my_key.rsa)
00248 {
00249
00250 WvStreamClone::uread(buf, size);
00251 return 0;
00252 }
00253
00254 size_t len, decode_len, rsa_size = RSA_size(my_key.rsa);
00255
00256 if (size > rsa_size)
00257 size = rsa_size;
00258
00259 len = WvStreamClone::uread(in, rsa_size);
00260 if (len < rsa_size)
00261 {
00262
00263
00264 return 0;
00265 }
00266
00267
00268 unsigned char *decoded = new unsigned char[rsa_size];
00269 decode_len = RSA_private_decrypt(len, in, decoded,
00270 my_key.rsa, RSA_PKCS1_PADDING);
00271
00272 if (decode_len == (size_t)-1)
00273 return 0;
00274
00275
00276 if (decode_len < size)
00277 size = decode_len;
00278 memcpy(buf, decoded, size);
00279
00280
00281 inbuf.put(decoded+size, decode_len - size);
00282
00283 delete decoded;
00284 return size;
00285 }
00286
00287
00288 size_t WvRSAStream::uwrite(const void *buf, size_t size)
00289 {
00290 if (!their_key.rsa)
00291 {
00292
00293
00294 return size;
00295 }
00296
00297 size_t off, len, totalwrite = 0, rsa_size = RSA_size(my_key.rsa), outsz;
00298 unsigned char *out = cryptbuf(rsa_size);
00299
00300
00301 for (off = 0; off < size; off += rsa_size/2)
00302 {
00303 if (size-off < rsa_size/2)
00304 len = size-off;
00305 else
00306 len = rsa_size/2;
00307
00308 outsz = RSA_public_encrypt(len, (unsigned char *)buf+off, out,
00309 their_key.rsa, RSA_PKCS1_PADDING);
00310 assert(outsz == rsa_size);
00311
00312
00313
00314
00315 if (WvStreamClone::uwrite(out, outsz))
00316 totalwrite += len;
00317 }
00318
00319 return totalwrite;
00320 }
00321
00322 WvMD5::WvMD5(const WvString &string_to_hash)
00323 {
00324 MD5_CTX ctx;
00325 unsigned char temp[20];
00326
00327 MD5_Init(&ctx);
00328 MD5_Update(&ctx,(const unsigned char *)string_to_hash.cstr(),
00329 strlen(string_to_hash));
00330 MD5_Final(temp, &ctx);
00331 md5_hash_value = (unsigned char *)calloc(1,sizeof(temp));
00332 memcpy(md5_hash_value,temp,sizeof(temp));
00333 }
00334
00335 WvMD5::WvMD5(FILE *file_to_hash)
00336 {
00337 unsigned char buf[1024];
00338 unsigned char temp[20];
00339 MD5_CTX ctx;
00340 int n;
00341
00342 MD5_Init(&ctx);
00343 while ((n = fread(buf, 1, sizeof(buf), file_to_hash)) > 0)
00344 MD5_Update(&ctx, buf, n);
00345 MD5_Final(temp, &ctx);
00346 if (ferror(file_to_hash))
00347 md5_hash_value = NULL;
00348 else
00349 {
00350 md5_hash_value = (unsigned char *)calloc(1,sizeof(temp));
00351 memcpy(md5_hash_value,temp,sizeof(temp));
00352 }
00353 }
00354
00355 WvMD5::~WvMD5()
00356 {
00357 free(md5_hash_value);
00358 }
00359
00360 WvString WvMD5::md5_hash() const
00361 {
00362 int count;
00363 unsigned char *temp;
00364 WvString hash_value("");
00365
00366 temp = md5_hash_value;
00367 for (count = 0; count < 16; count++)
00368 {
00369 char buf[2];
00370 snprintf(buf,2,"%02x", *temp++);
00371 hash_value.append(buf);
00372 }
00373
00374 return hash_value;
00375 }