ocaml-openpgp
ocaml-openpgp copied to clipboard
WiP: RFC 4880 (OpenPGP) library and utilities in OCaml
OpenPGP library (RFC 4880) 
This library implements rudimentary support for OpenPGP as used with signatures, and has basic support for decryption of messages.
Right now it's a work in progress and should not be used for anything critical to security in a real-world situation.
-
Encryption is being worked on; currently GnuPG won't read our messages (but we can read their messages!).
-
Supporting El-Gamal and elliptic curve keys are out of scope due to lack of support for these in nocrypto.
I could be persuaded to add these if someone can point me to maintained libraries implementing these.
Contributing
Contributions are greatly appreciated!
To prevent duplication/collision of work, please consider leaving a note in the issues section before implementing large changes.
The library and API is still a volatile as it is still being developed.
Suggestions for things to improve:
- Writing more tests, for example for primitives in
types.ml.- Tests for vulnerabilities that have affected other OpenPGP implementations.
- Tests pertaining to diverse/"exotic" keys
- Adding useful debug output, or extending existing pretty-printers with more information.
- Suggestions / signatures for a better API, or scenarios that the library should support.
- CLI commands or arguments (this is one of my first times using
cmdliner- I'm sure things can be improved) - Performance improvements
Building
The library currently depends on the unreleased Usane library for unsigned
arithmetic, and on my unreleased wrappers around Cstruct, called cs.
opam pin add -n usane 'https://github.com/hannesm/usane.git'
opam pin add -n cs 'https://github.com/cfcs/ocaml-cs.git'
opam pin add -n gmap 'https://github.com/hannesm/gmap.git'
opam pin add -n nocrypto -k git 'https://github.com/mirleft/ocaml-nocrypto.git#79d5db2488e338d161d7e170cd681a8120ce07d1'
opam pin add -n mrmime -k git https://github.com/oklm-wsh/MrMime.git
opam install alcotest bos cmdliner cs cstruct fmt fpath gmap hex logs \
nocrypto ptime qcheck rresult usane topkg mrmime
ocaml pkg/pkg.ml build
Roadmap
- Consider support for inline signatures
- ~~GPG-agent protocol~~ the GPG-agent protocol is inherently unsafe for
signing operations. Other projects (
git,qubes,enigmail) seem to implement GnuPG integration by shelling out to thegpgcli. Some limited compatibility with that seems more useful to implement. - Git signing / verification, see section below
- MirageOS version of Qubes split-gpg
Cmdline usage
The library ships with a sample application in app/opgp.ml.
Usage details is available with opgp --help.
Examples of how to use the application are also given there.
It can currently:
opgp genkey: Generate a (DSA | RSA) private key with subkeys for signing+encryptionopgp sign: Produce a detached signature on a fileopgp convert: Derive a public key from a private keyopgp verify: Verify a detached signatureopgp list-packets: List packets contained in armored or binary PGP streamsopgp decrypt: Decrypt messages to RSA keys- Decompress ZIP(RFC1951) and ZLIB messages - BZip2 is still missing
opgp encrypt: Encrypt messages to RSA keysopgp mail-decrypt: Carve out PGP/MIME messages and decrypt them. Currently does not check signatures.
Git / OpenPGP integration
git integrates cryptographic signature creation and verification by
calling out to gpg.
Peter Todd has a nice article about that in the
documentation for his OpenTimeStamps project
(which is a separate project that combines gpg-signatures with
date proofs using append-only logs like BitCoin).
A minimally GnuPG-compatible program opgp-git is provided with
the ocaml-openpgp distribution to replace the use of gpg in this scenario.
- NB: At the moment only verification is supported, and only against a
single public key contained in
~/opgp-git.asc- as thus this is not super useful, but is there as an example, and to remind me to fix the API to support some sort of PKI / key database.
To activate it, you will have to change the gpg.program variable to
point to opgp-git instead of gpg:
$ git config --global gpg.program "$(opam config var openpgp:bin)/opgp-git"
- NOTE that
opgp-gitdoes not implement the full GnuPG command-line interface, it merely implements the handling of the functionality expected bygit, namely["opgp-git", "--verify", "$file", "-"]and["opgp-git", "-bsau", "$key"]. See thegpg.programentry inman git-configfor more details.
Once configured, you can "manually" sign commits at commit-time with
git commit --gpg-sign=KEYID, or you can configure git to do this automatically
(see the commit.gpgSign entry in man git-config for more details).
- To retrieve the purported PGP key for a Github account, you can add
.gpgto the end of their URL. Example: https://github.com/rootkovska.gpg
Resources
The spec is included in this repository in the rfc/ subdirectory.
RFC 4880 - OpenPGP Message Format TODO - IANA registry updates
Alternative implementations
- GnuPG (C, using libgcrypt)
- Keybase PGP (C)
- libsimplepgp (C)
- NetPGP (C)
- pgcrypto (C, from postgresql)
- TinyGPG (C, using libgcrypt)
- CalcCrypto OpenPGP (C++)
- Golang OpenPGP (Go)
- hOpenPGP (Haskell)
- Bouncy Castle (Java)
- Open-Keychain
- Google End-to-End (JavaScript)
- OpenPGP.js (JavaScript)
- Mailvelope OpenPGP.js (JavaScript)
- ObjectivePGP (Objective-C? TODO)
- Crypt::OpenPGP (perl)
- PGPy (Python)
- Bigloo (Scheme?)
- NeoPG (C++/Botan)
- Sequoia-PGP (Rust/libnettle)
- pbp "pretty bad protocol" (Rust/libdalek)
- see also the author's git commit signing tool