59 lines
1.7 KiB
Python
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()
|