fork download
  1. #include <array>
  2. #include <cstdlib>
  3. #include <iostream>
  4. #include <memory>
  5.  
  6. using namespace std;
  7.  
  8. class DES;
  9.  
  10. class DES {
  11. public:
  12. DES(const unsigned long long& key);
  13. unsigned long long encipher(const unsigned long long& plane_data);
  14. unsigned long long decipher(const unsigned long long& cipher_data);
  15. protected:
  16. shared_ptr<array<unsigned long long, 16> > subkeys;
  17. DES(const DES& des);
  18. DES& operator =(const DES& des);
  19. static const unsigned int PC_1C_TABLE[28];
  20. static const unsigned int PC_1D_TABLE[28];
  21. static const unsigned int PC_2_TABLE[48];
  22. static const unsigned int SUBKEY_SHIFT_AMOUNTS[16];
  23. static const unsigned int IP_TABLE[64];
  24. static const unsigned int IIP_TABLE[64];
  25. static const unsigned int E_TABLE[48];
  26. static const unsigned int S_TABLE[8][4][16];
  27. static const unsigned int P_TABLE[32];
  28. static unsigned long long appendParityBits(const unsigned long long& key);
  29. template <class I> static unsigned long long execute(const unsigned long long& data, const I& begin, const I& end);
  30. static unsigned long f(const unsigned long& r, const unsigned long long& subkey);
  31. static unsigned char s(const unsigned char& t, const unsigned int tab[4][16]);
  32. template <class D, class S> static D choice(const S& src, const unsigned int& src_len, const unsigned int* tab, const unsigned int& tab_len);
  33. };
  34.  
  35. template <class X> X rotateLeft(const X& x, const unsigned int& n, const unsigned int& w = (sizeof(X) << 3));
  36.  
  37. #define ASSERT(pred) assert(#pred, pred);
  38.  
  39. extern void assert(const char* pred_str, const bool& pred_res);
  40.  
  41. const unsigned int DES::PC_1C_TABLE[28] = {
  42. 57, 49, 41, 33, 25, 17, 9,
  43. 1, 58, 50, 42, 34, 26, 18,
  44. 10, 2, 59, 51, 43, 35, 27,
  45. 19, 11, 3, 60, 52, 44, 36,
  46. };
  47.  
  48. const unsigned int DES::PC_1D_TABLE[28] = {
  49. 63, 55, 47, 39, 31, 23, 15,
  50. 7, 62, 54, 46, 38, 30, 22,
  51. 14, 6, 61, 53, 45, 37, 29,
  52. 21, 13, 5, 28, 20, 12, 4,
  53. };
  54.  
  55. const unsigned int DES::PC_2_TABLE[48] = {
  56. 14, 17, 11, 24, 1, 5,
  57. 3, 28, 15, 6, 21, 10,
  58. 23, 19, 12, 4, 26, 8,
  59. 16, 7, 27, 20, 13, 2,
  60. 41, 52, 31, 37, 47, 55,
  61. 30, 40, 51, 45, 33, 48,
  62. 44, 49, 39, 56, 34, 53,
  63. 46, 42, 50, 36, 29, 32,
  64. };
  65.  
  66. const unsigned int DES::SUBKEY_SHIFT_AMOUNTS[16] = {
  67. 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1,
  68. };
  69.  
  70. const unsigned int DES::IP_TABLE[64] = {
  71. 58, 50, 42, 34, 26, 18, 10, 2,
  72. 60, 52, 44, 36, 28, 20, 12, 4,
  73. 62, 54, 46, 38, 30, 22, 14, 6,
  74. 64, 56, 48, 40, 32, 24, 16, 8,
  75. 57, 49, 41, 33, 25, 17, 9, 1,
  76. 59, 51, 43, 35, 27, 19, 11, 3,
  77. 61, 53, 45, 37, 29, 21, 13, 5,
  78. 63, 55, 47, 39, 31, 23, 15, 7,
  79. };
  80.  
  81. const unsigned int DES::IIP_TABLE[64] = {
  82. 40, 8, 48, 16, 56, 24, 64, 32,
  83. 39, 7, 47, 15, 55, 23, 63, 31,
  84. 38, 6, 46, 14, 54, 22, 62, 30,
  85. 37, 5, 45, 13, 53, 21, 61, 29,
  86. 36, 4, 44, 12, 52, 20, 60, 28,
  87. 35, 3, 43, 11, 51, 19, 59, 27,
  88. 34, 2, 42, 10, 50, 18, 58, 26,
  89. 33, 1, 41, 9, 49, 17, 57, 25,
  90. };
  91.  
  92. const unsigned int DES::E_TABLE[48] = {
  93. 32, 1, 2, 3, 4, 5,
  94. 4, 5, 6, 7, 8, 9,
  95. 8, 9, 10, 11, 12, 13,
  96. 12, 13, 14, 15, 16, 17,
  97. 16, 17, 18, 19, 20, 21,
  98. 20, 21, 22, 23, 24, 25,
  99. 24, 25, 26, 27, 28, 29,
  100. 28, 29, 30, 31, 32, 1,
  101. };
  102.  
  103. const unsigned int DES::S_TABLE[8][4][16] = {
  104. {
  105. {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, },
  106. { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, },
  107. { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, },
  108. {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, },
  109. },
  110. {
  111. {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, },
  112. { 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, },
  113. { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, },
  114. {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, },
  115. },
  116. {
  117. {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, },
  118. {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, },
  119. {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, },
  120. { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, },
  121. },
  122. {
  123. {7 , 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, },
  124. {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, },
  125. {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, },
  126. { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, },
  127. },
  128. {
  129. { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, },
  130. {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, },
  131. { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, },
  132. {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, },
  133. },
  134. {
  135. {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, },
  136. {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, },
  137. { 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, },
  138. { 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, },
  139. },
  140. {
  141. { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, },
  142. {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, },
  143. { 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, },
  144. { 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, },
  145. },
  146. {
  147. {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, },
  148. { 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, },
  149. { 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, },
  150. { 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11, },
  151. },
  152. };
  153.  
  154. const unsigned int DES::P_TABLE[32] = {
  155. 16, 7, 20, 21,
  156. 29, 12, 28, 17,
  157. 1, 15, 23, 26,
  158. 5, 18, 31, 10,
  159. 2, 8, 24, 14,
  160. 32, 27, 3, 9,
  161. 19, 13, 30, 6,
  162. 22, 11, 4, 25,
  163. };
  164.  
  165. DES::DES(const unsigned long long& key) {
  166. unsigned long long act_key = appendParityBits(key);
  167. this->subkeys.reset(new array<unsigned long long, 16>);
  168. unsigned long c = choice<unsigned long>(act_key, 64, PC_1C_TABLE, 28);
  169. unsigned long d = choice<unsigned long>(act_key, 64, PC_1D_TABLE, 28);
  170. for (unsigned int i = 0; i < 16; i++) {
  171. c = rotateLeft(c, SUBKEY_SHIFT_AMOUNTS[i], 28);
  172. d = rotateLeft(d, SUBKEY_SHIFT_AMOUNTS[i], 28);
  173. this->subkeys->at(i) = choice<unsigned long long>(c << 28 | d, 56, PC_2_TABLE, 48);
  174. }
  175. }
  176.  
  177. unsigned long long DES::encipher(const unsigned long long& plane_data) {
  178. return execute(plane_data, this->subkeys->begin(), this->subkeys->end());
  179. }
  180.  
  181. unsigned long long DES::decipher(const unsigned long long& cipher_data) {
  182. return execute(cipher_data, this->subkeys->rbegin(), this->subkeys->rend());
  183. }
  184.  
  185. unsigned long long DES::appendParityBits(const unsigned long long& key) {
  186. unsigned long long res = 0;
  187. unsigned int par_bit = 1;
  188. for (unsigned int i = 0; i < 56; i++) {
  189. res <<= 1;
  190. unsigned int bit = (key >> (56 - 1 - i)) & 1;
  191. res |= bit;
  192. par_bit ^= bit;
  193. if ((i + 1) % 7 == 0) {
  194. res <<= 1;
  195. res |= par_bit;
  196. par_bit = 1;
  197. }
  198. }
  199. return res;
  200. }
  201.  
  202. template <class I> unsigned long long DES::execute(const unsigned long long& data, const I& begin, const I& end) {
  203. unsigned long long ip_data = choice<unsigned long long>(data, 64, IP_TABLE, 64);
  204. unsigned long l = ip_data >> 32;
  205. unsigned long r = ip_data & 0xffffffff;
  206. for (auto iter = begin; iter != end; iter++) {
  207. unsigned long t = r;
  208. r = l ^ f(r, *iter);
  209. l = t;
  210. }
  211. return choice<unsigned long long>(((unsigned long long)r << 32) | l, 64, IIP_TABLE, 64);
  212. }
  213.  
  214. unsigned long DES::f(const unsigned long& r, const unsigned long long& subkey) {
  215. unsigned long long t = choice<unsigned long long>(r, 32, E_TABLE, 48) ^ subkey;
  216. unsigned long long u = 0;
  217. for (unsigned int i = 0; i < 8; i++) {
  218. u <<= 4;
  219. u |= s((t >> (48 - 6 * (i + 1))) & 0x3f, S_TABLE[i]);
  220. }
  221. return choice<unsigned long>(u, 32, P_TABLE, 32);
  222. }
  223.  
  224. unsigned char DES::s(const unsigned char& t, const unsigned int tab[4][16]) {
  225. unsigned int row = ((t >> (6 - 1)) << 1) | (t & 1);
  226. unsigned int col = (t >> (2 - 1)) & 0xf;
  227. return tab[row][col];
  228. }
  229.  
  230. template <class D, class S> D DES::choice(const S& src, const unsigned int& src_len, const unsigned int* tab, const unsigned int& tab_len) {
  231. D dest = 0;
  232. for (unsigned int i = 0; i < tab_len; i++) {
  233. dest <<= 1;
  234. dest |= (src >> (src_len - tab[i])) & 1;
  235. }
  236. return dest;
  237. }
  238.  
  239. template <class X> X rotateLeft(const X& x, const unsigned int& n, const unsigned int& w) {
  240. return (x << n) | (x >> (w - n));
  241. }
  242.  
  243. void assert(const char* pred_str, const bool& pred_res) {
  244. if (pred_res) {
  245. cout << "アサート成功: " << pred_str << endl;
  246. }
  247. else {
  248. cerr << "アサート失敗: " << pred_str << endl;
  249. exit(1);
  250. }
  251. }
  252.  
  253. int main() {
  254. cout << hex;
  255. {
  256. DES des(0x1234567812345678);
  257. ASSERT(des.encipher(0x1234567812345678) == 0x941eddd882714d98)
  258. ASSERT(des.decipher(0x941eddd882714d98) == 0x1234567812345678)
  259. ASSERT(des.encipher(0x8765432187654321) == 0x084cd9754e5f3058)
  260. ASSERT(des.decipher(0x084cd9754e5f3058) == 0x8765432187654321)
  261. }
  262. {
  263. DES des(0x8765432187654321);
  264. ASSERT(des.encipher(0x1234567812345678) == 0x5b3a1ef3f29089a1)
  265. ASSERT(des.decipher(0x5b3a1ef3f29089a1) == 0x1234567812345678)
  266. ASSERT(des.encipher(0x8765432187654321) == 0x46f4a70e6ff7166c)
  267. ASSERT(des.decipher(0x46f4a70e6ff7166c) == 0x8765432187654321)
  268. }
  269. return 0;
  270. }
  271.  
Success #stdin #stdout 0s 3480KB
stdin
Standard input is empty
stdout
アサート成功: des.encipher(0x1234567812345678) == 0x941eddd882714d98
アサート成功: des.decipher(0x941eddd882714d98) == 0x1234567812345678
アサート成功: des.encipher(0x8765432187654321) == 0x084cd9754e5f3058
アサート成功: des.decipher(0x084cd9754e5f3058) == 0x8765432187654321
アサート成功: des.encipher(0x1234567812345678) == 0x5b3a1ef3f29089a1
アサート成功: des.decipher(0x5b3a1ef3f29089a1) == 0x1234567812345678
アサート成功: des.encipher(0x8765432187654321) == 0x46f4a70e6ff7166c
アサート成功: des.decipher(0x46f4a70e6ff7166c) == 0x8765432187654321