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