算法实现: OTP(One-Time Pad) 一次一密密码本 加解密

按照<<密码学导引>>上描述的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字符集, 已经可以作为一个玩具使用.

从需求的变化到程序修改的实际效果中可以体会到宏的好处~

 
  1. /// @file OtpCipherConst.h

  2. /// @brief OtpCihper常量定义

  3.  
  4. #ifndef __OTP_CIPHER_CONST_H__

  5. #define __OTP_CIPHER_CONST_H__

  6.  
  7. /// @ref http://www.dreamdu.com/xhtml/ascii/

  8. /// 32 ~ 126 是可以打印的字符

  9. #define OTP_FIRST_CHAR_W L' ' ///< 字符集中第一个字符

  10. #define OTP_LAST_CHAR_W L'~' ///< 字符集中最后一个字符

  11.  
  12. #define OTP_FIRST_CHAR ' ' ///< 字符集中第一个字符

  13. #define OTP_LAST_CHAR '~' ///< 字符集中最后一个字符

  14. #define OTP_MOD (OTP_LAST_CHAR - OTP_FIRST_CHAR + 1)

  15. #define OTP_FIRST_INDEX 1

  16. #define OTP_LAST_INDEX OTP_MOD

  17.  
  18. #define SZ_FILE_NAME_PLAINTEXT L"OtpPlaintext.txt"

  19. #define SZ_FILE_NAME_OTP_KEY L"OtpKey.txt"

  20. #define SZ_FILE_NAME_CIPHERTEXT L"OtpCiphertext.txt"

  21.  
  22. /// 算法说明

  23. #define SZ_ALG_README L"算法说明\r\n"\

  24. L"OTP算法是一次一密的算法\r\n"\

  25. L"变形的算法支持可见Ascii字符集\r\n"\

  26. L"明文是' '~'~'的小写字母, 数组为x, 长度为N\r\n"\

  27. L"密钥是' '~'~'的小写字母, 数组为k, 长度为N\r\n"\

  28. L"OTP变形加密算法:\r\n"\

  29. L"模M = '~' - ' '\r\n"\

  30. L"EK(x) = ((x1 + k1)%M,(x2 + k2)%M,...(xn + kn)%M)\r\n"\

  31. L"OTP解密算法:\r\n"\

  32. L"DK(x) = ((x1 - k1)%M,(x2 - k2)%M,...(xn - kn)%M)\r\n"\

  33. L"\r\n"\

  34. L"变形后的OTP算法有效字符集为可见Ascii字符, 从' '~'~'\r\n"

  35.  
  36. #endif // #ifndef __OTP_CIPHER_CONST_H__

  37.  


 

效果图

新的算法说明

<2013_0110>

算法说明:

OTP加密:

OTP解密:

从使用角度, 考虑了以下几点:

* 加密前的明文输入方式: 手工输入明文, 载入明文文件.

* 加密时的OTP密码自动生成.

* 加密后的文件保存(保存明文,密钥,密文).

* 解密前的密文输入方式: 手工输入密文, 载入密文文件.

* 解密前的密钥输入方式: 载入密钥文件.

* 解密后的文件保存(保存明文)

* 考虑到解密时,一般是直接使用密文和密钥文件, 而不会手工输入, 特别是密文较长时的情况.

/// @todo 原版OTP的明文内容只能是小写字母(a~z), 这不实用, 稍后要改成支持全部ascii字符, 

/// 这样, 英文较好的使用者,就可以将这个工具作为一个实用工具.

直接按照书里描述的OTP算法, 解密不准确. 要处理一些细节.

e.g.  明文是'a', 密钥是'z', 加密和解密都要处理. 直接按照公式来行不通~

