파비콘에 웹사이트를 저장한 실험

6 hours ago 3
  • 개발자는 브라우저 탭 아이콘인 favicon을 픽셀 바이트 저장소로 보고, 작은 HTML을 이미지의 RGB 채널에 넣는 실험을 진행함
  • 인코딩은 HTML의 UTF-8 바이트 앞에 4바이트 길이 헤더를 붙이고, 각 바이트를 픽셀의 R·G·B 값에 순서대로 기록하는 방식임
  • 데모 페이로드는 208바이트이며 헤더 포함 212바이트라서, 3바이트씩 저장하는 픽셀 71개와 9×9 PNG로 충분했음
  • 복원은 favicon 이미지를 canvas에 그린 뒤 JavaScript가 픽셀 데이터를 읽고 RGB 값을 다시 바이트 배열로 조립해 HTML로 디코딩함
  • favicon만으로 웹사이트가 독립 실행되는 구조는 아니며, 별도의 bootstrap JavaScript가 필요해 실용성보다 경계 실험에 가까움

favicon을 저장소처럼 다루는 방법

  • favicon은 브라우저 탭에 표시되는 작은 아이콘이지만, 실제로는 픽셀과 바이트로 구성된 이미지 파일
  • 실험의 출발점은 스테가노그래피였지만, 데모에서는 아이콘처럼 보이는 것보다 순수한 저장 공간으로 쓰는 데 초점을 둠
  • 저장 대상은 작은 HTML 페이로드임
<h1>Website in a Favicon</h1> <p> Everything you're reading right now was decoded from favicon pixels. </p>
  • 인코딩 절차는 단순함
    • TextEncoder로 HTML을 UTF-8 바이트로 변환함
    • 페이로드 길이를 담은 4바이트 헤더를 앞에 붙임
    • 남는 픽셀이 있을 수 있어 길이 헤더로 실제 페이로드의 끝을 구분함
    • 첫 번째 바이트는 첫 픽셀의 red 채널, 두 번째 바이트는 green, 세 번째 바이트는 blue에 저장됨
    • 이후 픽셀도 같은 순서로 채워 HTML 문서 전체가 색상값으로 들어감
  • 결과 이미지는 시각적으로 노이즈처럼 보임

크기와 복원 과정

  • 데모의 최종 크기는 매우 작음
    • 페이로드: 208 bytes
    • 헤더 포함 총량: 212 bytes
    • 필요한 픽셀: 71 pixels
    • 이미지 크기: 9×9 pixels
    • 용량: 239 bytes
    • 사용률: 87% {p:87}
  • 복원은 브라우저 기능만으로 처리됨
    • favicon을 이미지로 로드함
    • 이미지를 canvas에 그림
    • Canvas API로 모든 픽셀을 읽음
    • RGB 값을 바이트 배열로 재구성함
    • 처음 4바이트에서 페이로드 길이를 읽음
    • 페이로드를 추출하고 UTF-8 텍스트로 디코딩함
  • 데모 사이트는 "Render Website" 버튼을 누르면 favicon을 읽고 HTML을 복원한 뒤 페이지 내용을 교체함

한계와 대안

  • 가장 큰 제약은 favicon이 웹사이트 전체를 혼자 실행하지 않는다는 점임
    • favicon에는 웹사이트의 콘텐츠가 들어 있음
    • 디코딩을 위한 작은 JavaScript 로더가 별도로 필요함
    • JavaScript가 없으면 favicon은 웹사이트 콘텐츠를 담은 PNG일 뿐임
  • 실용성은 낮음
    • 저장 가능한 데이터가 매우 작음
    • 페이지가 JavaScript로 부트스트랩되어야 함
    • 작은 HTML 문서를 배포하는 더 나은 방법이 많음
  • 대안으로는 SVG favicon에 markup을 직접 넣기, PNG의 tEXt, zTXt, iTXt comment chunk 사용, 여러 해상도 아이콘을 담을 수 있는 ico 파일 형식 사용이 있음
  • 데모 사이트: https://www.timwehrle.de/labs/favicon-site/
  • 구현 코드: https://github.com/timwehrle/favicon
Read Entire Article