qrcrypt/tool.py

59 lines
1.7 KiB
Python

import os
import secrets
import sys
import compact_xchapoly
import compact_ecdh_curve25519
def keygen():
sk = os.urandom(32)
pk = compact_ecdh_curve25519.pubkey(sk)
return sk, pk
def enc_pk(pk, plaintext):
ephemeral_sk, ephemeral_pk = keygen()
# Based on monocypher's
raw_shared_secret = compact_ecdh_curve25519.ecdh(pk, ephemeral_sk)
shared_secret = compact_xchapoly.hchacha20(raw_shared_secret, b'\x00'*24)
nonce = os.urandom(24)
return ephemeral_pk + nonce + compact_xchapoly.enc(b'', shared_secret, nonce, plaintext)
def dec_sk(sk, ciphertext):
ephemeral_pk = ciphertext[:32]
nonce = ciphertext[32:56]
ciphertext = ciphertext[56:]
raw_shared_secret = compact_ecdh_curve25519.ecdh(ephemeral_pk, sk)
shared_secret = compact_xchapoly.hchacha20(raw_shared_secret, b'\x00'*24)
return compact_xchapoly.dec(b'', shared_secret, nonce, ciphertext)
def usage():
name=os.path.basename(sys.argv[0])
print('Usage: %s -G seckey\n %s -E pubkey\n %s -D seckey' % (name, name, name), file=sys.stderr)
sys.exit(1)
if __name__ == '__main__':
if len(sys.argv) != 3:
usage()
if sys.argv[1] == '-G':
sk, pk = keygen()
with open(sys.argv[2], 'wb') as f:
f.write(sk)
print('pubkey:', pk.hex())
elif sys.argv[1] == '-E':
pk = bytes.fromhex(sys.argv[2])
plaintext = sys.stdin.buffer.read()
sys.stdout.buffer.write(enc_pk(pk, plaintext))
elif sys.argv[1] == '-D':
with open(sys.argv[2], 'rb') as f:
sk = f.read()
ciphertext = sys.stdin.buffer.read()
plaintext = dec_sk(sk, ciphertext)
if plaintext is None:
print('%s: Error: Ciphertext authentication failure' % os.path.basename(sys.argv[0]), file=sys.stderr)
sys.exit(1)
else:
sys.stdout.buffer.write(plaintext)
else:
usage()