Hi :)
I went ahead and implemented support for decrypting symmetrically encrypted messages in our 'sq' tool, mostly to get a feeling for how the parser works:
% echo 123456789 | sq decrypt -i openpgp/tests/data/messages/encrypted-aes128-password-123456789.gpg 2>/dev/null | head -n 8 A Cypherpunk's Manifesto by Eric Hughes
Privacy is necessary for an open society in the electronic age. Privacy is not secrecy. A private matter is something one doesn't want the whole world to know, but a secret matter is something one doesn't want anybody to know. Privacy is the power to selectively reveal oneself to the world.
For the curious, here [0] is the code. Note that this code is using the low-level API, we don't expect that every application developer will use this, but 0/ some people might, and b/ currently there is no high-level API.
0: https://gitlab.com/sequoia-pgp/sequoia/commit/30604553c08564e27621ce1e022cfe...
Then I was curious how the parser API would translate to the foreign function interface, so I added just barely enough glue to be able to do the same from C or Python. The Python version looks like this:
import sys import os from getpass import getpass from enum import Enum, auto from sequoia.core import Context, NetworkPolicy from sequoia.openpgp import Tag, PacketParser
ctx = Context("org.sequoia-pgp.tests", network_policy=NetworkPolicy.Offline, ephemeral=True)
class State(Enum): Start = auto() Decrypted = auto() Deciphered = auto() Done = auto()
state = State.Start algo, key = None, None pp = PacketParser.open(ctx, sys.argv[1]) while pp.has_packet: packet = pp.packet tag = packet.tag
if state == State.Start: if tag == Tag.SKESK: passphrase = getpass("Enter passphrase to decrypt message: ") algo, key = packet.match().decrypt(passphrase.encode()) state = State.Decrypted elif tag == Tag.PKESK: sys.stderr.write("Decryption using PKESK not yet supported.\n") elif state == State.Decrypted: if tag == Tag.SEIP: pp.decrypt(algo, key) state = State.Deciphered elif state == State.Deciphered: if tag == Tag.Literal: body = pp.buffer_unread_content() os.write(sys.stdout.fileno(), body) state = State.Done
pp.recurse() assert state == State.Done
It is structured like the Rust version and I think it looks quite reasonable.
(To use it, grab the latest Python branch from [1]).
1: https://gitlab.com/sequoia-pgp/sequoia/tree/justus/python-4
Cheers, Justus