TestBase32.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 2 or (at your option)
  7. * version 3 of the License.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "TestBase32.h"
  18. #include "core/Base32.h"
  19. #include <QTest>
  20. QTEST_GUILESS_MAIN(TestBase32)
  21. void TestBase32::testDecode()
  22. {
  23. // 3 quanta, all upper case + padding
  24. QByteArray encodedData = "JBSWY3DPEB3W64TMMQXC4LQ=";
  25. QVariant data = Base32::decode(encodedData);
  26. QString expectedData = "Hello world...";
  27. QVERIFY(!data.isNull());
  28. QCOMPARE(data.toString(), expectedData);
  29. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  30. // 4 quanta, all upper case
  31. encodedData = "GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ";
  32. data = Base32::decode(encodedData);
  33. expectedData = "12345678901234567890";
  34. QVERIFY(!data.isNull());
  35. QCOMPARE(data.toString(), expectedData);
  36. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  37. // 4 quanta, all lower case
  38. encodedData = "gezdgnbvgy3tqojqgezdgnbvgy3tqojq";
  39. data = Base32::decode(encodedData);
  40. expectedData = "12345678901234567890";
  41. QVERIFY(!data.isNull());
  42. QCOMPARE(data.toString(), expectedData);
  43. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  44. // 4 quanta, mixed upper and lower case
  45. encodedData = "Gezdgnbvgy3tQojqgezdGnbvgy3tQojQ";
  46. data = Base32::decode(encodedData);
  47. expectedData = "12345678901234567890";
  48. QVERIFY(!data.isNull());
  49. QCOMPARE(data.toString(), expectedData);
  50. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  51. // 1 pad characters
  52. encodedData = "ORSXG5A=";
  53. data = Base32::decode(encodedData);
  54. expectedData = "test";
  55. QVERIFY(!data.isNull());
  56. QCOMPARE(data.toString(), expectedData);
  57. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  58. // 3 pad characters
  59. encodedData = "L5PV6===";
  60. data = Base32::decode(encodedData);
  61. expectedData = "___";
  62. QVERIFY(!data.isNull());
  63. QCOMPARE(data.toString(), expectedData);
  64. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  65. // 4 pad characters
  66. encodedData = "MZXW6IDCMFZA====";
  67. data = Base32::decode(encodedData);
  68. expectedData = "foo bar";
  69. QVERIFY(!data.isNull());
  70. QCOMPARE(data.toString(), expectedData);
  71. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  72. // six pad characters
  73. encodedData = "MZXW6YTBOI======";
  74. data = Base32::decode(encodedData);
  75. expectedData = "foobar";
  76. QVERIFY(!data.isNull());
  77. QCOMPARE(data.toString(), expectedData);
  78. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  79. encodedData = "IA======";
  80. data = Base32::decode(encodedData);
  81. expectedData = "@";
  82. QVERIFY(!data.isNull());
  83. QCOMPARE(data.toString(), expectedData);
  84. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  85. // error: illegal character
  86. encodedData = "1MZXW6YTBOI=====";
  87. data = Base32::decode(encodedData);
  88. QVERIFY(data.isNull());
  89. // error: missing pad character
  90. encodedData = "MZXW6YTBOI=====";
  91. data = Base32::decode(encodedData);
  92. QVERIFY(data.isNull());
  93. // RFC 4648 test vectors
  94. encodedData = "";
  95. data = Base32::decode(encodedData);
  96. expectedData = "";
  97. QVERIFY(!data.isNull());
  98. QCOMPARE(data.toString(), expectedData);
  99. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  100. encodedData = "MY======";
  101. data = Base32::decode(encodedData);
  102. expectedData = "f";
  103. QVERIFY(!data.isNull());
  104. QCOMPARE(data.toString(), expectedData);
  105. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  106. encodedData = "MZXQ====";
  107. data = Base32::decode(encodedData);
  108. expectedData = "fo";
  109. QVERIFY(!data.isNull());
  110. QCOMPARE(data.toString(), expectedData);
  111. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  112. encodedData = "MZXW6===";
  113. data = Base32::decode(encodedData);
  114. QVERIFY(!data.isNull());
  115. expectedData = "foo";
  116. QCOMPARE(data.toString(), expectedData);
  117. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  118. encodedData = "MZXW6YQ=";
  119. data = Base32::decode(encodedData);
  120. expectedData = "foob";
  121. QVERIFY(!data.isNull());
  122. QCOMPARE(data.toString(), expectedData);
  123. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  124. encodedData = "MZXW6YTB";
  125. expectedData = "fooba";
  126. data = Base32::decode(encodedData);
  127. QVERIFY(!data.isNull());
  128. QCOMPARE(data.toString(), expectedData);
  129. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  130. encodedData = "MZXW6YTBOI======";
  131. data = Base32::decode(encodedData);
  132. expectedData = "foobar";
  133. QVERIFY(!data.isNull());
  134. QCOMPARE(data.toString(), expectedData);
  135. QVERIFY(data.value<QByteArray>().size() == expectedData.size());
  136. }
  137. void TestBase32::testEncode()
  138. {
  139. QByteArray data = "Hello world...";
  140. QByteArray encodedData = Base32::encode(data);
  141. QCOMPARE(encodedData, QByteArray("JBSWY3DPEB3W64TMMQXC4LQ="));
  142. data = "12345678901234567890";
  143. encodedData = Base32::encode(data);
  144. QCOMPARE(encodedData, QByteArray("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ"));
  145. data = "012345678901234567890";
  146. encodedData = Base32::encode(data);
  147. QCOMPARE(encodedData, QByteArray("GAYTEMZUGU3DOOBZGAYTEMZUGU3DOOBZGA======"));
  148. data = "test";
  149. encodedData = Base32::encode(data);
  150. QCOMPARE(encodedData, QByteArray("ORSXG5A="));
  151. data = "___";
  152. encodedData = Base32::encode(data);
  153. QCOMPARE(encodedData, QByteArray("L5PV6==="));
  154. data = "foo bar";
  155. encodedData = Base32::encode(data);
  156. QCOMPARE(encodedData, QByteArray("MZXW6IDCMFZA===="));
  157. data = "@";
  158. encodedData = Base32::encode(data);
  159. QCOMPARE(encodedData, QByteArray("IA======"));
  160. // RFC 4648 test vectors
  161. data = "";
  162. encodedData = Base32::encode(data);
  163. QCOMPARE(encodedData, QByteArray(""));
  164. data = "f";
  165. encodedData = Base32::encode(data);
  166. QCOMPARE(encodedData, QByteArray("MY======"));
  167. data = "fo";
  168. encodedData = Base32::encode(data);
  169. QCOMPARE(encodedData, QByteArray("MZXQ===="));
  170. data = "foo";
  171. encodedData = Base32::encode(data);
  172. QCOMPARE(encodedData, QByteArray("MZXW6==="));
  173. data = "foob";
  174. encodedData = Base32::encode(data);
  175. QCOMPARE(encodedData, QByteArray("MZXW6YQ="));
  176. data = "fooba";
  177. encodedData = Base32::encode(data);
  178. QCOMPARE(encodedData, QByteArray("MZXW6YTB"));
  179. data = "foobar";
  180. encodedData = Base32::encode(data);
  181. QCOMPARE(encodedData, QByteArray("MZXW6YTBOI======"));
  182. }
  183. void TestBase32::testAddPadding()
  184. {
  185. // Empty. Invalid, returns input.
  186. QByteArray data = "";
  187. QByteArray paddedData = Base32::addPadding(data);
  188. QCOMPARE(paddedData, data);
  189. // One byte of encoded data. Invalid, returns input.
  190. data = "B";
  191. paddedData = Base32::addPadding(data);
  192. QCOMPARE(paddedData, data);
  193. // Two bytes of encoded data.
  194. data = "BB";
  195. paddedData = Base32::addPadding(data);
  196. QCOMPARE(paddedData, QByteArray("BB======"));
  197. // Three bytes of encoded data. Invalid, returns input.
  198. data = "BBB";
  199. paddedData = Base32::addPadding(data);
  200. QCOMPARE(paddedData, data);
  201. // Four bytes of encoded data.
  202. data = "BBBB";
  203. paddedData = Base32::addPadding(data);
  204. QCOMPARE(paddedData, QByteArray("BBBB===="));
  205. // Five bytes of encoded data.
  206. data = "BBBBB";
  207. paddedData = Base32::addPadding(data);
  208. QCOMPARE(paddedData, QByteArray("BBBBB==="));
  209. // Six bytes of encoded data. Invalid, returns input.
  210. data = "BBBBBB";
  211. paddedData = Base32::addPadding(data);
  212. QCOMPARE(paddedData, data);
  213. // Seven bytes of encoded data.
  214. data = "BBBBBBB";
  215. paddedData = Base32::addPadding(data);
  216. QCOMPARE(paddedData, QByteArray("BBBBBBB="));
  217. // Eight bytes of encoded data. Valid, but returns same as input.
  218. data = "BBBBBBBB";
  219. paddedData = Base32::addPadding(data);
  220. QCOMPARE(paddedData, data);
  221. // More than eight bytes (8+5).
  222. data = "AAAAAAAABBBBB";
  223. paddedData = Base32::addPadding(data);
  224. QCOMPARE(paddedData, QByteArray("AAAAAAAABBBBB==="));
  225. }
  226. void TestBase32::testRemovePadding()
  227. {
  228. QByteArray data = "";
  229. QByteArray unpaddedData = Base32::removePadding(data);
  230. QCOMPARE(unpaddedData, data);
  231. data = "AAAAAAAABB======";
  232. unpaddedData = Base32::removePadding(data);
  233. QCOMPARE(unpaddedData, QByteArray("AAAAAAAABB"));
  234. data = "BBBB====";
  235. unpaddedData = Base32::removePadding(data);
  236. QCOMPARE(unpaddedData, QByteArray("BBBB"));
  237. data = "AAAAAAAABBBBB===";
  238. unpaddedData = Base32::removePadding(data);
  239. QCOMPARE(unpaddedData, QByteArray("AAAAAAAABBBBB"));
  240. data = "BBBBBBB=";
  241. unpaddedData = Base32::removePadding(data);
  242. QCOMPARE(unpaddedData, QByteArray("BBBBBBB"));
  243. // Invalid: 7 bytes of data. Returns same as input.
  244. data = "IIIIIII";
  245. unpaddedData = Base32::removePadding(data);
  246. QCOMPARE(unpaddedData, data);
  247. // Invalid: more padding than necessary. Returns same as input.
  248. data = "AAAAAAAABBBB=====";
  249. unpaddedData = Base32::removePadding(data);
  250. QCOMPARE(unpaddedData, data);
  251. }
  252. void TestBase32::testSanitizeInput()
  253. {
  254. // sanitize input (white space + missing padding)
  255. QByteArray encodedData = "JBSW Y3DP EB3W 64TM MQXC 4LQA";
  256. auto data = Base32::decode(Base32::sanitizeInput(encodedData));
  257. QVERIFY(!data.isNull());
  258. QCOMPARE(data.toString(), QString("Hello world..."));
  259. // sanitize input (typo + missing padding)
  260. encodedData = "J8SWY3DPE83W64TMMQXC4LQA";
  261. data = Base32::decode(Base32::sanitizeInput(encodedData));
  262. QVERIFY(!data.isNull());
  263. QCOMPARE(data.toString(), QString("Hello world..."));
  264. // sanitize input (other illegal characters)
  265. encodedData = "J8SWY3D[PE83W64TMMQ]XC!4LQA";
  266. data = Base32::decode(Base32::sanitizeInput(encodedData));
  267. QVERIFY(!data.isNull());
  268. QCOMPARE(data.toString(), QString("Hello world..."));
  269. // sanitize input (NUL character)
  270. encodedData = "J8SWY3DPE83W64TMMQXC4LQA";
  271. encodedData.insert(3, '\0');
  272. data = Base32::decode(Base32::sanitizeInput(encodedData));
  273. QVERIFY(!data.isNull());
  274. QCOMPARE(data.toString(), QString("Hello world..."));
  275. }