Otp加解密接口的实现如下:

 
  1. /// @file OtpCipherConst.h

  2. /// @brief OtpCihper常量定义

  3.  
  4. #ifndef __OTP_CIPHER_CONST_H__

  5. #define __OTP_CIPHER_CONST_H__

  6.  
  7. #define OTP_FIRST_CHAR_W L'a' ///< 字符集中第一个字符

  8. #define OTP_LAST_CHAR_W L'z' ///< 字符集中最后一个字符

  9.  
  10. #define OTP_FIRST_CHAR 'a' ///< 字符集中第一个字符

  11. #define OTP_LAST_CHAR 'z' ///< 字符集中最后一个字符

  12. #define OTP_MOD (OTP_LAST_CHAR - OTP_FIRST_CHAR + 1)

  13. #define OTP_FIRST_INDEX 1

  14. #define OTP_LAST_INDEX OTP_MOD

  15.  
  16. #define SZ_FILE_NAME_PLAINTEXT L"OtpPlaintext.txt"

  17. #define SZ_FILE_NAME_OTP_KEY L"OtpKey.txt"

  18. #define SZ_FILE_NAME_CIPHERTEXT L"OtpCiphertext.txt"

  19.  
  20. /// 算法说明

  21. #define SZ_ALG_README L"算法说明\r\n"\

  22. L"OTP算法是一次一密的算法\r\n"\

  23. L"明文是a~z的小写字母, 数组为x, 长度为N\r\n"\

  24. L"密钥是a~z的小写字母, 数组为k, 长度为N\r\n"\

  25. L"OTP加密算法:\r\n"\

  26. L"EK(x) = ((x1 + k1)%26,(x2 + k2)%26,...(xn + kn)%26)\r\n"\

  27. L"OTP解密算法:\r\n"\

  28. L"DK(x) = ((x1 - k1)%26,(x2 - k2)%26,...(xn - kn)%26)\r\n"

  29.  
  30. #endif // #ifndef __OTP_CIPHER_CONST_H__

  31.  
 
  1. /// @file OtpCipher.h

  2. /// @brief OtpCihper函数定义

  3.  
  4. #ifndef __OTP_CIPHER_H__

  5. #define __OTP_CIPHER_H__

  6.  
  7. #include "OtpCipherConst.h"

  8. #include <tchar.h>

  9. #include <string>

  10.  
  11. /// @fn isValidPlaintext

  12. /// @brief 判断明文内容是否有效

  13. /// @param IN const wchar_t * pcPlaintextW, 明文

  14. /// @return boolen

  15. /// @retval true, 明文有效

  16. /// @retval false, 明文无效, 有非法字符

  17. bool isValidPlaintext(IN const wchar_t * pcPlaintextW);

  18.  
  19. /// @fn isValidChar

  20. /// @brief 给定的字符是否是有效的明文内容

  21. /// @param IN char cIn, 给定的字符

  22. /// @return boolen

  23. /// @retval true, 入参字符有效

  24. /// @retval false, 入参字符无效, 不是有效明文字符集中的字符

  25. bool isValidChar(IN char cIn);

  26.  
  27. char char2Index(char cParam);

  28. char Index2Char(char cParam);

  29. char OtpModX(int iParam, char cMod);

  30.  
  31. /// @fn GenerateOtpKey

  32. /// @brief 产生Otp密钥

  33. /// @param IN const wchar_t * pcPlaintextW, 明文

  34. /// @param OUT std::wstring & strOtpKeyW, 根据明文长度生成的等长度密钥

  35. /// @return boolen

  36. /// @retval true, 密钥产生成功

  37. /// @retval false, 密钥产生失败

  38. bool GenerateOtpKey(IN const wchar_t * pcPlaintextW, OUT std::wstring & strOtpKeyW);

  39.  
  40. /// @fn OtpCipher

  41. /// @brief Otp加解密

  42. /// @param IN bool bEncrypt, 是加密还是解密, true = 加密, false = 解密

  43. /// @param IN OUT std::string & strPlaintext, 明文

  44. /// @param IN const char * pcOtpKey, 密钥

  45. /// @param IN OUT std::string & strCiphertext, 密文

  46. bool OtpCipher(IN bool bEncrypt,

  47. IN OUT std::string & strPlaintext,

  48. IN const char * pcOtpKey,

  49. IN OUT std::string & strCiphertext);

  50.  
  51. #endif // #ifndef __OTP_CIPHER_H__

  52.  
 
  1. /// @file OtpCipher.cpp

  2. /// @brief OtpCihper函数实现

  3.  
  4. #include "stdafx.h"

  5. #include "OtpCipher.h"

  6. #include "Helper/string/stringHelper.h"

  7.  
  8. bool isValidPlaintext(IN const wchar_t * pcPlaintextW)

  9. {

  10. std::string strPlaintextA;

  11. std::string::iterator it;

  12.  
  13. if(NULL == pcPlaintextW)

  14. return false;

  15.  
  16. Wstring2String(strPlaintextA, pcPlaintextW);

  17. for(it = strPlaintextA.begin(); it != strPlaintextA.end(); it++)

  18. {

  19. if(!isValidChar(*it))

  20. return false;

  21. }

  22.  
  23. return true;

  24. }

  25.  
  26. bool isValidChar(IN char cIn)

  27. {

  28. return (cIn >= OTP_FIRST_CHAR) && (cIn <= OTP_LAST_CHAR);

  29. }

  30.  
  31. bool GenerateOtpKey(IN const wchar_t * pcPlaintextW, OUT std::wstring & strOtpKeyW)

  32. {

  33. bool bPassFirstRand = true;

  34. size_t nLen = 0;

  35. wchar_t cRandW = '\0';

  36.  
  37. std::string strPlaintextA;

  38.  
  39. strOtpKeyW = L"";

  40. if (NULL == pcPlaintextW)

  41. return false;

  42.  
  43. srand(static_cast<UINT>(time(NULL)));

  44.  
  45. Wstring2String(strPlaintextA, pcPlaintextW);

  46. nLen = strPlaintextA.length();

  47.  
  48. while (0 != nLen--)

  49. {

  50. cRandW = OTP_FIRST_CHAR_W - 1 + RangedRand(OTP_FIRST_INDEX, OTP_LAST_INDEX, bPassFirstRand);

  51. bPassFirstRand = false;

  52. strOtpKeyW += cRandW;

  53. }

  54.  
  55. return true;

  56. }

  57.  
  58. char char2Index(char cParam)

  59. {

  60. return cParam - OTP_FIRST_CHAR + 1;

  61. }

  62.  
  63. char Index2Char(char cParam)

  64. {

  65. /// 字符集中最后一个字符的索引是0

  66. return (cParam >= 1) ? (cParam - 1 + OTP_FIRST_CHAR) : OTP_LAST_CHAR;

  67. }

  68.  
  69. char OtpModX(int iParam, char cMod)

  70. {

  71. if (iParam < 0)

  72. iParam += cMod; ///< 防止 iParam < 0, e.g. ('a' - 'z') % 26

  73.  
  74. return static_cast<char>(iParam % cMod);

  75. }

  76.  
  77. bool OtpCipher(IN bool bEncrypt,

  78. IN OUT std::string & strPlaintext,

  79. IN const char * pcOtpKey,

  80. IN OUT std::string & strCiphertext)

  81. {

  82. char cTmp = '\0';

  83. char cX = '\0';

  84. char cK = '\0';

  85. size_t nIndex = 0;

  86. std::string::iterator it;

  87.  
  88. if ((NULL == pcOtpKey)

  89. || (bEncrypt && (strlen(strPlaintext.c_str()) != strlen(pcOtpKey)))

  90. || (!bEncrypt && (strlen(strCiphertext.c_str()) != strlen(pcOtpKey))))

  91. {

  92. return false;

  93. }

  94.  
  95. if (bEncrypt)

  96. {

  97. /// OTP加密算法:

  98. /// EK(x) = ((x1 + k1)%26,(x2 + k2)%26,...(xn + kn)%26)

  99. strCiphertext = "";

  100. for (it = strPlaintext.begin(); it != strPlaintext.end(); it++)

  101. {

  102. cX = char2Index(*it);

  103. cK = char2Index(*(pcOtpKey + nIndex++));

  104. cTmp = OtpModX(cX + cK, OTP_MOD);

  105. strCiphertext += Index2Char(cTmp);

  106. }

  107. }

  108. else

  109. {

  110. /// OTP解密算法:

  111. /// DK(x) = ((x1 - k1)%26,(x2 - k2)%26,...(xn - kn)%26)

  112. strPlaintext = "";

  113. for (it = strCiphertext.begin(); it != strCiphertext.end(); it++)

  114. {

  115. cX = char2Index(*it);

  116. cK = char2Index(*(pcOtpKey + nIndex++));

  117. cTmp = OtpModX(cX - cK, OTP_MOD);

  118. strPlaintext += Index2Char(cTmp);

  119. }

  120. }

  121.  
  122. return true;

  123. }

<2013_0112_1033>

OTP加密的好处: 多表替换.

多表替换: 在整个消息中, 同一个字符通常不会被加密成同一个字符.

猜你喜欢

转载自blog.csdn.net/p312011150/article/details/81076507