注意:本篇代码已经发现存在严重问题!给您带来麻烦真的不好意思。您可以看C/C++对字串简单进行可逆加密(2)
加密字串当然是为了安全,废话不多说,直接进入!
要想进行可逆加密,目前我只知道用或者,或对字符进行移位。
新建一个控制台工程。
简单用密钥对明文进行异或运算。异或运算不改变字串的长度。
#include <iostream.h> #include <windows.h> #include <tchar.h> void EncodeString(LPTSTR lpszText, LPCTSTR lpszKey) { int nTextLen = ::_tcslen(lpszText); int nKeyLen = ::_tcslen(lpszKey); int i = 0; int k = 0; for(; i < nTextLen; i++) { lpszText[i] = lpszText[i] ^ lpszKey[k]; k++; if(k >= nKeyLen) k = 0; } } int main(int argc, char* argv[]) { char strText[] = "Hello world!"; cout<<strText<<endl; cout<<"========================================"<<endl; EncodeString(strText, "Zimmerk"); // 加密 cout<<strText<<endl; cout<<"========================================"<<endl; EncodeString(strText, "Zimmerk"); // 解密 cout<<strText<<endl; return 0; }
运行发现加密,解密都正常。
但测试中发现,随着明文的增加,会出现解密不完整的情况,比如加密“Hello world! I'm zimmerk. I'm a boy. What's your name?”,这是因为加密得到的密文中含有特殊字符,导致_tcslen函数提前中止,获取字串长度不正确。这种上情况的解决方法可以是自己计算字串结尾。但如果字串中间出现\0,那就用不了了。
还有一种方法就是自己添加字串的中止标记。
这样无法确定字串长度,只好自己在函数内申请内存(当然你也可以用string)
我们设定在密文末尾加密自定的终止标记“==\0”
所以有以下代码
int nTextLen = 0; char *cPos = NULL; char *pDest = NULL; if(!lpszReturn) // 加密 { nTextLen = ::_tcslen(lpszText); pDest = (LPTSTR)lpszText; } else // 解密 { cPos = ::_tcsstr(lpszText, _T("==\0")); // 查找自定的中止标记 if(!cPos) // 没有找到结束标记,也不是加密 return; nTextLen = cPos - lpszText; pDest = new char[nTextLen + 3]; // ==\0 }
但测试发现,随着字串长度的增加,::_tcsstr同样会无法正确获取到我们自定的终止标记,那只好自己搜索了。
#include <iostream.h> #include <windows.h> #include <tchar.h> void EncodeString(LPCTSTR lpszText, LPTSTR *lpszReturn, LPCTSTR lpszKey) { int nTextLen = 0; char *cPos = NULL; char *pDest = NULL; if(!lpszReturn) // 加密 { nTextLen = ::_tcslen(lpszText); pDest = (LPTSTR)lpszText; } else // 解密 { // 查找自定的中止标记 cPos = (LPTSTR)lpszText; while(true) // 从这里可以看到,除非搜索到我们自定的中止标记,否则会一直搜索下去 { if(*cPos == '=') if(cPos[1] == '=') if(cPos[2] == '\0') break; cPos++; } if(!cPos) // 没有找到结束标记,也不是加密 return; nTextLen = cPos - lpszText; pDest = new char[nTextLen + 3]; // ==\0 } int nKeyLen = ::_tcslen(lpszKey); int i = 0; int k = 0; for(; i < nTextLen; i++) { pDest[i] = lpszText[i] ^ lpszKey[k]; k++; if(k >= nKeyLen) k = 0; } if(!cPos) memcpy(pDest + nTextLen, _T("==\0"), 3 * sizeof(TCHAR)); else { memset(pDest + nTextLen, _T('\0'), sizeof(TCHAR)); *lpszReturn = pDest; } } int main(int argc, char* argv[]) { char strText[] = "Hello world! I'm zimmerk. I'm a boy. What's your name?"; char *lpszDest = NULL; cout<<strText<<endl; cout<<"========================================"<<endl; EncodeString(strText , NULL, "Zimmerk"); // 加密 cout<<strText<<endl; cout<<"========================================"<<endl; EncodeString(strText, &lpszDest, "Zimmerk"); // 解密 if(*lpszDest) { cout<<lpszDest<<endl; delete [] lpszDest; } else cout<<_T("(NULL)")<<endl; return 0; }
在测试中发现,再长的字串也能正常解密。
但还发现一个问题,如果知道密钥的一部分,密文就能解出一部分来,这样试下去,密钥不难被试出来。如果才能增大试出密钥的难度能,现在已经晚了,等下一篇文章吧。呵呵.
以上代码在Windows 2003 Server + VC6.0下编译通过
原文链接: https://www.cnblogs.com/zimmerk/archive/2011/08/28/2156547.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/31302
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!