按照<<密码学导引>>上描述的OTP算法, 实现了一个OTP算法加解密工具~
src : srcOtpCipher_V2013_0111_0517.rar, 这版的明文只能是 'a'~'z', 以后会改成支持所有可见的Asiic字符.
src: srcOtpCihper_V2013_0111_2317.rar, 变形OTP算法, 支持可见Ascii字符集.
编译环境: win7X64Sp1 + vs2008Sp1
<2013_0111_2251>
将Cipher\Otp\OtpCipherConst.h 中的常量改了, 支持了可见Ascii字符集, 已经可以作为一个玩具使用.
从需求的变化到程序修改的实际效果中可以体会到宏的好处~
-
/// @file OtpCipherConst.h
-
/// @brief OtpCihper常量定义
-
#ifndef __OTP_CIPHER_CONST_H__
-
#define __OTP_CIPHER_CONST_H__
-
/// @ref http://www.dreamdu.com/xhtml/ascii/
-
/// 32 ~ 126 是可以打印的字符
-
#define OTP_FIRST_CHAR_W L' ' ///< 字符集中第一个字符
-
#define OTP_LAST_CHAR_W L'~' ///< 字符集中最后一个字符
-
#define OTP_FIRST_CHAR ' ' ///< 字符集中第一个字符
-
#define OTP_LAST_CHAR '~' ///< 字符集中最后一个字符
-
#define OTP_MOD (OTP_LAST_CHAR - OTP_FIRST_CHAR + 1)
-
#define OTP_FIRST_INDEX 1
-
#define OTP_LAST_INDEX OTP_MOD
-
#define SZ_FILE_NAME_PLAINTEXT L"OtpPlaintext.txt"
-
#define SZ_FILE_NAME_OTP_KEY L"OtpKey.txt"
-
#define SZ_FILE_NAME_CIPHERTEXT L"OtpCiphertext.txt"
-
/// 算法说明
-
#define SZ_ALG_README L"算法说明\r\n"\
-
L"OTP算法是一次一密的算法\r\n"\
-
L"变形的算法支持可见Ascii字符集\r\n"\
-
L"明文是' '~'~'的小写字母, 数组为x, 长度为N\r\n"\
-
L"密钥是' '~'~'的小写字母, 数组为k, 长度为N\r\n"\
-
L"OTP变形加密算法:\r\n"\
-
L"模M = '~' - ' '\r\n"\
-
L"EK(x) = ((x1 + k1)%M,(x2 + k2)%M,...(xn + kn)%M)\r\n"\
-
L"OTP解密算法:\r\n"\
-
L"DK(x) = ((x1 - k1)%M,(x2 - k2)%M,...(xn - kn)%M)\r\n"\
-
L"\r\n"\
-
L"变形后的OTP算法有效字符集为可见Ascii字符, 从' '~'~'\r\n"
-
#endif // #ifndef __OTP_CIPHER_CONST_H__
效果图
新的算法说明
<2013_0110>
算法说明:
OTP加密:
OTP解密:
从使用角度, 考虑了以下几点:
* 加密前的明文输入方式: 手工输入明文, 载入明文文件.
* 加密时的OTP密码自动生成.
* 加密后的文件保存(保存明文,密钥,密文).
* 解密前的密文输入方式: 手工输入密文, 载入密文文件.
* 解密前的密钥输入方式: 载入密钥文件.
* 解密后的文件保存(保存明文)
* 考虑到解密时,一般是直接使用密文和密钥文件, 而不会手工输入, 特别是密文较长时的情况.
/// @todo 原版OTP的明文内容只能是小写字母(a~z), 这不实用, 稍后要改成支持全部ascii字符,
/// 这样, 英文较好的使用者,就可以将这个工具作为一个实用工具.
直接按照书里描述的OTP算法, 解密不准确. 要处理一些细节.
e.g. 明文是'a', 密钥是'z', 加密和解密都要处理. 直接按照公式来行不通~
Otp加解密接口的实现如下:
-
/// @file OtpCipherConst.h
-
/// @brief OtpCihper常量定义
-
#ifndef __OTP_CIPHER_CONST_H__
-
#define __OTP_CIPHER_CONST_H__
-
#define OTP_FIRST_CHAR_W L'a' ///< 字符集中第一个字符
-
#define OTP_LAST_CHAR_W L'z' ///< 字符集中最后一个字符
-
#define OTP_FIRST_CHAR 'a' ///< 字符集中第一个字符
-
#define OTP_LAST_CHAR 'z' ///< 字符集中最后一个字符
-
#define OTP_MOD (OTP_LAST_CHAR - OTP_FIRST_CHAR + 1)
-
#define OTP_FIRST_INDEX 1
-
#define OTP_LAST_INDEX OTP_MOD
-
#define SZ_FILE_NAME_PLAINTEXT L"OtpPlaintext.txt"
-
#define SZ_FILE_NAME_OTP_KEY L"OtpKey.txt"
-
#define SZ_FILE_NAME_CIPHERTEXT L"OtpCiphertext.txt"
-
/// 算法说明
-
#define SZ_ALG_README L"算法说明\r\n"\
-
L"OTP算法是一次一密的算法\r\n"\
-
L"明文是a~z的小写字母, 数组为x, 长度为N\r\n"\
-
L"密钥是a~z的小写字母, 数组为k, 长度为N\r\n"\
-
L"OTP加密算法:\r\n"\
-
L"EK(x) = ((x1 + k1)%26,(x2 + k2)%26,...(xn + kn)%26)\r\n"\
-
L"OTP解密算法:\r\n"\
-
L"DK(x) = ((x1 - k1)%26,(x2 - k2)%26,...(xn - kn)%26)\r\n"
-
#endif // #ifndef __OTP_CIPHER_CONST_H__
-
/// @file OtpCipher.h
-
/// @brief OtpCihper函数定义
-
#ifndef __OTP_CIPHER_H__
-
#define __OTP_CIPHER_H__
-
#include "OtpCipherConst.h"
-
#include <tchar.h>
-
#include <string>
-
/// @fn isValidPlaintext
-
/// @brief 判断明文内容是否有效
-
/// @param IN const wchar_t * pcPlaintextW, 明文
-
/// @return boolen
-
/// @retval true, 明文有效
-
/// @retval false, 明文无效, 有非法字符
-
bool isValidPlaintext(IN const wchar_t * pcPlaintextW);
-
/// @fn isValidChar
-
/// @brief 给定的字符是否是有效的明文内容
-
/// @param IN char cIn, 给定的字符
-
/// @return boolen
-
/// @retval true, 入参字符有效
-
/// @retval false, 入参字符无效, 不是有效明文字符集中的字符
-
bool isValidChar(IN char cIn);
-
char char2Index(char cParam);
-
char Index2Char(char cParam);
-
char OtpModX(int iParam, char cMod);
-
/// @fn GenerateOtpKey
-
/// @brief 产生Otp密钥
-
/// @param IN const wchar_t * pcPlaintextW, 明文
-
/// @param OUT std::wstring & strOtpKeyW, 根据明文长度生成的等长度密钥
-
/// @return boolen
-
/// @retval true, 密钥产生成功
-
/// @retval false, 密钥产生失败
-
bool GenerateOtpKey(IN const wchar_t * pcPlaintextW, OUT std::wstring & strOtpKeyW);
-
/// @fn OtpCipher
-
/// @brief Otp加解密
-
/// @param IN bool bEncrypt, 是加密还是解密, true = 加密, false = 解密
-
/// @param IN OUT std::string & strPlaintext, 明文
-
/// @param IN const char * pcOtpKey, 密钥
-
/// @param IN OUT std::string & strCiphertext, 密文
-
bool OtpCipher(IN bool bEncrypt,
-
IN OUT std::string & strPlaintext,
-
IN const char * pcOtpKey,
-
IN OUT std::string & strCiphertext);
-
#endif // #ifndef __OTP_CIPHER_H__
-
/// @file OtpCipher.cpp
-
/// @brief OtpCihper函数实现
-
#include "stdafx.h"
-
#include "OtpCipher.h"
-
#include "Helper/string/stringHelper.h"
-
bool isValidPlaintext(IN const wchar_t * pcPlaintextW)
-
{
-
std::string strPlaintextA;
-
std::string::iterator it;
-
if(NULL == pcPlaintextW)
-
return false;
-
Wstring2String(strPlaintextA, pcPlaintextW);
-
for(it = strPlaintextA.begin(); it != strPlaintextA.end(); it++)
-
{
-
if(!isValidChar(*it))
-
return false;
-
}
-
return true;
-
}
-
bool isValidChar(IN char cIn)
-
{
-
return (cIn >= OTP_FIRST_CHAR) && (cIn <= OTP_LAST_CHAR);
-
}
-
bool GenerateOtpKey(IN const wchar_t * pcPlaintextW, OUT std::wstring & strOtpKeyW)
-
{
-
bool bPassFirstRand = true;
-
size_t nLen = 0;
-
wchar_t cRandW = '\0';
-
std::string strPlaintextA;
-
strOtpKeyW = L"";
-
if (NULL == pcPlaintextW)
-
return false;
-
srand(static_cast<UINT>(time(NULL)));
-
Wstring2String(strPlaintextA, pcPlaintextW);
-
nLen = strPlaintextA.length();
-
while (0 != nLen--)
-
{
-
cRandW = OTP_FIRST_CHAR_W - 1 + RangedRand(OTP_FIRST_INDEX, OTP_LAST_INDEX, bPassFirstRand);
-
bPassFirstRand = false;
-
strOtpKeyW += cRandW;
-
}
-
return true;
-
}
-
char char2Index(char cParam)
-
{
-
return cParam - OTP_FIRST_CHAR + 1;
-
}
-
char Index2Char(char cParam)
-
{
-
/// 字符集中最后一个字符的索引是0
-
return (cParam >= 1) ? (cParam - 1 + OTP_FIRST_CHAR) : OTP_LAST_CHAR;
-
}
-
char OtpModX(int iParam, char cMod)
-
{
-
if (iParam < 0)
-
iParam += cMod; ///< 防止 iParam < 0, e.g. ('a' - 'z') % 26
-
return static_cast<char>(iParam % cMod);
-
}
-
bool OtpCipher(IN bool bEncrypt,
-
IN OUT std::string & strPlaintext,
-
IN const char * pcOtpKey,
-
IN OUT std::string & strCiphertext)
-
{
-
char cTmp = '\0';
-
char cX = '\0';
-
char cK = '\0';
-
size_t nIndex = 0;
-
std::string::iterator it;
-
if ((NULL == pcOtpKey)
-
|| (bEncrypt && (strlen(strPlaintext.c_str()) != strlen(pcOtpKey)))
-
|| (!bEncrypt && (strlen(strCiphertext.c_str()) != strlen(pcOtpKey))))
-
{
-
return false;
-
}
-
if (bEncrypt)
-
{
-
/// OTP加密算法:
-
/// EK(x) = ((x1 + k1)%26,(x2 + k2)%26,...(xn + kn)%26)
-
strCiphertext = "";
-
for (it = strPlaintext.begin(); it != strPlaintext.end(); it++)
-
{
-
cX = char2Index(*it);
-
cK = char2Index(*(pcOtpKey + nIndex++));
-
cTmp = OtpModX(cX + cK, OTP_MOD);
-
strCiphertext += Index2Char(cTmp);
-
}
-
}
-
else
-
{
-
/// OTP解密算法:
-
/// DK(x) = ((x1 - k1)%26,(x2 - k2)%26,...(xn - kn)%26)
-
strPlaintext = "";
-
for (it = strCiphertext.begin(); it != strCiphertext.end(); it++)
-
{
-
cX = char2Index(*it);
-
cK = char2Index(*(pcOtpKey + nIndex++));
-
cTmp = OtpModX(cX - cK, OTP_MOD);
-
strPlaintext += Index2Char(cTmp);
-
}
-
}
-
return true;
-
}
<2013_0112_1033>
OTP加密的好处: 多表替换.
多表替换: 在整个消息中, 同一个字符通常不会被加密成同一个字符.