|
| 1 | +import hmac, hashlib, subprocess |
| 2 | +import gnupg |
| 3 | +import config |
| 4 | + |
| 5 | +BITS_IN_RANDOM_ID = 256 |
| 6 | +HASH_FUNCTION = hashlib.sha256 |
| 7 | +GPG_KEY_TYPE = "RSA" |
| 8 | +GPG_KEY_LENGTH = "4096" |
| 9 | + |
| 10 | +def genrandomid(): |
| 11 | + return hex(random.getrandbits(BITS_IN_RANDOM_ID))[2:-1] |
| 12 | + |
| 13 | +def shash(s): |
| 14 | + """ |
| 15 | + >>> shash('Hello, world!') |
| 16 | + '98015b0fbf815a630cbcda94b809d207490d7cc2c5c02cb33a242acfd5b73cc1' |
| 17 | + """ |
| 18 | + return hmac.HMAC(config.HMAC_SECRET, s, HASH_FUNCTION).hexdigest() |
| 19 | + |
| 20 | +gpg = gnupg.GPG(gnupghome=config.GPG_KEY_DIR) |
| 21 | + |
| 22 | +def genkeypair(name, secret): |
| 23 | + """ |
| 24 | + >>> if not gpg.list_keys(shash('randomid')): |
| 25 | + ... genkeypair(shash('randomid'), 'randomid').type |
| 26 | + ... else: |
| 27 | + ... u'P' |
| 28 | + u'P' |
| 29 | + """ |
| 30 | + return gpg.gen_key(gpg.gen_key_input( |
| 31 | + key_type=GPG_KEY_TYPE, key_length=GPG_KEY_LENGTH, |
| 32 | + passphrase=secret, |
| 33 | + name_email="%s@wireleaks.example.com" % name |
| 34 | + )) |
| 35 | + |
| 36 | +def encrypt(name, s): |
| 37 | + """ |
| 38 | + >>> encrypt(shash('randomid'), "Goodbye, cruel world!")[:75] |
| 39 | + '-----BEGIN PGP MESSAGE-----\\nVersion: GnuPG v1.4.9 (Darwin)\\n\\nhQIMA3rf0hDNFTT' |
| 40 | + """ |
| 41 | + fp = gpg.list_keys(name)[0]['fingerprint'] |
| 42 | + if isinstance(s, unicode): |
| 43 | + s = s.encode('utf8') |
| 44 | + if isinstance(s, str): |
| 45 | + out = gpg.encrypt(s, [fp]) |
| 46 | + else: |
| 47 | + out = gpg.encrypt_file(s, [fp]) |
| 48 | + return out.data |
| 49 | + |
| 50 | +def decrypt(name, secret, s): |
| 51 | + """ |
| 52 | + >>> decrypt(shash('randomid'), 'randomid', |
| 53 | + ... encrypt(shash('randomid'), 'Goodbye, cruel world!') |
| 54 | + ... ) |
| 55 | + 'Goodbye, cruel world!' |
| 56 | + """ |
| 57 | + return gpg.decrypt(s, passphrase=secret).data |
| 58 | + |
| 59 | +def secureunlink(fn): |
| 60 | + return subprocess.check_call(['srm', fn]) |
| 61 | + |
| 62 | +if __name__ == "__main__": |
| 63 | + import doctest |
| 64 | + doctest.testmod() |
0 commit comments