QAESEncryption.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. #include "QAESEncryption.h"
  2. /*
  3. * Static Functions
  4. * */
  5. QByteArray QAESEncryption::Crypt(QAESEncryption::AES level, QAESEncryption::MODE mode, const QByteArray &rawText,
  6. const QByteArray &key, const QByteArray &iv, QAESEncryption::PADDING padding)
  7. {
  8. return QAESEncryption(level, mode, padding).encode(rawText, key, iv);
  9. }
  10. QByteArray QAESEncryption::Decrypt(QAESEncryption::AES level, QAESEncryption::MODE mode, const QByteArray &rawText,
  11. const QByteArray &key, const QByteArray &iv, QAESEncryption::PADDING padding)
  12. {
  13. return QAESEncryption(level, mode, padding).decode(rawText, key, iv);
  14. }
  15. QByteArray QAESEncryption::ExpandKey(QAESEncryption::AES level, QAESEncryption::MODE mode, const QByteArray &key)
  16. {
  17. return QAESEncryption(level, mode).expandKey(key);
  18. }
  19. QByteArray QAESEncryption::RemovePadding(const QByteArray &rawText, QAESEncryption::PADDING padding)
  20. {
  21. QByteArray ret(rawText);
  22. switch (padding)
  23. {
  24. case PADDING::ZERO:
  25. //Works only if the last byte of the decoded array is not zero
  26. while (ret.at(ret.length()-1) == 0x00)
  27. ret.remove(ret.length()-1, 1);
  28. break;
  29. case PADDING::PKCS7:
  30. ret.remove(ret.length() - ret.at(ret.length()-1), ret.at(ret.length()-1));
  31. break;
  32. case PADDING::ISO:
  33. ret.truncate(ret.lastIndexOf(0x80u));
  34. break;
  35. default:
  36. //do nothing
  37. break;
  38. }
  39. return ret;
  40. }
  41. /*
  42. * End Static function declarations
  43. * */
  44. /*
  45. * Inline Functions
  46. * */
  47. inline quint8 xTime(quint8 x){
  48. return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
  49. }
  50. inline quint8 multiply(quint8 x, quint8 y){
  51. return (((y & 1) * x) ^ ((y>>1 & 1) * xTime(x)) ^ ((y>>2 & 1) * xTime(xTime(x))) ^ ((y>>3 & 1)
  52. * xTime(xTime(xTime(x)))) ^ ((y>>4 & 1) * xTime(xTime(xTime(xTime(x))))));
  53. }
  54. /*
  55. * End Inline functions
  56. * */
  57. QAESEncryption::QAESEncryption(QAESEncryption::AES level, QAESEncryption::MODE mode, PADDING padding)
  58. : m_nb(4), m_blocklen(16), m_level(level), m_mode(mode), m_padding(padding)
  59. {
  60. m_state = NULL;
  61. switch (level)
  62. {
  63. case AES_128: {
  64. AES128 aes;
  65. m_nk = aes.nk;
  66. m_keyLen = aes.keylen;
  67. m_nr = aes.nr;
  68. m_expandedKey = aes.expandedKey;
  69. }
  70. break;
  71. case AES_192: {
  72. AES192 aes;
  73. m_nk = aes.nk;
  74. m_keyLen = aes.keylen;
  75. m_nr = aes.nr;
  76. m_expandedKey = aes.expandedKey;
  77. }
  78. break;
  79. case AES_256: {
  80. AES256 aes;
  81. m_nk = aes.nk;
  82. m_keyLen = aes.keylen;
  83. m_nr = aes.nr;
  84. m_expandedKey = aes.expandedKey;
  85. }
  86. break;
  87. default: {
  88. AES128 aes;
  89. m_nk = aes.nk;
  90. m_keyLen = aes.keylen;
  91. m_nr = aes.nr;
  92. m_expandedKey = aes.expandedKey;
  93. }
  94. break;
  95. }
  96. }
  97. QByteArray QAESEncryption::getPadding(int currSize, int alignment)
  98. {
  99. QByteArray ret(0);
  100. int size = (alignment - currSize % alignment) % alignment;
  101. if (size == 0) return ret;
  102. switch(m_padding)
  103. {
  104. case PADDING::ZERO:
  105. ret.insert(0, size, 0x00);
  106. break;
  107. case PADDING::PKCS7:
  108. ret.insert(0, size, size);
  109. break;
  110. case PADDING::ISO:
  111. ret.insert(0, 0x80u);
  112. ret.insert(1, size, 0x00);
  113. break;
  114. default:
  115. ret.insert(0, size, 0x00);
  116. break;
  117. }
  118. return ret;
  119. }
  120. QByteArray QAESEncryption::expandKey(const QByteArray &key)
  121. {
  122. int i, k;
  123. quint8 tempa[4]; // Used for the column/row operations
  124. QByteArray roundKey(key);
  125. // The first round key is the key itself.
  126. // ...
  127. // All other round keys are found from the previous round keys.
  128. //i == Nk
  129. for(i = m_nk; i < m_nb * (m_nr + 1); i++)
  130. {
  131. tempa[0] = (quint8) roundKey.at((i-1) * 4 + 0);
  132. tempa[1] = (quint8) roundKey.at((i-1) * 4 + 1);
  133. tempa[2] = (quint8) roundKey.at((i-1) * 4 + 2);
  134. tempa[3] = (quint8) roundKey.at((i-1) * 4 + 3);
  135. if (i % m_nk == 0)
  136. {
  137. // This function shifts the 4 bytes in a word to the left once.
  138. // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
  139. // Function RotWord()
  140. k = tempa[0];
  141. tempa[0] = tempa[1];
  142. tempa[1] = tempa[2];
  143. tempa[2] = tempa[3];
  144. tempa[3] = k;
  145. // Function Subword()
  146. tempa[0] = getSBoxValue(tempa[0]);
  147. tempa[1] = getSBoxValue(tempa[1]);
  148. tempa[2] = getSBoxValue(tempa[2]);
  149. tempa[3] = getSBoxValue(tempa[3]);
  150. tempa[0] = tempa[0] ^ Rcon[i/m_nk];
  151. }
  152. if (m_level == AES_256 && i % m_nk == 4)
  153. {
  154. // Function Subword()
  155. tempa[0] = getSBoxValue(tempa[0]);
  156. tempa[1] = getSBoxValue(tempa[1]);
  157. tempa[2] = getSBoxValue(tempa[2]);
  158. tempa[3] = getSBoxValue(tempa[3]);
  159. }
  160. roundKey.insert(i * 4 + 0, (quint8) roundKey.at((i - m_nk) * 4 + 0) ^ tempa[0]);
  161. roundKey.insert(i * 4 + 1, (quint8) roundKey.at((i - m_nk) * 4 + 1) ^ tempa[1]);
  162. roundKey.insert(i * 4 + 2, (quint8) roundKey.at((i - m_nk) * 4 + 2) ^ tempa[2]);
  163. roundKey.insert(i * 4 + 3, (quint8) roundKey.at((i - m_nk) * 4 + 3) ^ tempa[3]);
  164. }
  165. return roundKey;
  166. }
  167. // This function adds the round key to state.
  168. // The round key is added to the state by an XOR function.
  169. void QAESEncryption::addRoundKey(const quint8 round, const QByteArray expKey)
  170. {
  171. QByteArray::iterator it = m_state->begin();
  172. for(int i=0; i < 16; ++i)
  173. it[i] = (quint8) it[i] ^ (quint8) expKey.at(round * m_nb * 4 + (i/4) * m_nb + (i%4));
  174. }
  175. // The SubBytes Function Substitutes the values in the
  176. // state matrix with values in an S-box.
  177. void QAESEncryption::subBytes()
  178. {
  179. QByteArray::iterator it = m_state->begin();
  180. for(int i = 0; i < 16; i++)
  181. it[i] = getSBoxValue((quint8) it[i]);
  182. }
  183. // The ShiftRows() function shifts the rows in the state to the left.
  184. // Each row is shifted with different offset.
  185. // Offset = Row number. So the first row is not shifted.
  186. void QAESEncryption::shiftRows()
  187. {
  188. QByteArray::iterator it = m_state->begin();
  189. quint8 temp;
  190. //Keep in mind that QByteArray is column-driven!!
  191. //Shift 1 to left
  192. temp = (quint8)it[1];
  193. it[1] = (quint8)it[5];
  194. it[5] = (quint8)it[9];
  195. it[9] = (quint8)it[13];
  196. it[13] = (quint8)temp;
  197. //Shift 2 to left
  198. temp = (quint8)it[2];
  199. it[2] = (quint8)it[10];
  200. it[10] = (quint8)temp;
  201. temp = (quint8)it[6];
  202. it[6] = (quint8)it[14];
  203. it[14] = (quint8)temp;
  204. //Shift 3 to left
  205. temp = (quint8)it[3];
  206. it[3] = (quint8)it[15];
  207. it[15] = (quint8)it[11];
  208. it[11] = (quint8)it[7];
  209. it[7] = (quint8)temp;
  210. }
  211. // MixColumns function mixes the columns of the state matrix
  212. //optimized!!
  213. void QAESEncryption::mixColumns()
  214. {
  215. QByteArray::iterator it = m_state->begin();
  216. quint8 tmp, tm, t;
  217. for(int i = 0; i < 16; i += 4){
  218. t = (quint8)it[i];
  219. tmp = (quint8)it[i] ^ (quint8)it[i+1] ^ (quint8)it[i+2] ^ (quint8)it[i+3] ;
  220. tm = xTime( (quint8)it[i] ^ (quint8)it[i+1] );
  221. it[i] = (quint8)it[i] ^ (quint8)tm ^ (quint8)tmp;
  222. tm = xTime( (quint8)it[i+1] ^ (quint8)it[i+2]);
  223. it[i+1] = (quint8)it[i+1] ^ (quint8)tm ^ (quint8)tmp;
  224. tm = xTime( (quint8)it[i+2] ^ (quint8)it[i+3]);
  225. it[i+2] =(quint8)it[i+2] ^ (quint8)tm ^ (quint8)tmp;
  226. tm = xTime((quint8)it[i+3] ^ (quint8)t);
  227. it[i+3] =(quint8)it[i+3] ^ (quint8)tm ^ (quint8)tmp;
  228. }
  229. }
  230. // MixColumns function mixes the columns of the state matrix.
  231. // The method used to multiply may be difficult to understand for the inexperienced.
  232. // Please use the references to gain more information.
  233. void QAESEncryption::invMixColumns()
  234. {
  235. QByteArray::iterator it = m_state->begin();
  236. quint8 a,b,c,d;
  237. for(int i = 0; i < 16; i+=4){
  238. a = (quint8) it[i];
  239. b = (quint8) it[i+1];
  240. c = (quint8) it[i+2];
  241. d = (quint8) it[i+3];
  242. it[i] = (quint8) (multiply(a, 0x0e) ^ multiply(b, 0x0b) ^ multiply(c, 0x0d) ^ multiply(d, 0x09));
  243. it[i+1] = (quint8) (multiply(a, 0x09) ^ multiply(b, 0x0e) ^ multiply(c, 0x0b) ^ multiply(d, 0x0d));
  244. it[i+2] = (quint8) (multiply(a, 0x0d) ^ multiply(b, 0x09) ^ multiply(c, 0x0e) ^ multiply(d, 0x0b));
  245. it[i+3] = (quint8) (multiply(a, 0x0b) ^ multiply(b, 0x0d) ^ multiply(c, 0x09) ^ multiply(d, 0x0e));
  246. }
  247. }
  248. // The SubBytes Function Substitutes the values in the
  249. // state matrix with values in an S-box.
  250. void QAESEncryption::invSubBytes()
  251. {
  252. QByteArray::iterator it = m_state->begin();
  253. for(int i = 0; i < 16; ++i)
  254. it[i] = getSBoxInvert((quint8) it[i]);
  255. }
  256. void QAESEncryption::invShiftRows()
  257. {
  258. QByteArray::iterator it = m_state->begin();
  259. uint8_t temp;
  260. //Keep in mind that QByteArray is column-driven!!
  261. //Shift 1 to right
  262. temp = (quint8)it[13];
  263. it[13] = (quint8)it[9];
  264. it[9] = (quint8)it[5];
  265. it[5] = (quint8)it[1];
  266. it[1] = (quint8)temp;
  267. //Shift 2
  268. temp = (quint8)it[10];
  269. it[10] = (quint8)it[2];
  270. it[2] = (quint8)temp;
  271. temp = (quint8)it[14];
  272. it[14] = (quint8)it[6];
  273. it[6] = (quint8)temp;
  274. //Shift 3
  275. temp = (quint8)it[15];
  276. it[15] = (quint8)it[3];
  277. it[3] = (quint8)it[7];
  278. it[7] = (quint8)it[11];
  279. it[11] = (quint8)temp;
  280. }
  281. QByteArray QAESEncryption::byteXor(const QByteArray &a, const QByteArray &b)
  282. {
  283. QByteArray::const_iterator it_a = a.begin();
  284. QByteArray::const_iterator it_b = b.begin();
  285. QByteArray ret;
  286. for(int i = 0; i < m_blocklen; i++)
  287. ret.insert(i,it_a[i] ^ it_b[i]);
  288. return ret;
  289. }
  290. // Cipher is the main function that encrypts the PlainText.
  291. QByteArray QAESEncryption::cipher(const QByteArray &expKey, const QByteArray &in)
  292. {
  293. //m_state is the input buffer...
  294. QByteArray output(in);
  295. m_state = &output;
  296. // Add the First round key to the state before starting the rounds.
  297. addRoundKey(0, expKey);
  298. // There will be Nr rounds.
  299. // The first Nr-1 rounds are identical.
  300. // These Nr-1 rounds are executed in the loop below.
  301. for(quint8 round = 1; round < m_nr; ++round){
  302. subBytes();
  303. shiftRows();
  304. mixColumns();
  305. addRoundKey(round, expKey);
  306. }
  307. // The last round is given below.
  308. // The MixColumns function is not here in the last round.
  309. subBytes();
  310. shiftRows();
  311. addRoundKey(m_nr, expKey);
  312. return output;
  313. }
  314. QByteArray QAESEncryption::invCipher(const QByteArray &expKey, const QByteArray &in)
  315. {
  316. //m_state is the input buffer.... handle it!
  317. QByteArray output(in);
  318. m_state = &output;
  319. // Add the First round key to the state before starting the rounds.
  320. addRoundKey(m_nr, expKey);
  321. // There will be Nr rounds.
  322. // The first Nr-1 rounds are identical.
  323. // These Nr-1 rounds are executed in the loop below.
  324. for(quint8 round=m_nr-1; round>0 ; round--){
  325. invShiftRows();
  326. invSubBytes();
  327. addRoundKey(round, expKey);
  328. invMixColumns();
  329. }
  330. // The last round is given below.
  331. // The MixColumns function is not here in the last round.
  332. invShiftRows();
  333. invSubBytes();
  334. addRoundKey(0, expKey);
  335. return output;
  336. }
  337. QByteArray QAESEncryption::encode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv)
  338. {
  339. if (m_mode >= CBC && (iv.isNull() || iv.size() != m_blocklen))
  340. return QByteArray();
  341. QByteArray ret;
  342. QByteArray expandedKey = expandKey(key);
  343. QByteArray alignedText(rawText);
  344. QByteArray ivTemp(iv);
  345. //Fill array with padding
  346. alignedText.append(getPadding(rawText.size(), m_blocklen));
  347. //Preparation for CFB
  348. if (m_mode == CFB)
  349. ret.append(byteXor(alignedText.mid(0, m_blocklen), cipher(expandedKey, iv)));
  350. //Looping thru all blocks
  351. for(int i=0; i < alignedText.size(); i+= m_blocklen){
  352. switch(m_mode)
  353. {
  354. case ECB:
  355. ret.append(cipher(expandedKey, alignedText.mid(i, m_blocklen)));
  356. break;
  357. case CBC:
  358. alignedText.replace(i, m_blocklen, byteXor(alignedText.mid(i, m_blocklen),ivTemp));
  359. ret.append(cipher(expandedKey, alignedText.mid(i, m_blocklen)));
  360. ivTemp = ret.mid(i, m_blocklen);
  361. break;
  362. case CFB:
  363. if (i+m_blocklen < alignedText.size())
  364. ret.append(byteXor(alignedText.mid(i+m_blocklen, m_blocklen),
  365. cipher(expandedKey, ret.mid(i, m_blocklen))));
  366. break;
  367. default:
  368. //do nothing
  369. break;
  370. }
  371. }
  372. return ret;
  373. }
  374. QByteArray QAESEncryption::decode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv)
  375. {
  376. if (m_mode >= CBC && (iv.isNull() || iv.size() != m_blocklen))
  377. return QByteArray();
  378. QByteArray ret;
  379. QByteArray expandedKey = expandKey(key);
  380. QByteArray ivTemp(iv);
  381. //Preparation for CFB
  382. if (m_mode == CFB)
  383. ret.append(byteXor(rawText.mid(0, m_blocklen), cipher(expandedKey, iv)));
  384. for(int i=0; i < rawText.size(); i+= m_blocklen){
  385. switch(m_mode)
  386. {
  387. case ECB:
  388. ret.append(invCipher(expandedKey, rawText.mid(i, m_blocklen)));
  389. break;
  390. case CBC:
  391. ret.append(invCipher(expandedKey, rawText.mid(i, m_blocklen)));
  392. ret.replace(i, m_blocklen, byteXor(ret.mid(i, m_blocklen),ivTemp));
  393. ivTemp = rawText.mid(i, m_blocklen);
  394. break;
  395. case CFB:
  396. if (i+m_blocklen < rawText.size()){
  397. ret.append(byteXor(rawText.mid(i+m_blocklen, m_blocklen),
  398. cipher(expandedKey, rawText.mid(i, m_blocklen))));
  399. }
  400. break;
  401. default:
  402. //do nothing
  403. break;
  404. }
  405. }
  406. return ret;
  407. }
  408. QByteArray QAESEncryption::removePadding(const QByteArray &rawText)
  409. {
  410. QByteArray ret(rawText);
  411. switch (m_padding)
  412. {
  413. case PADDING::ZERO:
  414. //Works only if the last byte of the decoded array is not zero
  415. while (ret.at(ret.length()-1) == 0x00)
  416. ret.remove(ret.length()-1, 1);
  417. break;
  418. case PADDING::PKCS7:
  419. ret.remove(ret.length() - ret.at(ret.length()-1), ret.at(ret.length()-1));
  420. break;
  421. case PADDING::ISO:
  422. ret.truncate(ret.lastIndexOf(0x80u));
  423. break;
  424. default:
  425. //do nothing
  426. break;
  427. }
  428. return ret;
  429. }