I went ahead and implemented support for decrypting symmetrically
encrypted messages in our 'sq' tool, mostly to get a feeling for how the
% 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  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
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:
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",
Start = auto()
Decrypted = auto()
Deciphered = auto()
Done = auto()
state = State.Start
algo, key = None, None
pp = PacketParser.open(ctx, sys.argv)
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:
state = State.Deciphered
elif state == State.Deciphered:
if tag == Tag.Literal:
body = pp.buffer_unread_content()
state = State.Done
assert state == State.Done
It is structured like the Rust version and I think it looks quite
(To use it, grab the latest Python branch from ).
I have been working on the foreign function interface, aka our C API.
Instead of writing tests for that, I decided to write bindings for
Python and testing that. This also gives me a feel for how complete and
usable the C API is.
And while there is no documentation yet, I have integrated it in our new
build system and I invite you to try it out. Even if you are not into
Python, it is a nice way to interactively play with Sequoia.
To get it, either checkout the 'justus/python-3' branch or clone it
% git clone -b justus/python-3 https://gitlab.com/sequoia-pgp/sequoia.git
In addition to the build dependencies mentioned in 'README.md', you need
python3-dev, python3-cffi (poke me if I missed any additional
dependencies) and ipython3 (only for the nice interactive shell).
Then do 'make', followed by:
% make -Cffi/lang/python shell
IPython 5.5.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
Wow, an interactive Python shell with all of Sequoias functionality
already imported for you and a Context 'ctx' already created for your
convenience is at your fingertips. Let's have some fun:
In : fp = Fingerprint.from_hex("D2F2C5D45BE9FDE6A4EE0AAF31855247603831FD")
In : keyid = fp.keyid()
In : tpk = KeyServer.sks_pool(ctx).get(keyid)
In : assert fp == tpk.fingerprint()
In : st = Store.open(ctx, "my awesome store")
In : st.import_("Justus' signing key", tpk)
Out: <sequoia.openpgp.TPK at 0x7fc5c0142780>
In : binding = st.lookup("Justus' signing key")
In : list(map(str, binding.log()))
Out: ["2018-03-16 13:10:10+00:00: org.sequoia-pgp.tests.interactive:my awesome store: New binding Justus' signing key -> 3185 5247 6038 31FD"]
For more ideas you can look into ffi/lang/python/tests.