├── requirements.txt
├── example
├── generate.sh
├── horcrux_2.svg
├── horcrux_6.svg
├── horcrux_3.svg
├── horcrux_4.svg
├── horcrux_5.svg
├── horcrux_7.svg
├── horcrux_1.svg
└── horcrux_full.svg
├── README.md
└── horqrux.py
/requirements.txt:
--------------------------------------------------------------------------------
1 | beautifulsoup4
2 | more-itertools
3 | qrcode
4 |
--------------------------------------------------------------------------------
/example/generate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ../horqrux.py "hello hackernews"
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # horQRux
2 |
3 | ### Disclaimer
4 |
5 | This is only a proof of concept, don't use it to protect serious data.
6 |
7 | ### Proof of concept
8 |
9 | By splitting a QR code into 7 fragments, we may physically split and distribute a secret into the real world. For example by printing the QR fragments onto transparent paper and handing them out to multiple people.
10 |
11 |  =  +  +  +  +  +  + 
12 |
--------------------------------------------------------------------------------
/horqrux.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python
2 |
3 | import random
4 | import sys
5 | from copy import copy
6 |
7 | import qrcode
8 | import qrcode.image.svg
9 | from bs4 import BeautifulSoup
10 | from more_itertools import chunked_even
11 |
12 | factory = qrcode.image.svg.SvgFragmentImage
13 | qrcode = qrcode.make(sys.argv[1], image_factory=factory)
14 | svg_string = qrcode.to_string(encoding='unicode')
15 | with open("horcrux_full.svg", 'w') as f:
16 | f.write(svg_string)
17 | svg = BeautifulSoup(svg_string, 'xml')
18 | svg_object = svg.find('svg:svg')
19 |
20 | rects = svg.find_all('svg:rect')
21 | random.shuffle(rects)
22 | horcruxes = chunked_even(rects, len(rects)//6)
23 |
24 | svg_object.clear()
25 |
26 | # write horcruxes to svg files
27 | for idx, horcrux in enumerate(horcruxes):
28 | horcrux_svg = copy(svg_object)
29 | for rect in horcrux:
30 | horcrux_svg.append(rect)
31 | with open(f"horcrux_{idx + 1}.svg", 'w') as f:
32 | f.write(str(horcrux_svg))
33 |
--------------------------------------------------------------------------------
/example/horcrux_2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/horcrux_6.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/horcrux_3.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/horcrux_4.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/horcrux_5.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/horcrux_7.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/horcrux_1.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/horcrux_full.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------