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.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. if len(payload) > 100:
  57. warnings.warn(
  58. 'Unable to hide all payload. %d bytes not hidden' % (
  59. len(payload)))
  60. else:
  61. warnings.warn(
  62. 'Unable to hide all payload. %d bytes not hidden : "%s"' % (
  63. len(payload), repr(payload)))
  64. if cur_shift != 8:
  65. warnings.warn(
  66. 'last byte not complete. %d bits missing' % (8 - cur_shift))
  67. return res
  68. def unhide(html):
  69. res = bytearray()
  70. cur_byte = 0
  71. cur_shift = 0
  72. prev = None
  73. pre_add = False
  74. for c in html:
  75. bit_added = False
  76. if c in R_CHARS and prev == c:
  77. #1
  78. cur_byte += 1 << cur_shift
  79. bit_added = True
  80. c = None
  81. elif prev in R_CHARS:
  82. #0
  83. bit_added = True
  84. if bit_added:
  85. if cur_shift == 7:
  86. #print("unhide byte ", bytearray([cur_byte]))
  87. res += bytearray([cur_byte])
  88. cur_byte = 0
  89. cur_shift = 0
  90. else:
  91. cur_shift += 1
  92. prev = c
  93. return res