00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include <string>
00024
#include <memory>
00025
#include <cmath>
00026
00027
#include "cryptopp/misc.h"
00028
#include "cryptopp/idea.h"
00029
#include "cryptopp/rng.h"
00030
#include "cryptopp/osrng.h"
00031
#include "cryptopp/files.h"
00032
#include "cryptopp/rsa.h"
00033
#include "cryptopp/queue.h"
00034
#include "cryptopp/randpool.h"
00035
#include "cryptopp/hex.h"
00036
#include "cryptopp/osrng.h"
00037
#include "cryptopp/rijndael.h"
00038
#include "cryptopp/mars.h"
00039
#include "cryptopp/des.h"
00040
#include "cryptopp/3way.h"
00041
#include "cryptopp/idea.h"
00042
#include "cryptopp/serpent.h"
00043
#include "cryptopp/rc2.h"
00044
#include "cryptopp/rc5.h"
00045
#include "cryptopp/blowfish.h"
00046
#include "cryptopp/rc6.h"
00047
#include "cryptopp/camellia.h"
00048
#include "cryptopp/twofish.h"
00049
#include "cryptopp/tea.h"
00050
#include "cryptopp/modes.h"
00051
#include "cryptopp/sha.h"
00052
#include "cryptopp/md2.h"
00053
#include "cryptopp/md5.h"
00054
#include "cryptopp/haval.h"
00055
#include "cryptopp/ripemd.h"
00056
#include "cryptopp/tiger.h"
00057
#include "cryptopp/default.h"
00058
#include "cryptopp/base64.h"
00059
#include "cryptopp/base32.h"
00060
#include "cryptopp/panama.h"
00061
#include "cryptopp/gzip.h"
00062
#include "cryptopp/zlib.h"
00063
#include "cryptopp/filters.h"
00064
#include "cryptopp/secblock.h"
00065
00066
#include "gm/cryptography.h"
00067
#include "gm/crypto_defs.h"
00068
#include "gm/misc.h"
00069
00070
namespace GNUMessenger {
00071
00072
using namespace CryptoPP;
00073
using namespace std;
00074
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
#if 0 // dunno if i need these
00110
void Cryptography::compressFile(
const string& data,
const string& filename)
00111 {
00112
00113
try {
00114 StringSource f(data.c_str(),
true,
00115
new Gzip(
00116
new FileSink(filename.c_str())
00117 )
00118 );
00119 }
catch (CryptoPP::Exception &e) {
00120
throw DiskError(e.what());
00121 }
00122
00123 }
00124
00125 string Cryptography::decompressFile(
const string& infile)
00126 {
00127
00128 string decryptedFile;
00129
try {
00130 FileSource f(infile.c_str(),
true,
00131
new Gunzip(
00132
new StringSink(decryptedFile)
00133 )
00134 );
00135 }
catch (CryptoPP::Exception &e) {
00136
throw DiskError(e.what());
00137 }
00138
return decryptedFile;
00139
00140 }
00141
#endif
00142
00143 HashTransformation * CryptoManager::getHash(CryptDefines::Hashes type)
00144
throw (
AlgoError)
00145 {
00146
switch (type)
00147 {
00148
case(CryptDefines::SHA1):
return new SHA();
00149
case(CryptDefines::SHA_256):
return new SHA256();
00150
case(CryptDefines::SHA_384):
return new SHA384();
00151
case(CryptDefines::SHA_512):
return new SHA512();
00152
case(CryptDefines::MD_2):
return new MD2();
00153
case(CryptDefines::MD_5):
return new MD5();
00154
case(CryptDefines::HAVAL_3):
return new HAVAL3();
00155
case(CryptDefines::HAVAL_4):
return new HAVAL4();
00156
case(CryptDefines::HAVAL_5):
return new HAVAL5();
00157
case(CryptDefines::RIPEMD_160):
return new RIPEMD160();
00158
case(CryptDefines::_TIGER):
return new Tiger();
00159
#ifdef IS_LITTLE_ENDIAN
00160
case(CryptDefines::PANAMA_HASH):
00161
return new PanamaHash<LittleEndian>();
00162
#else
00163
case(CryptDefines::PANAMA_HASH):
00164
return new PanamaHash<BigEndian>();
00165
#endif
00166
default:
throw AlgoError(
"Invalid Hash Algorithm.");
00167 }
00168 }
00169
00170 byte * CryptoManager::hash(
const string& data,
unsigned int& len,
00171 CryptDefines::Hashes hashType)
throw (
AlgoError)
00172 {
00173 auto_ptr<HashTransformation> theHash(getHash(hashType));
00174
00175 byte * result =
new byte[theHash->DigestSize()];
00176 theHash->CalculateDigest(result, (byte *)data.c_str(), data.length());
00177
00178
return result;
00179 }
00180
00181 byte * CryptoManager::generateIV(
const SecByteBlock& data,
00182 CryptDefines::Hashes hash)
00183 {
00184 auto_ptr<HashTransformation> theHash(
getHash(hash));
00185
00186 byte * result =
new byte[theHash->DigestSize()];
00187
00188 SecByteBlock hashed(theHash->DigestSize());
00189 theHash->CalculateDigest(hashed, data, data.size());
00190
00191
00192
for (
unsigned int i = 0; i < theHash->DigestSize() / 2; i++)
00193 result[i] = hashed[i] ^ hashed[i+ (theHash->DigestSize() / 2)];
00194
00195
return result;
00196 }
00197
00198
unsigned int CryptoManager::testRNG(
const unsigned int insize)
00199
throw (RNGError)
00200 {
00201
unsigned int result = 0;
00202
00203 byte * randomData = generateRandom(insize);
00204 byte * compressedData = compress(SecByteBlock(randomData, insize),
00205 result);
00206
delete [] compressedData;
00207
delete [] randomData;
00208
00209
return result;
00210
00211 }
00212
00213 byte * CryptoManager::generateRandom(
const unsigned int size)
00214
throw (
RNGError)
00215 {
00216
00217 byte * result =
new byte[size];
00218
00219 AutoSeededRandomPool rng;
00220
try {
00221 rng.GenerateBlock(result, size);
00222 }
catch (OS_RNG_Err &e) {
00223
delete [] result;
00224
throw RNGError(e.what());
00225 }
00226
return result;
00227
00228 }
00229
00230 byte * CryptoManager::compress(
const SecByteBlock& data,
00231
unsigned int& resultLen,
00232
const unsigned int level)
00233 {
00234 ZlibCompressor z(NULL, level);
00235 z.Put(data, data.size());
00236 z.MessageEnd();
00237
00238 resultLen = z.MaxRetrievable();
00239 byte * out =
new byte[resultLen];
00240 z.Get(out, z.MaxRetrievable());
00241
00242
return out;
00243 }
00244
00245 byte * CryptoManager::decompress(
const SecByteBlock& data,
00246
unsigned int& resultLen)
00247 {
00248 ZlibDecompressor inflate;
00249 inflate.Put(data, data.size());
00250 inflate.MessageEnd();
00251
00252 resultLen = inflate.MaxRetrievable();
00253 byte * out =
new byte[resultLen];
00254 inflate.Get(out, inflate.MaxRetrievable());
00255
00256
return out;
00257 }
00258
00259 byte * CryptoManager::encrypt(
const SecByteBlock& data,
00260
const SecByteBlock& key,
00261
unsigned int& resultLen,
00262
const unsigned int blockSize,
00263 CryptDefines::BlockCipher cipher,
00264 CryptDefines::Mode mode)
00265
throw (
RNGError,
AlgoError,
KeySizeError,
BlockSizeError)
00266 {
00267
00268 auto_ptr<SymmetricCipher> theCipher(getEncryptor(cipher,mode));
00269
00270
if (!theCipher->IsValidKeyLength(key.size()))
00271
throw KeySizeError(
"Invalid key size for this cipher",
00272 theCipher->MinKeyLength(),
00273 theCipher->MaxKeyLength());
00274
00275
if (theCipher->IVRequirement() == theCipher->RANDOM_IV)
00276 LOG_DEBUG(
"Requires random IV");
00277
00278 SecByteBlock iv(
00279 generateIV(
00280 SecByteBlock(
00281 generateRandom(theCipher->MandatoryBlockSize()),
00282 theCipher->MandatoryBlockSize()
00283 )
00284 ),
00285 theCipher->MandatoryBlockSize()
00286 );
00287
00288 theCipher->SetKeyWithIV(key, key.size(), iv);
00289 ArraySink cipherText;
00290
00291 StreamTransformationFilter encryptor(*theCipher, &cipherText);
00292 encryptor.Put(data, data.size());
00293
00294 encryptor.MessageEnd();
00295
return NULL;
00296 }
00297
00298 string CryptoManager::encode(
const SecByteBlock& data,
00299 CryptDefines::Encoding type)
throw (
AlgoError)
00300 {
00301 string result;
00302 auto_ptr<SimpleProxyFilter> encoder;
00303
00304
switch (type) {
00305
case(CryptDefines::Base64):
00306 encoder.reset(
new Base64Encoder(
new StringSink(result)));
00307
break;
00308
case(CryptDefines::Base32):
00309 encoder.reset(
new Base32Encoder(
new StringSink(result)));
00310
break;
00311
case(CryptDefines::Hex):
00312 encoder.reset(
new HexEncoder(
new StringSink(result)));
00313
break;
00314
default:
throw AlgoError(
"No such encoding system.");
00315 }
00316
00317 encoder->Put(data, data.size());
00318 encoder->MessageEnd();
00319
return result;
00320 }
00321
00322 SymmetricCipher * CryptoManager::getEncryptor(
00323 CryptDefines::BlockCipher cipher,
00324 CryptDefines::Mode mode)
00325
throw (AlgoError)
00326 {
00327
00328
00329
return NULL;
00330 }
00331
00332
00333 bool CryptoManager::encryptFile(
const string& filename,
const VBuffer& key,
00334
const string& data)
throw (
IOError)
00335 {
00336
00337
00338 SecByteBlock ivSeed(CryptDefines::IV_SEED_LENGTH);
00339 SecByteBlock realIv(CryptDefines::IV_LENGTH);
00340
00341 AutoSeededRandomPool rng;
00342 rng.GenerateBlock(ivSeed, CryptDefines::IV_SEED_LENGTH);
00343
00344
00345 SecByteBlock ivHash(SHA256::DIGESTSIZE);
00346 SHA256().CalculateDigest(ivHash, ivSeed, CryptDefines::IV_SEED_LENGTH);
00347
00348
for (
unsigned int i = 0; i != CryptDefines::IV_LENGTH; ++i)
00349 realIv[i] = ivHash[i] ^ ivHash[i+16];
00350
00351
00352 ZlibCompressor z(NULL,9);
00353 z.Put((
const unsigned char *)data.c_str(),
00354 static_cast<unsigned int>(data.length()));
00355 z.MessageEnd();
00356
00357 SecByteBlock compressedPlainText(z.MaxRetrievable());
00358 z.Get(compressedPlainText, compressedPlainText.size());
00359
00360
00361 SecByteBlock cipherText(compressedPlainText.size());
00362
00363 CBC_Mode<MARS>::Encryption enc(key.data(), key.size(), realIv.data());
00364 StreamTransformationFilter encryptor(enc);
00365 encryptor.Put(compressedPlainText, compressedPlainText.size());
00366 encryptor.MessageEnd();
00367
00369 cipherText.CleanGrow(encryptor.MaxRetrievable());
00370 encryptor.Get(cipherText, cipherText.size());
00371
00372
00373 SecByteBlock myMac(HMAC<SHA>::DIGESTSIZE);
00374 HMAC<SHA> themac(key.data(), key.size());
00375 themac.Update(cipherText, cipherText.size());
00376 themac.Final(myMac);
00377
00378
00379
try {
00380 Base64Encoder encoder(
new FileSink(filename.c_str(),
false));
00381 encoder.Put(realIv, CryptDefines::IV_LENGTH);
00382 encoder.Put(cipherText, cipherText.size());
00383 encoder.Put(myMac, HMAC<SHA>::DIGESTSIZE);
00384 encoder.MessageEnd();
00385
00386 }
catch(CryptoPP::Exception &e) {
00387
throw IOError(e.what());
00388 }
00389
00390
return true;
00391
00392 }
00393
00394 string CryptoManager::decryptFile(
const string& filename,
00395
const VBuffer &key)
00396
throw (InvalidPassword, AuthFailed)
00397 {
00398
00399 FileSource inputFile(filename.c_str(),
true);
00400 SecByteBlock dataFromFile(inputFile.MaxRetrievable());
00401 inputFile.Get(dataFromFile, dataFromFile.size());
00402
00403
00404 Base64Decoder decoder64;
00405 decoder64.Put(dataFromFile, dataFromFile.size());
00406 decoder64.MessageEnd();
00407
00408 SecByteBlock iv(CryptDefines::IV_LENGTH);
00409 SecByteBlock payload(decoder64.MaxRetrievable() -
00410 CryptDefines::IV_LENGTH - HMAC<SHA>::DIGESTSIZE);
00411 SecByteBlock hmac(HMAC<SHA>::DIGESTSIZE);
00412
00413
00414 decoder64.Get(iv, CryptDefines::IV_LENGTH);
00415 decoder64.Get(payload, payload.size());
00416 decoder64.Get(hmac, HMAC<SHA>::DIGESTSIZE);
00417
00418
00419 CBC_Mode<MARS>::Decryption dec(key.data(), key.size(), iv.data());
00420 StreamTransformationFilter decf(dec);
00421
00422
try {
00423 decf.Put(payload, payload.size());
00424 decf.MessageEnd();
00425 }
catch (CryptoPP::Exception& e) {
00426
throw InvalidPassword(e.what());
00427 }
00428
00429
00430
00431
if (!HMAC<SHA>(key.data(), key.size()).VerifyDigest(hmac, payload,
00432 payload.size()))
00433
throw AuthFailed(
"File digest not verified.");
00434
00435
00436 SecByteBlock compressedPlaintext(decf.MaxRetrievable());
00437
00438
00439 decf.Get(compressedPlaintext, compressedPlaintext.size());
00440
00441 string output;
00442 ZlibDecompressor zDecompressor(
new StringSink(output));
00443 zDecompressor.Put(compressedPlaintext, compressedPlaintext.size());
00444 zDecompressor.MessageEnd();
00445
00446
return output;
00447
00448 }
00449
00450 string CryptoManager::hashEncode(
const VBuffer& toHash,
00451 CryptDefines::Hashes hashf,
00452 CryptDefines::Encoding enc)
00453 {
00454 VBuffer block(
hash(toHash, hashf));
00455 auto_ptr<Filter> encoding;
00456
00457 string outString;
00458
00459
switch (enc) {
00460
case (CryptDefines::Hex):
00461 encoding.reset(
new HexEncoder(
new StringSink(outString)));
00462
break;
00463
case (CryptDefines::Base64):
00464 encoding.reset(
new Base64Encoder(
new StringSink(outString),
false));
00465
break;
00466
case (CryptDefines::Base32):
00467 encoding.reset(
new Base32Encoder(
new StringSink(outString),
false));
00468
break;
00469
default:
break;
00470 };
00471
00472 encoding->Put(block.data(), block.size());
00473 encoding->MessageEnd();
00474
00475
return outString;
00476 }
00477
00478
00479 VBuffer CryptoManager::hash(
const VBuffer& toHash, CryptDefines::Hashes hashf)
00480 {
00481 auto_ptr<HashTransformation>
hash;
00482
00483
switch (hashf)
00484 {
00485
case(CryptDefines::SHA1): hash.reset(
new SHA);
break;
00486
case(CryptDefines::SHA_256): hash.reset(
new SHA256);
break;
00487
case(CryptDefines::SHA_384): hash.reset(
new SHA384);
break;
00488
case(CryptDefines::SHA_512): hash.reset(
new SHA512);
break;
00489
case(CryptDefines::MD_2): hash.reset(
new MD2);
break;
00490
case(CryptDefines::MD_5): hash.reset(
new MD5);
break;
00491
case(CryptDefines::HAVAL_3): hash.reset(
new HAVAL3);
break;
00492
case(CryptDefines::HAVAL_4): hash.reset(
new HAVAL4);
break;
00493
case(CryptDefines::HAVAL_5): hash.reset(
new HAVAL5);
break;
00494
case(CryptDefines::RIPEMD_160): hash.reset(
new RIPEMD160);
break;
00495
case(CryptDefines::_TIGER): hash.reset(
new Tiger);
break;
00496 }
00497
00498 SecByteBlock retBlock(hash->DigestSize());
00499 hash->CalculateDigest(retBlock, toHash.data(), toHash.size());
00500
00501 VBuffer ret(retBlock.begin(), retBlock.size());
00502
00503
return ret;
00504
00505 }
00506
00507 }
00508
00509