📄 algorithm.cpp
字号:
/************************************************************************* * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * *************************************************************************/#include "algorithm.h"/** * Encode str with the given codec. * * @param str The string that should be encoded. * @param codec The codec that should be used. * @returns The encoded string. */string Algorithm::encode (const string &str, CODEC codec){ string enc_str = ""; switch (codec) { case BASE64: Algorithm::enc_base64 (str, &enc_str); break; case BASE64_NIL: Algorithm::enc_base64_nil (str, &enc_str); break; } return (enc_str);}/** * Decode str with the given codec. * * @param str The string that should be decoded. * @param codec The codec that should be used. * @returns The encoded string. * * @throws DecodeException * If the BASE64 data was invalid. */string Algorithm::decode (const string &str, CODEC codec){ string dec_str = ""; int ret = 0; switch (codec) { case BASE64: ret = Algorithm::dec_base64 (str, &dec_str); if (ret == -1) { string msg = LIBSMTP_I18N_1 ("Invalid Base64 Data."); throw (DecodeException (msg, "Algorithm::decode()", 1)); } break; case BASE64_NIL: ret = Algorithm::dec_base64_nil (str, &dec_str); if (ret == -1) { string msg = LIBSMTP_I18N_1 ("Invalid Base64 Data."); throw (DecodeException (msg, "Algorithm::decode()", 2)); } break; } return (dec_str);}/** * Calculates the keyed md5sum. (rfc2104) * * @param text The text that should be checksummed. * @param key The key that should be used. * @param digest The checksum that is calculated out of key * and text will be stored at digest. digest * needs to be at least 16 Bytes big. */void Algorithm::hmac_md5 (const string &str, const string &key, unsigned char * digest){ unsigned int md_len; digest = HMAC ( EVP_md5 (), (unsigned char*)key.c_str (), key.length (), (unsigned char*)str.c_str (), str.length (), digest, &md_len );}/** * Calculates the keyed sha1sum. (rfc2104) * * @param text The text that should be checksummed. * @param key The key that should be used. * @param digest The checksum that is calculated out of key * and text will be stored at digest. digest * needs to be at least 20 Bytes big. */void Algorithm::hmac_sha1 (const string &str, const string &key, unsigned char * digest){ unsigned int md_len; digest = HMAC ( EVP_sha1 (), (unsigned char*)key.c_str (), key.length (), (unsigned char*)str.c_str (), str.length (), digest, &md_len );}/** * Calculates the keyed sha1sum and returns the digest as a * string. (rfc2104) * Just for your convenience. * * @param str The text that should be checksummed. * @param key The key that should be used. * @returns A string representation of the checksum * that was calculated using str and key. */string Algorithm::hmac_sha1_str (const string &str, const string &key){ unsigned char digest[20]; Algorithm::hmac_sha1 (str, key, (unsigned char*)digest); char str_digest[41]; unsigned int i; for (i = 0; i < 20; i++) { sprintf (str_digest+(i*2),"%02x", digest[i]); } str_digest[40] = '\0'; return (str_digest);}/** * Calculates the keyed md5sum and returns the digest as a * string. (rfc2104) * Just for your convenience. * * @param str The text that should be checksummed. * @param key The key that should be used. * @returns A string representation of the checksum * that was calculated using str and key. */string Algorithm::hmac_md5_str (const string &str, const string &key){ unsigned char digest[16]; Algorithm::hmac_md5 (str, key, (unsigned char *)digest); char str_digest[33]; unsigned int i; for (i = 0; i < 16; i++) { sprintf (str_digest+(i*2),"%02x", digest[i]); } str_digest[32] = '\0'; return (str_digest);}/** * Encode orig_str with the base64 codec and store * the result in the string pointed by enc_str. * * @param orig_str The string that should be encoded. * @param enc_str The resulting encoded string will be stored * at the address pointed to by enc_str. */void Algorithm::enc_base64 (const string &orig_str, string * enc_str){ unsigned int remain = orig_str.length () % 3; unsigned int idx = 0; while (idx < (orig_str.length ()-remain)) { int concat = ((unsigned char)orig_str[idx+0] << 16) | ((unsigned char)orig_str[idx+1] << 8) | ((unsigned char)orig_str[idx+2] << 0); (*enc_str) += tbl_base64[(concat >> 18) & 0x3F]; (*enc_str) += tbl_base64[(concat >> 12) & 0x3F]; (*enc_str) += tbl_base64[(concat >> 6) & 0x3F]; (*enc_str) += tbl_base64[(concat >> 0) & 0x3F]; idx += 3; } if (remain == 2) { int concat = (orig_str[idx+0] << 16) | (orig_str[idx+1] << 8); (*enc_str) += Algorithm::tbl_base64[(concat >> 18) & 0x3F]; (*enc_str) += Algorithm::tbl_base64[(concat >> 12) & 0x3F]; (*enc_str) += Algorithm::tbl_base64[(concat >> 6) & 0x3F]; (*enc_str) += '='; } else if (remain == 1) { int concat = (orig_str[idx+0] << 16); (*enc_str) += Algorithm::tbl_base64[(concat >> 18) & 0x3F]; (*enc_str) += Algorithm::tbl_base64[(concat >> 12) & 0x3F]; (*enc_str) += '='; (*enc_str) += '='; }}/** * Decode enc_str with the base64 codec and store * the result in the string pointed by orig_str. * If successfull 0 is returned, and -1 if the * base64 data was invalid. * * @param enc_str The string that should be decoded. * @param orig_str The resulting decoded string will be stored * at the address pointed to by orig_str. * @returns 0 if the decoding process was successfull and -1 if * the base64 data was invalid. */int Algorithm::dec_base64 (const string &enc_str, string * orig_str){ if (enc_str.length () % 4) { return (-1); } unsigned int idx = 0; while (idx < enc_str.length ()) { char b[] = { -1, -1, -1 , -1 }; for (int i = 0; i < 4; i++) { for (int z = 0; z < 64; z++) { if (Algorithm::tbl_base64[z] == enc_str[idx+i]) { b[i] = z; break; } else if (enc_str[idx+i] == '=') { if (enc_str.length () == (idx+i+2)) { b[2] = 0x7F; b[3] = 0x7F; break; } if (enc_str.length () == (idx+i+1)) { b[3] = 0x7F; break; } else { return (-1); } } } if (b[i] == -1) { return (-1); } } int concat = (b[0] << 18) | (b[1] << 12) | (b[2] << 6) | (b[3] << 0); if (b[2] == 0x7F) { (*orig_str) += (char)((concat >> 16) & 0xFF); } else if (b[3] == 0x7F) { (*orig_str) += (char)((concat >> 16) & 0xFF); (*orig_str) += (char)((concat >> 8) & 0xFF); } else { (*orig_str) += (char)((concat >> 16) & 0xFF); (*orig_str) += (char)((concat >> 8) & 0xFF); (*orig_str) += (char)((concat >> 0) & 0xFF); } idx += 4; } return (0);}/** * Encode enc_str with a slightly advanced base64 codec * and store the result in the string pointed by orig_str. * The sequence "<NIL>" will be substituted with one zero byte. * * @param orig_str The string that should be encoded. * @param enc_str The resulting encoded string will be stored * at the address pointed to by enc_str. */void Algorithm::enc_base64_nil (string orig_str, string * enc_str){ vector<unsigned int> nil_chars; unsigned int pos; while ((pos = orig_str.find ("<NIL>")) != string::npos) { orig_str.replace (pos, 5, "."); nil_chars.push_back (pos); } int remain = orig_str.length () % 3; unsigned int idx = 0; while (idx < (orig_str.length ()-remain)) { int concat = 0; if (find (nil_chars.begin (), nil_chars.end (), idx) != nil_chars.end ()) { concat = 0 << 16; } else { concat = ((unsigned char)orig_str[idx+0] << 16); } if (find (nil_chars.begin (), nil_chars.end (), idx+1) != nil_chars.end ()) { concat |= 0 << 8; } else { concat |= ((unsigned char)orig_str[idx+1] << 8); } if (find (nil_chars.begin (), nil_chars.end (), idx+2) != nil_chars.end ()) { concat |= 0 << 0; } else { concat |= ((unsigned char)orig_str[idx+2] << 0); } (*enc_str) += Algorithm::tbl_base64[(concat >> 18) & 0x3F]; (*enc_str) += Algorithm::tbl_base64[(concat >> 12) & 0x3F]; (*enc_str) += Algorithm::tbl_base64[(concat >> 6) & 0x3F]; (*enc_str) += Algorithm::tbl_base64[(concat >> 0) & 0x3F]; idx += 3; } if (remain == 2) { int concat = 0; if (find (nil_chars.begin (), nil_chars.end (), idx) != nil_chars.end ()) { concat = 0 << 16; } else { concat = ((unsigned char)orig_str[idx+0] << 16); } if (find (nil_chars.begin (), nil_chars.end (), idx+1) != nil_chars.end ()) { concat |= 0 << 8; } else { concat |= ((unsigned char)orig_str[idx+1] << 8); } (*enc_str) += Algorithm::tbl_base64[(concat >> 18) & 0x3F]; (*enc_str) += Algorithm::tbl_base64[(concat >> 12) & 0x3F]; (*enc_str) += Algorithm::tbl_base64[(concat >> 6) & 0x3F]; (*enc_str) += '='; } else if (remain == 1) { int concat = 0; if (find (nil_chars.begin (), nil_chars.end (), idx) != nil_chars.end ()) { concat = 0 << 16; } else { concat = ((unsigned char)orig_str[idx+0] << 16); } (*enc_str) += Algorithm::tbl_base64[(concat >> 18) & 0x3F]; (*enc_str) += Algorithm::tbl_base64[(concat >> 12) & 0x3F]; (*enc_str) += '='; (*enc_str) += '='; }}/** * Decode enc_str with a slightly advanced base64 * codec and store the result in the string pointed * by orig_str. * Each zero byte will be substituted with the * sequence "<NIL>". * If successfull 0 is returned, and -1 if the * base64 data was invalid. * * @param enc_str The string that should be decoded. * @param orig_str The resulting decoded string will be stored * at the address pointed to by orig_str. * @returns 0 if the decodeing process was successfull and -1 if * the base64 data was invalid. */int Algorithm::dec_base64_nil (const string &enc_str, string * orig_str){ if (enc_str.length () % 4) { return (-1); } unsigned int idx = 0; while (idx < enc_str.length ()) { char b[] = { -1, -1, -1 , -1 }; for (int i = 0; i < 4; i++) { for (int z = 0; z < 64; z++) { if (Algorithm::tbl_base64[z] == enc_str[idx+i]) { b[i] = z; break; } else if (enc_str[idx+i] == '=') { if (enc_str.length () == (idx+i+2)) { b[2] = 0x7F; b[3] = 0x7F; break; } if (enc_str.length () == (idx+i+1)) { b[3] = 0x7F; break; } else { return (-1); } } } if (b[i] == -1) { return (-1); } } int concat = (b[0] << 18) | (b[1] << 12) | (b[2] << 6) | (b[3] << 0); if (b[2] == 0x7F) { char c = (char)((concat >> 16) & 0xFF); if (c == '\0') { (*orig_str) += "<NIL>"; } else { (*orig_str) += c; } } else if (b[3] == 0x7F) { char c = (char)((concat >> 16) & 0xFF); if (c == '\0') { (*orig_str) += "<NIL>"; } else { (*orig_str) += c; } c = (char)((concat >> 8) & 0xFF); if (c == '\0') { (*orig_str) += "<NIL>"; } else { (*orig_str) += c; } } else { char c = (char)((concat >> 16) & 0xFF); if (c == '\0') { (*orig_str) += "<NIL>"; } else { (*orig_str) += c; } c = (char)((concat >> 8) & 0xFF); if (c == '\0') { (*orig_str) += "<NIL>"; } else { (*orig_str) += c; } c = (char)((concat >> 0) & 0xFF); if (c == '\0') { (*orig_str) += "<NIL>"; } else { (*orig_str) += c; } } idx += 4; } return (0);}/** * the base64 character table */char Algorithm::tbl_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -