Program that hide data in repeating whitespace in HTML.
python
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

steg.py 2.7KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. # -*- coding: utf-8 -*-#
  2. # Copyright 2017 Weber Yann <yann.weber@member.fsf.org>
  3. #
  4. # This file is part of HtmlSteg.
  5. #
  6. # HtmlSteg is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # any later version.
  10. #
  11. # HtmlSteg is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with HtmlSteg. If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. import warnings
  20. R_CHARS = [' ', "\t", "\n"]
  21. def clean_html(html):
  22. '''Clean html squeezing repeating R_CHARS'''
  23. res = ''
  24. prev = None
  25. for c in html:
  26. if c in R_CHARS and c == prev:
  27. continue
  28. prev = c
  29. res += c
  30. return res
  31. def hide(html, payload):
  32. cur_val = payload[0]
  33. cur_bit = cur_val & 1
  34. cur_val >>= 1
  35. cur_shift = 1
  36. payload = payload[1:]
  37. end = False
  38. res = ''
  39. for c in html:
  40. if not end and c in R_CHARS:
  41. if cur_bit == 1:
  42. res += c
  43. if cur_shift == 8:
  44. cur_shift = 0
  45. if len(payload) == 0:
  46. end = True
  47. else:
  48. cur_val = payload[0]
  49. payload = payload[1:]
  50. cur_bit = cur_val & 1
  51. cur_val >>= 1
  52. cur_shift += 1
  53. res += c
  54. if not end:
  55. if len(payload) > 0:
  56. warnings.warn(
  57. 'Unable to hide all payload. %d bytes not hidden : "%s"' % (
  58. len(payload), repr(payload)))
  59. if cur_shift != 8:
  60. warnings.warn(
  61. 'last byte not complete. %d bits missing' % (8 - cur_shift))
  62. return res
  63. def unhide(html):
  64. res = bytearray()
  65. cur_byte = 0
  66. cur_shift = 0
  67. prev = None
  68. pre_add = False
  69. for c in html:
  70. bit_added = False
  71. if c in R_CHARS and prev == c:
  72. #1
  73. cur_byte += 1 << cur_shift
  74. bit_added = True
  75. c = None
  76. elif prev in R_CHARS:
  77. #0
  78. bit_added = True
  79. if bit_added:
  80. if cur_shift == 7:
  81. #print("unhide byte ", bytearray([cur_byte]))
  82. res += bytearray([cur_byte])
  83. cur_byte = 0
  84. cur_shift = 0
  85. else:
  86. cur_shift += 1
  87. prev = c
  88. return res