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/30604553c08564e27621ce1e022cf…
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
Hello :)
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
using:
% 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
[... stuff...]
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.
In [1]:
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 [1]: fp = Fingerprint.from_hex("D2F2C5D45BE9FDE6A4EE0AAF31855247603831FD")
In [2]: keyid = fp.keyid()
In [3]: tpk = KeyServer.sks_pool(ctx).get(keyid)
In [4]: assert fp == tpk.fingerprint()
In [5]: st = Store.open(ctx, "my awesome store")
In [6]: st.import_("Justus' signing key", tpk)
Out[6]: <sequoia.openpgp.TPK at 0x7fc5c0142780>
In [7]: binding = st.lookup("Justus' signing key")
In [8]: list(map(str, binding.log()))
Out[8]: ["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.
Cheers,
Justus