00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "wave-crypto.h"
00037
00038 #ifdef WIN32
00039
00040 #include "third-party/openssl/openssl/des.h"
00041 #include "third-party/openssl/openssl/rsa.h"
00042 #include "third-party/openssl/openssl/sha.h"
00043 #else // WIN32
00044
00045 #include <openssl/des.h>
00046 #include <openssl/rsa.h>
00047 #include <openssl/sha.h>
00048 #endif // WIN32
00049
00050 #include "common/wave_ex.h"
00051 #include "perf/perf.h"
00052
00053
00054 namespace crypto {
00055
00056
00057 static const int s_keyNumber = 1536;
00058 static const long s_keyExponent = 65537;
00059 static const int s_padding = RSA_PKCS1_OAEP_PADDING;
00060
00061 static const int32_t s_maxEncodeLength = 0x007FFFFFF;
00062
00063 static const int s_bytesPerDESBlock = 8;
00064
00065 typedef std::vector<byte_t> byte_vec_t;
00066
00067
00068
00069 RSAPublicKey::~RSAPublicKey(void) throw() { }
00070 RSAKey::~RSAKey(void) throw() { }
00071 DESKey::~DESKey(void) throw() { }
00072
00073
00074 static char s_base64encode[65] =
00075 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
00076
00077 static int s_base64decode[128];
00078
00079
00080
00081
00082
00083
00084
00085
00086 static void
00087 initializeDecoding
00088 (
00089 void
00090 )
00091 throw()
00092 {
00093 for (int i = 0; i < 128; ++i) {
00094 s_base64decode[i] = -1;
00095 }
00096 for (int i = 0; i < 26; ++i) {
00097 s_base64decode['A' + i] = i;
00098 s_base64decode['a' + i] = i + 26;
00099 }
00100 for (int i = 0; i < 10; ++i) {
00101 s_base64decode['0' + i] = i + 52;
00102 }
00103 s_base64decode['-' + 0] = 62;
00104 s_base64decode['_' + 0] = 63;
00105 }
00106
00107
00108
00109 static void
00110 encodeInt32
00111 (
00112 IO std::string& out,
00113 IN int32_t l
00114 )
00115 {
00116 ASSERT(l >= 0 && l < s_maxEncodeLength, "bad l: %ld", (long) l);
00117
00118
00119 char buff[4];
00120 for (int i = 0; i < 4; ++i) {
00121 int val = l % 64;
00122 l = l / 64;
00123 buff[i] = s_base64encode[val];
00124 }
00125
00126 for (int i = 3; i >= 0; --i) {
00127 out += buff[i];
00128 }
00129 }
00130
00131
00132
00133 static int32_t
00134 decodeInt32
00135 (
00136 IN const char * p
00137 )
00138 {
00139 int32_t l = 0;
00140 for (int i = 0; i < 4; ++i, ++p) {
00141 l = 64 * l;
00142 l += s_base64decode[(int) *p];
00143 }
00144 return l;
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 static long
00174 symmetricEncrypt
00175 (
00176 IN const byte_t * input,
00177 IN long bytes,
00178 IN DES_key_schedule * ks,
00179 IN int flag,
00180 OUT byte_vec_t& output
00181 )
00182 {
00183 ASSERT(input, "null");
00184 ASSERT(bytes > 0, "bad bytes: %ld", bytes);
00185 ASSERT(ks, "null");
00186 output.clear();
00187
00188
00189 int remainder = bytes % s_bytesPerDESBlock;
00190 int nBlocks = bytes / s_bytesPerDESBlock;
00191
00192 long output_size = ((nBlocks + 1) * s_bytesPerDESBlock) + 1;
00193 output.resize(output_size);
00194
00195 long output_bytes = 0;
00196 byte_t * b = &output[0];
00197 DES_cblock in_dcb;
00198 DES_cblock out_dcb;
00199 const byte_t * p = input;
00200 for (int i = 0; i < nBlocks; ++i, p += s_bytesPerDESBlock) {
00201
00202 DES_ecb_encrypt((const_DES_cblock *) p, &out_dcb, ks, flag);
00203
00204
00205
00206 memcpy(b, out_dcb, s_bytesPerDESBlock);
00207 b += s_bytesPerDESBlock;
00208 output_bytes += s_bytesPerDESBlock;
00209 }
00210
00211
00212 if (remainder) {
00213 byte_t * q = (byte_t *) in_dcb;
00214 memcpy(q, p, remainder);
00215 memset(q + remainder, 0, s_bytesPerDESBlock - remainder);
00216
00217 DES_ecb_encrypt(&in_dcb, &out_dcb, ks, flag);
00218 memcpy(b, out_dcb, s_bytesPerDESBlock);
00219
00220 output_bytes += s_bytesPerDESBlock;
00221 }
00222
00223 return output_bytes;
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 class PublicKey : public RSAPublicKey {
00235 public:
00236 PublicKey(void) throw();
00237 ~PublicKey(void) throw();
00238
00239
00240 void initialize(IN const char * serialized);
00241 void initialize(IN RSA * rsa);
00242
00243
00244 std::string serialize(void);
00245 std::string encrypt(IN const char * plaintext);
00246
00247 private:
00248
00249 RSA * m_rsa;
00250 };
00251
00252
00253
00254 PublicKey::PublicKey
00255 (
00256 void
00257 )
00258 throw()
00259 {
00260 m_rsa = NULL;
00261 }
00262
00263
00264 PublicKey::~PublicKey
00265 (
00266 void
00267 )
00268 throw()
00269 {
00270 if (m_rsa) {
00271 RSA_free(m_rsa);
00272 }
00273 }
00274
00275
00276
00277 void
00278 PublicKey::initialize
00279 (
00280 IN const char * serialized
00281 )
00282 {
00283 ASSERT(serialized, "null");
00284
00285
00286
00287
00288 m_rsa = RSA_new();
00289 ASSERT(m_rsa, "failed to create empty RSA key");
00290 ASSERT(!m_rsa->n, "already have n?");
00291 ASSERT(!m_rsa->e, "already have e?");
00292
00293
00294
00295 const int buffsize = 1024;
00296 char buffer[buffsize];
00297 const char * s = strstr(serialized, ":");
00298 if (!s) {
00299 WAVE_EX(wex);
00300 wex << "Malformed serialized key";
00301 }
00302 int iN = s - serialized;
00303 if (iN < 1 || iN >= buffsize) {
00304 WAVE_EX(wex);
00305 wex << "Malformed serialized key";
00306 }
00307 strncpy(buffer, serialized, iN);
00308 buffer[iN] = 0;
00309
00310 BN_hex2bn(&m_rsa->n, buffer);
00311
00312 serialized += iN + 1;
00313 iN = strlen(serialized);
00314 if (iN < 1 || iN >= buffsize) {
00315 WAVE_EX(wex);
00316 wex << "Malformed serialized key";
00317 }
00318 strcpy(buffer, serialized);
00319
00320 BN_hex2bn(&m_rsa->e, buffer);
00321 }
00322
00323
00324
00325 void
00326 PublicKey::initialize
00327 (
00328 IN RSA * rsa
00329 )
00330 {
00331 ASSERT(rsa, "null");
00332 ASSERT(!m_rsa, "already have a key?");
00333 m_rsa = rsa;
00334 }
00335
00336
00337
00338 std::string
00339 PublicKey::serialize
00340 (
00341 void
00342 )
00343 {
00344 std::string public_key;
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 ASSERT(m_rsa, "null");
00356 ASSERT(m_rsa->n, "null");
00357 ASSERT(m_rsa->e, "null");
00358
00359 char * n = BN_bn2hex(m_rsa->n);
00360 char * e = BN_bn2hex(m_rsa->e);
00361
00362
00363
00364
00365 public_key += n;
00366 public_key += ":";
00367 public_key += e;
00368
00369 OPENSSL_free(n);
00370 OPENSSL_free(e);
00371
00372
00373 return public_key;
00374 }
00375
00376
00377
00378 std::string
00379 PublicKey::encrypt
00380 (
00381 IN const char * plaintext
00382 )
00383 {
00384 perf::Timer timer("crypto::RSAPublicKey::encrypt");
00385 ASSERT(m_rsa, "null");
00386 ASSERT(plaintext, "null");
00387
00388 long bytes = strlen(plaintext);
00389
00390
00391 int rbytes = RSA_size(m_rsa);
00392
00393 ASSERT(bytes > 0, "bad byte count? %d", rbytes);
00394
00395 std::vector<byte_t> out;
00396 out.resize(rbytes + 1);
00397
00398 int ebytes = RSA_public_encrypt(bytes, (byte_t *) plaintext,
00399 &out[0], m_rsa, s_padding);
00400
00401
00402
00403
00404 if (ebytes < 1) {
00405 WAVE_EX(wex);
00406 wex << "Failed public key encryption";
00407 }
00408
00409 return encodeBase64(&out[0], ebytes);
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 class Key : public RSAKey {
00421 public:
00422 Key(void) throw();
00423 ~Key(void) throw();
00424
00425
00426 void initialize(void);
00427
00428
00429 smart_ptr<RSAPublicKey> getPublicKey(void);
00430 std::string decrypt(IN const char * encrypted);
00431
00432 private:
00433
00434 RSA * m_rsa;
00435 };
00436
00437
00438
00439 Key::Key
00440 (
00441 void
00442 )
00443 throw()
00444 {
00445 m_rsa = NULL;
00446 }
00447
00448
00449
00450 Key::~Key
00451 (
00452 void
00453 )
00454 throw()
00455 {
00456 if (m_rsa) {
00457 RSA_free(m_rsa);
00458 }
00459 }
00460
00461
00462
00463 void
00464 Key::initialize
00465 (
00466 void
00467 )
00468 {
00469 ASSERT(!m_rsa, "already have a key?");
00470 m_rsa = RSA_generate_key(s_keyNumber, s_keyExponent, NULL, NULL);
00471 ASSERT(m_rsa, "failed to generate RSA key");
00472 }
00473
00474
00475
00476 smart_ptr<RSAPublicKey>
00477 Key::getPublicKey
00478 (
00479 void
00480 )
00481 {
00482
00483
00484
00485
00486 RSA * rsa = RSA_new();
00487 ASSERT(rsa, "failed to create empty RSA key");
00488 ASSERT(!rsa->n, "already have n?");
00489 ASSERT(!rsa->e, "already have e?");
00490
00491
00492 rsa->n = BN_dup(m_rsa->n);
00493 rsa->e = BN_dup(m_rsa->e);
00494 ASSERT(rsa->n, "null");
00495 ASSERT(rsa->e, "null");
00496
00497
00498 smart_ptr<PublicKey> pkey = new PublicKey();
00499 ASSERT(pkey, "out of memory");
00500 pkey->initialize(rsa);
00501 return pkey;
00502 }
00503
00504
00505
00506 std::string
00507 Key::decrypt
00508 (
00509 IN const char * encrypted
00510 )
00511 {
00512 perf::Timer timer("crypto::RSAKey::decrypt");
00513 ASSERT(m_rsa, "null");
00514 ASSERT(encrypted, "null");
00515
00516 byte_vec_t data;
00517 decodeBase64(encrypted, data);
00518
00519 int ebytes = data.size();
00520
00521
00522 byte_vec_t out;
00523 out.resize(RSA_size(m_rsa));
00524
00525 int bytes = RSA_private_decrypt(ebytes, &data[0],
00526 &out[0], m_rsa, s_padding);
00527
00528 if (bytes < 1) {
00529 WAVE_EX(wex);
00530 wex << "Failed to decrypt data";
00531 }
00532
00533 return (const char *) &out[0];
00534 }
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544 class SymKey : public DESKey {
00545 public:
00546 SymKey(void) throw();
00547 ~SymKey(void) throw();
00548
00549
00550 void initialize(void);
00551 void initialize(IN const char * serialized);
00552
00553
00554 std::string serialize(void);
00555 std::string encrypt(IN const char * plaintext, IN int minSize);
00556 std::string decrypt(IN const char * encrypted);
00557
00558 private:
00559
00560 DES_cblock m_dcb;
00561 DES_key_schedule m_sched;
00562 };
00563
00564
00565
00566 SymKey::SymKey
00567 (
00568 void
00569 )
00570 throw()
00571 {
00572 }
00573
00574
00575
00576 SymKey::~SymKey
00577 (
00578 void
00579 )
00580 throw()
00581 {
00582 }
00583
00584
00585
00586 void
00587 SymKey::initialize
00588 (
00589 void
00590 )
00591 {
00592
00593
00594 DES_random_key(&m_dcb);
00595
00596
00597 if (DES_set_key_checked(&m_dcb, &m_sched)) {
00598 WAVE_EX(wex);
00599 wex << "Failed to create symmetric key (schedule)";
00600 }
00601
00602
00603 }
00604
00605
00606
00607 void
00608 SymKey::initialize
00609 (
00610 IN const char * serialized
00611 )
00612 {
00613 ASSERT(serialized, "null");
00614
00615 byte_vec_t data;
00616 decodeBase64(serialized, data);
00617 if (s_bytesPerDESBlock != (int) data.size()) {
00618 WAVE_EX(wex);
00619 wex << "Improperly encoded DES key";
00620 }
00621
00622 memcpy(m_dcb, &data[0], s_bytesPerDESBlock);
00623 if (DES_set_key_checked(&m_dcb, &m_sched)) {
00624 WAVE_EX(wex);
00625 wex << "Failed to create symmetric key (schedule)";
00626 }
00627
00628
00629 }
00630
00631
00632
00633 std::string
00634 SymKey::serialize
00635 (
00636 void
00637 )
00638 {
00639 const byte_t * b = (const byte_t *) m_dcb;
00640
00641 return encodeBase64(b, s_bytesPerDESBlock);
00642 }
00643
00644
00645
00646 std::string
00647 SymKey::encrypt
00648 (
00649 IN const char * plaintext,
00650 IN int minSize
00651 )
00652 {
00653 perf::Timer timer("crypto::DESKey::encrypt");
00654 ASSERT(plaintext, "null");
00655 long bytes = strlen(plaintext);
00656 ASSERT(bytes >= 0, "Bad bytes: %ld", bytes);
00657
00658
00659
00660
00661 std::string base;
00662 int nPad = minSize - bytes;
00663 if (minSize > 0 && nPad > 0) {
00664 for (int i = 0; i < nPad; ++i) {
00665 base += 'a' + (rand() % 26);
00666 }
00667 bytes += nPad;
00668 }
00669 base += ':';
00670 bytes += 1;
00671 base += plaintext;
00672
00673
00674
00675
00676
00677 byte_vec_t raw;
00678 long obytes = symmetricEncrypt((const byte_t *) base.c_str(), bytes,
00679 &m_sched, DES_ENCRYPT, raw);
00680
00681
00682
00683 return encodeBase64(&raw[0], obytes);
00684 }
00685
00686
00687
00688 std::string
00689 SymKey::decrypt
00690 (
00691 IN const char * encrypted
00692 )
00693 {
00694 perf::Timer timer("crypto::DESKey::decrypt");
00695 ASSERT(encrypted, "null");
00696
00697
00698
00699
00700 byte_vec_t raw;
00701 decodeBase64(encrypted, raw);
00702
00703 long bytes = raw.size();
00704 ASSERT(bytes > 0, "Bad bytes: %ld", bytes);
00705
00706
00707
00708 byte_vec_t output;
00709 symmetricEncrypt(&raw[0], bytes, &m_sched, DES_DECRYPT,
00710 output);
00711 output.push_back(0);
00712
00713
00714 const char * p = (const char *) &output[0];
00715
00716 while (*p && *p != ':') { ++p; }
00717 if (!*p) {
00718 WAVE_EX(wex);
00719 wex << "Improperly encrypted string?";
00720 }
00721 ++p;
00722
00723
00724
00725 return p;
00726 }
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 smart_ptr<RSAPublicKey>
00737 RSAPublicKey::create
00738 (
00739 IN const char * serialized
00740 )
00741 {
00742 perf::Timer timer("crypto::RSAPublicKey::create");
00743
00744 smart_ptr<PublicKey> local = new PublicKey;
00745 ASSERT(local, "out of memory");
00746
00747 local->initialize(serialized);
00748
00749 return local;
00750 }
00751
00752
00753
00754 smart_ptr<RSAKey>
00755 RSAKey::create
00756 (
00757 void
00758 )
00759 {
00760 perf::Timer timer("crypto::RSAKey::create");
00761
00762 smart_ptr<Key> local = new Key;
00763 ASSERT(local, "out of memory");
00764
00765 local->initialize();
00766
00767 return local;
00768 }
00769
00770
00771
00772 smart_ptr<DESKey>
00773 DESKey::create
00774 (
00775 void
00776 )
00777 {
00778 perf::Timer timer("crypto::DESKey::create");
00779
00780 smart_ptr<SymKey> local = new SymKey;
00781 ASSERT(local, "out of memory");
00782
00783 local->initialize();
00784
00785 return local;
00786 }
00787
00788
00789
00790 smart_ptr<DESKey>
00791 DESKey::create
00792 (
00793 IN const char * serialized
00794 )
00795 {
00796 smart_ptr<SymKey> local = new SymKey;
00797 ASSERT(local, "out of memory");
00798 local->initialize(serialized);
00799 return local;
00800 }
00801
00802
00803
00804 std::string
00805 getSHA1
00806 (
00807 IN const char * data
00808 )
00809 {
00810 perf::Timer timer("crypto::getSHA1");
00811 ASSERT(data, "null");
00812
00813 const int bufSize = SHA_DIGEST_LENGTH;
00814 byte_t buffer[bufSize];
00815 int length = strlen(data);
00816
00817 SHA1((const unsigned char *) data, length, buffer);
00818 return encodeBase64(buffer, SHA_DIGEST_LENGTH, false);
00819 }
00820
00821
00822
00823 std::string
00824 encodeBase64
00825 (
00826 IN const byte_t * data,
00827 IN long bytes,
00828 IN bool encodeLength
00829 )
00830 {
00831 perf::Timer timer("crypto::encodeBase64");
00832 ASSERT(data, "null");
00833 ASSERT(bytes > 0, "bad bytes: %ld", bytes);
00834 if (bytes >= s_maxEncodeLength) {
00835 WAVE_EX(wex);
00836 wex << "Cannot encode " << bytes << " bytes.";
00837 wex << " Max encode length is " << s_maxEncodeLength;
00838 }
00839
00840
00841
00842
00843
00844 std::string out;
00845
00846
00847 if (encodeLength) {
00848
00849 encodeInt32(out, bytes);
00850 }
00851
00852 char buf[4];
00853 buf[3] = 0;
00854 const byte_t * p = data;
00855 while (bytes > 0) {
00856
00857
00858 for (int i = 0; i < 3; ++i, --bytes) {
00859 buf[i] = *p;
00860 if (bytes > 1) {
00861 ++p;
00862 }
00863 }
00864
00865 int32_t * pl = (int32_t *) &buf;
00866 int32_t l = *pl;
00867 ASSERT(l >= 0, "Bad l: %ld", (long) l);
00868
00869 encodeInt32(out, l);
00870 }
00871
00872 return out;
00873 }
00874
00875
00876
00877 void
00878 decodeBase64
00879 (
00880 IN const char * encoded,
00881 OUT byte_vec_t& data
00882 )
00883 {
00884 perf::Timer timer("crypto::decodeBase64");
00885 data.clear();
00886
00887 int N = strlen(encoded);
00888 if (N % 4) {
00889 WAVE_EX(wex);
00890 wex << "Improperly encoded data (bad length)";
00891 }
00892
00893 static bool s_init = false;
00894 if (!s_init) {
00895 initializeDecoding();
00896 s_init = true;
00897 }
00898
00899 const char * p = encoded;
00900 int32_t bytes = decodeInt32(p);
00901
00902 p += 4;
00903
00904
00905 for (; N > 0; N -= 4) {
00906
00907 int32_t l = decodeInt32(p);
00908 p += 4;
00909 byte_t * pb = (byte_t *) &l;
00910 for (int i = 0; i < 3; ++i ) {
00911 if (bytes > 0) {
00912 data.push_back(pb[i]);
00913 bytes--;
00914 }
00915 }
00916 }
00917
00918 }
00919
00920
00921
00922 };
00923