Bug 1621782 - Import RNP sources into comm-central. r=kaie
authorRob Lemley <rob@thunderbird.net>
Tue, 14 Apr 2020 22:28:53 +0000
changeset 37949 01043748e1e0d2792f8a4d1bf26038ddd82d054c
parent 37948 5bda64d96f5f88cd886bb7064c5108ca04403280
child 37950 ca5a694350fbe0f89b46a23caafb8ebf39363257
push id2595
push userclokep@gmail.com
push dateMon, 04 May 2020 19:02:04 +0000
treeherdercomm-beta@f53913797371 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskaie
bugs1621782
Bug 1621782 - Import RNP sources into comm-central. r=kaie Modifications are documented in README.rnp and update-rnp.sh Differential Revision: https://phabricator.services.mozilla.com/D70738
build/virtualenv_packages.txt
python/thirdroc/setup.py
python/thirdroc/thirdroc/__init__.py
python/thirdroc/thirdroc/__main__.py
python/thirdroc/thirdroc/rnp.py
third_party/README.rnp
third_party/rnp/LICENSE-OCB.md
third_party/rnp/LICENSE.md
third_party/rnp/README.adoc
third_party/rnp/doc/tests/README.md
third_party/rnp/doc/tests/rnpkeys-generate-key.md
third_party/rnp/docs/c-usage.adoc
third_party/rnp/docs/cli-usage.adoc
third_party/rnp/docs/develop.adoc
third_party/rnp/docs/develop/cpp-usage.adoc
third_party/rnp/docs/develop/packaging.adoc
third_party/rnp/docs/develop/release-workflow.adoc
third_party/rnp/docs/installation.adoc
third_party/rnp/docs/navigation.adoc
third_party/rnp/include/rekey/rnp_key_store.h
third_party/rnp/include/repgp/repgp_def.h
third_party/rnp/include/rnp.h
third_party/rnp/include/rnp/rnp.h
third_party/rnp/include/rnp/rnp_def.h
third_party/rnp/include/rnp/rnp_err.h
third_party/rnp/include/rnp/rnp_sdk.h
third_party/rnp/src/examples/CMakeLists.txt
third_party/rnp/src/examples/README.md
third_party/rnp/src/examples/decrypt.c
third_party/rnp/src/examples/dump.c
third_party/rnp/src/examples/encrypt.c
third_party/rnp/src/examples/generate.c
third_party/rnp/src/examples/sign.c
third_party/rnp/src/examples/verify.c
third_party/rnp/src/fuzzing/fuzz_keys.c
third_party/rnp/src/lib/CMakeLists.txt
third_party/rnp/src/lib/config.h.in
third_party/rnp/src/lib/crypto.cpp
third_party/rnp/src/lib/crypto.h
third_party/rnp/src/lib/crypto/bn.cpp
third_party/rnp/src/lib/crypto/bn.h
third_party/rnp/src/lib/crypto/common.h
third_party/rnp/src/lib/crypto/dsa.cpp
third_party/rnp/src/lib/crypto/dsa.h
third_party/rnp/src/lib/crypto/ec.cpp
third_party/rnp/src/lib/crypto/ec.h
third_party/rnp/src/lib/crypto/ecdh.cpp
third_party/rnp/src/lib/crypto/ecdh.h
third_party/rnp/src/lib/crypto/ecdsa.cpp
third_party/rnp/src/lib/crypto/ecdsa.h
third_party/rnp/src/lib/crypto/eddsa.cpp
third_party/rnp/src/lib/crypto/eddsa.h
third_party/rnp/src/lib/crypto/elgamal.cpp
third_party/rnp/src/lib/crypto/elgamal.h
third_party/rnp/src/lib/crypto/hash.cpp
third_party/rnp/src/lib/crypto/hash.h
third_party/rnp/src/lib/crypto/mpi.cpp
third_party/rnp/src/lib/crypto/mpi.h
third_party/rnp/src/lib/crypto/rng.cpp
third_party/rnp/src/lib/crypto/rng.h
third_party/rnp/src/lib/crypto/rsa.cpp
third_party/rnp/src/lib/crypto/rsa.h
third_party/rnp/src/lib/crypto/s2k.cpp
third_party/rnp/src/lib/crypto/s2k.h
third_party/rnp/src/lib/crypto/signatures.cpp
third_party/rnp/src/lib/crypto/signatures.h
third_party/rnp/src/lib/crypto/sm2.cpp
third_party/rnp/src/lib/crypto/sm2.h
third_party/rnp/src/lib/crypto/symmetric.cpp
third_party/rnp/src/lib/crypto/symmetric.h
third_party/rnp/src/lib/defaults.h
third_party/rnp/src/lib/ffi-priv-types.h
third_party/rnp/src/lib/fingerprint.cpp
third_party/rnp/src/lib/fingerprint.h
third_party/rnp/src/lib/generate-key.cpp
third_party/rnp/src/lib/json_utils.h
third_party/rnp/src/lib/key-provider.cpp
third_party/rnp/src/lib/key-provider.h
third_party/rnp/src/lib/librnp.3
third_party/rnp/src/lib/list.cpp
third_party/rnp/src/lib/list.h
third_party/rnp/src/lib/misc.cpp
third_party/rnp/src/lib/pass-provider.cpp
third_party/rnp/src/lib/pass-provider.h
third_party/rnp/src/lib/pgp-key.cpp
third_party/rnp/src/lib/pgp-key.h
third_party/rnp/src/lib/rnp.cpp
third_party/rnp/src/lib/types.h
third_party/rnp/src/lib/utils.h
third_party/rnp/src/lib/version.h
third_party/rnp/src/lib/version.h.in
third_party/rnp/src/librekey/key_store_g10.cpp
third_party/rnp/src/librekey/key_store_g10.h
third_party/rnp/src/librekey/key_store_kbx.cpp
third_party/rnp/src/librekey/key_store_kbx.h
third_party/rnp/src/librekey/key_store_pgp.cpp
third_party/rnp/src/librekey/key_store_pgp.h
third_party/rnp/src/librekey/rnp_key_store.cpp
third_party/rnp/src/librepgp/stream-armor.cpp
third_party/rnp/src/librepgp/stream-armor.h
third_party/rnp/src/librepgp/stream-common.cpp
third_party/rnp/src/librepgp/stream-common.h
third_party/rnp/src/librepgp/stream-ctx.cpp
third_party/rnp/src/librepgp/stream-ctx.h
third_party/rnp/src/librepgp/stream-def.h
third_party/rnp/src/librepgp/stream-dump.cpp
third_party/rnp/src/librepgp/stream-dump.h
third_party/rnp/src/librepgp/stream-key.cpp
third_party/rnp/src/librepgp/stream-key.h
third_party/rnp/src/librepgp/stream-packet.cpp
third_party/rnp/src/librepgp/stream-packet.h
third_party/rnp/src/librepgp/stream-parse.cpp
third_party/rnp/src/librepgp/stream-parse.h
third_party/rnp/src/librepgp/stream-sig.cpp
third_party/rnp/src/librepgp/stream-sig.h
third_party/rnp/src/librepgp/stream-write.cpp
third_party/rnp/src/librepgp/stream-write.h
third_party/rnp/src/rnp/CMakeLists.txt
third_party/rnp/src/rnp/fficli.cpp
third_party/rnp/src/rnp/fficli.h
third_party/rnp/src/rnp/rnp.1
third_party/rnp/src/rnp/rnp.cpp
third_party/rnp/src/rnp/rnpcfg.cpp
third_party/rnp/src/rnp/rnpcfg.h
third_party/rnp/src/rnpkeys/CMakeLists.txt
third_party/rnp/src/rnpkeys/main.cpp
third_party/rnp/src/rnpkeys/rnpkeys.1
third_party/rnp/src/rnpkeys/rnpkeys.cpp
third_party/rnp/src/rnpkeys/rnpkeys.h
third_party/rnp/src/rnpkeys/tui.cpp
third_party/rnp/src/tests/CMakeLists.txt
third_party/rnp/src/tests/cipher.cpp
third_party/rnp/src/tests/cli.cpp
third_party/rnp/src/tests/cli_common.py
third_party/rnp/src/tests/cli_perf.py
third_party/rnp/src/tests/cli_tests.py
third_party/rnp/src/tests/data/.keepme
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_1024-sec.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_1024.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_2048-sec.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1024_2048.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1234_1234-sec.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_1234_1234.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2048_2048-sec.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2048_2048.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2112_2112-sec.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_2112_2112.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_3072_3072-sec.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_dsa_elgamal_3072_3072.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_1024_1024-sec.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_1024_1024.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_2048_2048-sec.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_2048_2048.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_3072_3072-sec.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_3072_3072.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_4096_4096-sec.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/GnuPG_rsa_4096_4096.gpg
third_party/rnp/src/tests/data/cli_EncryptSign/regenerate_keys
third_party/rnp/src/tests/data/keyrings/1/info.txt
third_party/rnp/src/tests/data/keyrings/1/pubring.gpg
third_party/rnp/src/tests/data/keyrings/1/secring.gpg
third_party/rnp/src/tests/data/keyrings/2/info.txt
third_party/rnp/src/tests/data/keyrings/2/pubring.gpg
third_party/rnp/src/tests/data/keyrings/2/secring.gpg
third_party/rnp/src/tests/data/keyrings/3/info.txt
third_party/rnp/src/tests/data/keyrings/3/private-keys-v1.d/63E59092E4B1AE9F8E675B2F98AA2B8BD9F4EA59.key
third_party/rnp/src/tests/data/keyrings/3/private-keys-v1.d/7EAB41A2F46257C36F2892696F5A2F0432499AD3.key
third_party/rnp/src/tests/data/keyrings/3/pubring.kbx
third_party/rnp/src/tests/data/keyrings/4/info.txt
third_party/rnp/src/tests/data/keyrings/4/pubring.pgp
third_party/rnp/src/tests/data/keyrings/4/rsav3-p.asc
third_party/rnp/src/tests/data/keyrings/4/rsav3-s.asc
third_party/rnp/src/tests/data/keyrings/4/secring.pgp
third_party/rnp/src/tests/data/keyrings/5/pubring.gpg
third_party/rnp/src/tests/data/keyrings/5/secring.gpg
third_party/rnp/src/tests/data/test_cli/hello.txt
third_party/rnp/src/tests/data/test_cli_g10_defkey/g10/private-keys-v1.d/A56DC8DB8355747A809037459B4258B8A743EAB5.key
third_party/rnp/src/tests/data/test_cli_g10_defkey/g10/private-keys-v1.d/FC81AECE90BCE6E54D0D637D266109783AC8DAC0.key
third_party/rnp/src/tests/data/test_cli_g10_defkey/g10/pubring.kbx
third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys
third_party/rnp/src/tests/data/test_cli_rnpkeys/g10_list_keys_sec
third_party/rnp/src/tests/data/test_cli_rnpkeys/getkey_00000000
third_party/rnp/src/tests/data/test_cli_rnpkeys/getkey_2fcadf05ffa501bb
third_party/rnp/src/tests/data/test_cli_rnpkeys/getkey_2fcadf05ffa501bb_sec
third_party/rnp/src/tests/data/test_cli_rnpkeys/getkey_2fcadf05ffa501bb_sig
third_party/rnp/src/tests/data/test_cli_rnpkeys/getkey_zzzzzzzz
third_party/rnp/src/tests/data/test_cli_rnpkeys/keyring_1_list_keys
third_party/rnp/src/tests/data/test_cli_rnpkeys/keyring_1_list_keys_sec
third_party/rnp/src/tests/data/test_cli_rnpkeys/keyring_1_list_sigs
third_party/rnp/src/tests/data/test_cli_rnpkeys/keyring_1_list_sigs_sec
third_party/rnp/src/tests/data/test_cli_rnpkeys/keyring_2_list_keys
third_party/rnp/src/tests/data/test_cli_rnpkeys/keyring_2_list_sigs
third_party/rnp/src/tests/data/test_cli_rnpkeys/keyring_3_list_keys
third_party/rnp/src/tests/data/test_cli_rnpkeys/keyring_3_list_sigs
third_party/rnp/src/tests/data/test_cli_rnpkeys/keyring_5_list_keys
third_party/rnp/src/tests/data/test_cli_rnpkeys/keyring_5_list_sigs
third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_keys
third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_keys_sec
third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_sigs
third_party/rnp/src/tests/data/test_cli_rnpkeys/test_stream_key_load_sigs_sec
third_party/rnp/src/tests/data/test_ffi_json/generate-pair-dsa-elg.json
third_party/rnp/src/tests/data/test_ffi_json/generate-pair.json
third_party/rnp/src/tests/data/test_ffi_json/generate-primary.json
third_party/rnp/src/tests/data/test_ffi_json/generate-sub.json
third_party/rnp/src/tests/data/test_forged_keys/dsa-eg-pub-forged-key.pgp
third_party/rnp/src/tests/data/test_forged_keys/dsa-eg-pub-forged-material.pgp
third_party/rnp/src/tests/data/test_forged_keys/dsa-eg-pub-forged-subkey.pgp
third_party/rnp/src/tests/data/test_forged_keys/dsa-eg-pub.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-25519-pub-forged-key.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-25519-pub-forged-material.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-25519-pub-future-cert.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-25519-pub.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-p256-pub-expired-key.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-p256-pub-expired-subkey.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-p256-pub-forged-key.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-p256-pub-forged-material.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-p256-pub-forged-subkey.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-p256-pub-no-binding.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-p256-pub-no-certification.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-p256-pub.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-p256-sec-expired-key.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-p256-sec-expired-subkey.pgp
third_party/rnp/src/tests/data/test_forged_keys/ecc-p256-sec.pgp
third_party/rnp/src/tests/data/test_forged_keys/rsa-rsa-pub-forged-key.pgp
third_party/rnp/src/tests/data/test_forged_keys/rsa-rsa-pub-forged-material.pgp
third_party/rnp/src/tests/data/test_forged_keys/rsa-rsa-pub-forged-subkey.pgp
third_party/rnp/src/tests/data/test_forged_keys/rsa-rsa-pub-future-key.pgp
third_party/rnp/src/tests/data/test_forged_keys/rsa-rsa-pub.pgp
third_party/rnp/src/tests/data/test_forged_keys/rsa-rsa-sec-future-key.pgp
third_party/rnp/src/tests/data/test_forged_keys/rsa-rsa-sec.pgp
third_party/rnp/src/tests/data/test_key_validity/CMakeLists.txt
third_party/rnp/src/tests/data/test_key_validity/alice-cert.pgp
third_party/rnp/src/tests/data/test_key_validity/alice-pub.asc
third_party/rnp/src/tests/data/test_key_validity/alice-rev.pgp
third_party/rnp/src/tests/data/test_key_validity/alice-revoker-sig.asc
third_party/rnp/src/tests/data/test_key_validity/alice-revoker-sig.pgp
third_party/rnp/src/tests/data/test_key_validity/alice-revoker.pgp
third_party/rnp/src/tests/data/test_key_validity/alice-sec.asc
third_party/rnp/src/tests/data/test_key_validity/alice-sigs-malf.pgp
third_party/rnp/src/tests/data/test_key_validity/alice-sigs.asc
third_party/rnp/src/tests/data/test_key_validity/alice-sigs.pgp
third_party/rnp/src/tests/data/test_key_validity/alice-sub-pub.pgp
third_party/rnp/src/tests/data/test_key_validity/alice-sub-sec.pgp
third_party/rnp/src/tests/data/test_key_validity/basil-pub.asc
third_party/rnp/src/tests/data/test_key_validity/basil-sec.asc
third_party/rnp/src/tests/data/test_key_validity/case1/pubring.gpg
third_party/rnp/src/tests/data/test_key_validity/case2/pubring.gpg
third_party/rnp/src/tests/data/test_key_validity/case3/pubring.gpg
third_party/rnp/src/tests/data/test_key_validity/case4/pubring.gpg
third_party/rnp/src/tests/data/test_key_validity/case5/CMakeLists.txt
third_party/rnp/src/tests/data/test_key_validity/case5/generate.cpp
third_party/rnp/src/tests/data/test_key_validity/case5/pubring.gpg
third_party/rnp/src/tests/data/test_key_validity/case6/pubring.gpg
third_party/rnp/src/tests/data/test_key_validity/case7/pubring.gpg
third_party/rnp/src/tests/data/test_key_validity/cases.txt
third_party/rnp/src/tests/data/test_key_validity/claus-pub.asc
third_party/rnp/src/tests/data/test_key_validity/claus-sec.asc
third_party/rnp/src/tests/data/test_large_MPIs/message.enc.rsa16384.pgp
third_party/rnp/src/tests/data/test_large_MPIs/message.enc.rsa16385.pgp
third_party/rnp/src/tests/data/test_large_MPIs/rsa-priv-16384bits.pgp
third_party/rnp/src/tests/data/test_large_MPIs/rsa-priv-16385bits.pgp
third_party/rnp/src/tests/data/test_large_MPIs/rsa-pub-16384bits.pgp
third_party/rnp/src/tests/data/test_large_MPIs/rsa-pub-16385bits.pgp
third_party/rnp/src/tests/data/test_large_MPIs/rsa-pub-65535bits.pgp
third_party/rnp/src/tests/data/test_large_MPIs/rsa-pub-65535bits.pgp.16385sig.sig
third_party/rnp/src/tests/data/test_large_MPIs/rsa-pub-65535bits.pgp.sig
third_party/rnp/src/tests/data/test_large_packet/4g.bzip2.gpg
third_party/rnp/src/tests/data/test_list_packets/ecc-p256-pub.asc
third_party/rnp/src/tests/data/test_list_packets/list_all.txt
third_party/rnp/src/tests/data/test_list_packets/list_grips.txt
third_party/rnp/src/tests/data/test_list_packets/list_json.txt
third_party/rnp/src/tests/data/test_list_packets/list_json_all.txt
third_party/rnp/src/tests/data/test_list_packets/list_json_grips.txt
third_party/rnp/src/tests/data/test_list_packets/list_json_mpi.txt
third_party/rnp/src/tests/data/test_list_packets/list_json_raw.txt
third_party/rnp/src/tests/data/test_list_packets/list_mpi.txt
third_party/rnp/src/tests/data/test_list_packets/list_raw.txt
third_party/rnp/src/tests/data/test_list_packets/list_standard.txt
third_party/rnp/src/tests/data/test_messages/message.sig.asc.malf
third_party/rnp/src/tests/data/test_messages/message.txt
third_party/rnp/src/tests/data/test_messages/message.txt.cleartext-malf
third_party/rnp/src/tests/data/test_messages/message.txt.cleartext-nosig
third_party/rnp/src/tests/data/test_messages/message.txt.cleartext-signed
third_party/rnp/src/tests/data/test_messages/message.txt.encrypted
third_party/rnp/src/tests/data/test_messages/message.txt.sig
third_party/rnp/src/tests/data/test_messages/message.txt.sig.malf
third_party/rnp/src/tests/data/test_messages/message.txt.sig.wrong-mpi-bitlen
third_party/rnp/src/tests/data/test_messages/message.txt.signed
third_party/rnp/src/tests/data/test_messages/message.txt.signed-encrypted
third_party/rnp/src/tests/data/test_messages/message.txt.signed.invsig
third_party/rnp/src/tests/data/test_messages/message.txt.signed.malfsig
third_party/rnp/src/tests/data/test_messages/message.txt.signed.nosig
third_party/rnp/src/tests/data/test_messages/message.txt.signed.unknown
third_party/rnp/src/tests/data/test_partial_length/message.txt.partial-1g
third_party/rnp/src/tests/data/test_partial_length/message.txt.partial-256
third_party/rnp/src/tests/data/test_partial_length/message.txt.partial-signed
third_party/rnp/src/tests/data/test_partial_length/message.txt.partial-zero-last
third_party/rnp/src/tests/data/test_partial_length/pubring.gpg.partial
third_party/rnp/src/tests/data/test_repgp/encrypted_key.gpg
third_party/rnp/src/tests/data/test_repgp/encrypted_text.gpg
third_party/rnp/src/tests/data/test_repgp/signed.gpg
third_party/rnp/src/tests/data/test_stream_armor/extra_line_before_trailer.asc
third_party/rnp/src/tests/data/test_stream_key_load/dsa-eg-pub.asc
third_party/rnp/src/tests/data/test_stream_key_load/dsa-eg-sec.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-25519-photo-pub.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-25519-pub.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-25519-sec.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-bp256-pub.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-bp256-sec.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-bp384-pub.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-bp384-sec.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-bp512-pub.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-bp512-sec.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-p256-pub.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-p256-revoked-key.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-p256-revoked-sub.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-p256-revoked-uid.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-p256-sec.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-p256k1-pub.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-p256k1-sec.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-p384-pub.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-p384-sec.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-p521-pub.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-p521-sec.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-x25519-pub.asc
third_party/rnp/src/tests/data/test_stream_key_load/ecc-x25519-sec.asc
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/2F25DB025DEBF3EA2715350209B985829B04F50A.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/48FFED40D018747363BDEFFDD404D1F4870F8064.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/498B89C485489BA16B40755C0EBA580166393074.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/552286BEB2999F0A9E26A50385B90D9724001187.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/5A484F56AB4B8B6583B6365034999F6543FAE1AE.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/636C983EDB558527BA82780B52CB5DAE011BE46B.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/797A83FE041FFE06A7F4B1D32C6F4AE0F6D87ADF.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/9133E4A7E8FC8515518DF444C3F2F247EEBBADEC.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/940D97D75C306D737A59A98EAFF1272832CEDC0B.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/A01BAA22A72F09A0FF0A1D4CBCE70844DD52DDD7.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/A1338230AED1C9C125663518470B49056C9D1733.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/A56DC8DB8355747A809037459B4258B8A743EAB5.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/A5E4CD2CBBE44A16E4D6EC05C2E3C3A599DC763C.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/A77DC8173DA6BEE126F5BD6F5A14E01200B52FCE.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/B6BD8B81F75AF914163D97DF8DE8F6FC64C283F8.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/C1678B7DE5F144C93B89468D5F9764ACE182ED36.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/CED7034A8EB5F4CE90DF99147EC33D86FCD3296C.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/D148210FAF36468055B83D0F5A6DEB83FBC8E864.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/D91B789603EC9138AA20342A2B6DC86C81B70F5D.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/FC81AECE90BCE6E54D0D637D266109783AC8DAC0.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/private-keys-v1.d/FD048B2CA1919CB241DC8A2C7FA3E742EF343DCA.key
third_party/rnp/src/tests/data/test_stream_key_load/g10/pubring.kbx
third_party/rnp/src/tests/data/test_stream_key_load/rsa-rsa-pub.asc
third_party/rnp/src/tests/data/test_stream_key_load/rsa-rsa-sec.asc
third_party/rnp/src/tests/data/test_stream_key_merge/key-both.asc
third_party/rnp/src/tests/data/test_stream_key_merge/key-pub-just-key.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-pub-just-subkey-1.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-pub-just-subkey-2-no-sigs.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-pub-just-subkey-2.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-pub-no-key-subkey-1.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-pub-subkey-1-no-sigs.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-pub-subkey-1.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-pub-subkey-2.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-pub-uid-1-no-sigs.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-pub-uid-1.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-pub-uid-2.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-pub.asc
third_party/rnp/src/tests/data/test_stream_key_merge/key-pub.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-sec-just-subkey-1.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-sec-just-subkey-2-no-sigs.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-sec-no-uid-no-sigs.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-sec-uid-1-subkey-1.pgp
third_party/rnp/src/tests/data/test_stream_key_merge/key-sec.asc
third_party/rnp/src/tests/data/test_stream_key_merge/key-sec.pgp
third_party/rnp/src/tests/data/test_stream_signatures/pub.asc
third_party/rnp/src/tests/data/test_stream_signatures/revoked-key-sig.gpg
third_party/rnp/src/tests/data/test_stream_signatures/sec.asc
third_party/rnp/src/tests/data/test_stream_signatures/source.txt
third_party/rnp/src/tests/data/test_stream_signatures/source.txt.asc
third_party/rnp/src/tests/data/test_stream_signatures/source.txt.asc.asc
third_party/rnp/src/tests/data/test_stream_signatures/source.txt.sig
third_party/rnp/src/tests/data/test_stream_signatures/source.txt.sig.asc
third_party/rnp/src/tests/data/test_stream_signatures/source_forged.txt
third_party/rnp/src/tests/data/test_stream_verification/verify_encrypted_no_key.pgp
third_party/rnp/src/tests/data/test_stream_z/128mb.zip
third_party/rnp/src/tests/data/test_stream_z/128mb.zip.cut
third_party/rnp/src/tests/data/test_stream_z/128mb.zlib
third_party/rnp/src/tests/data/test_stream_z/128mb.zlib.cut
third_party/rnp/src/tests/data/test_stream_z/4gb.bzip2
third_party/rnp/src/tests/data/test_stream_z/4gb.bzip2.asc
third_party/rnp/src/tests/data/test_stream_z/4gb.bzip2.cut
third_party/rnp/src/tests/data/test_validate_key_material/dsa-eg-pub.pgp
third_party/rnp/src/tests/data/test_validate_key_material/dsa-eg-sec.pgp
third_party/rnp/src/tests/data/test_validate_key_material/dsa-pub.pgp
third_party/rnp/src/tests/data/test_validate_key_material/dsa-sec.pgp
third_party/rnp/src/tests/data/test_validate_key_material/ecdh-p256-sec.pgp
third_party/rnp/src/tests/data/test_validate_key_material/ecdsa-p256-sec.pgp
third_party/rnp/src/tests/data/test_validate_key_material/ed25519-sec.pgp
third_party/rnp/src/tests/data/test_validate_key_material/eg-pub.pgp
third_party/rnp/src/tests/data/test_validate_key_material/eg-sec.pgp
third_party/rnp/src/tests/data/test_validate_key_material/rsa-pub.pgp
third_party/rnp/src/tests/data/test_validate_key_material/rsa-sec.pgp
third_party/rnp/src/tests/data/test_validate_key_material/rsa-ssb.pgp
third_party/rnp/src/tests/data/test_validate_key_material/rsa-sub.pgp
third_party/rnp/src/tests/data/test_validate_key_material/x25519-sec.pgp
third_party/rnp/src/tests/exportkey.cpp
third_party/rnp/src/tests/ffi.cpp
third_party/rnp/src/tests/generatekey.cpp
third_party/rnp/src/tests/gnupg.py
third_party/rnp/src/tests/gtest-CMakeLists.txt.in
third_party/rnp/src/tests/issues/1030.cpp
third_party/rnp/src/tests/kbx-nsigs-test.cpp
third_party/rnp/src/tests/key-add-userid.cpp
third_party/rnp/src/tests/key-grip.cpp
third_party/rnp/src/tests/key-prefs.cpp
third_party/rnp/src/tests/key-protect.cpp
third_party/rnp/src/tests/key-store-search.cpp
third_party/rnp/src/tests/key-unlock.cpp
third_party/rnp/src/tests/key-validate.cpp
third_party/rnp/src/tests/large-mpi.cpp
third_party/rnp/src/tests/large-packet.cpp
third_party/rnp/src/tests/load-g10.cpp
third_party/rnp/src/tests/load-pgp.cpp
third_party/rnp/src/tests/partial-length.cpp
third_party/rnp/src/tests/rnp.py
third_party/rnp/src/tests/rnp_tests.cpp
third_party/rnp/src/tests/rnp_tests.h
third_party/rnp/src/tests/s2k-iterations.cpp
third_party/rnp/src/tests/streams.cpp
third_party/rnp/src/tests/support.cpp
third_party/rnp/src/tests/support.h
third_party/rnp/src/tests/user-prefs.cpp
third_party/rnp/src/tests/utils-list.cpp
third_party/rnp/src/tests/utils-rnpcfg.cpp
third_party/update_rnp.sh
--- a/build/virtualenv_packages.txt
+++ b/build/virtualenv_packages.txt
@@ -1,1 +1,2 @@
 comm.pth:comm/testing/marionette
+comm.pth:comm/python/thirdroc
new file mode 100644
--- /dev/null
+++ b/python/thirdroc/setup.py
@@ -0,0 +1,26 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import
+
+from setuptools import setup, find_packages
+
+VERSION = '0.1'
+
+setup(
+    author='MZLA Technologies',
+    author_email='MZLA Technologies Release Engineering',
+    name='thirdroc',
+    description='Utility for maintaining third party source code in Thunderbird',
+    license='MPL 2.0',
+    packages=find_packages(),
+    version=VERSION,
+    classifiers=[
+        'Development Status :: 3 - Alpha',
+        'Topic :: Software Development :: Build Tools',
+        'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
+        'Programming Language :: Python :: 3.6',
+        'Programming Language :: Python :: Implementation :: CPython',
+    ],
+)
new file mode 100644
--- /dev/null
+++ b/python/thirdroc/thirdroc/__init__.py
@@ -0,0 +1,38 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import
+
+import re
+from distutils.version import StrictVersion
+
+VTAG_RE = re.compile(r"^v\d+\.\d+\.\d+$")
+
+
+def tag2version(tag):
+    """
+    Convert a tag of form v0.0.0 to a version string
+    :param string tag:
+    :return string:
+    """
+    if VTAG_RE.match(tag):
+        return tag[1:]
+    else:
+        raise Exception("Invalid tag {}".format(tag))
+
+
+def get_latest_version(*versions):
+    """
+    Given a list of versions (that must parse with distutils.version.StrictVersion,
+    return the latest/newest version.
+    :param list versions:
+    :return StrictVersion:
+    """
+    version_list = [StrictVersion(tag2version(v)) for v in versions]
+    version_list.sort()
+    return version_list[-1]
+
+
+def latest_version(*versions):
+    print(get_latest_version(*versions))
new file mode 100644
--- /dev/null
+++ b/python/thirdroc/thirdroc/__main__.py
@@ -0,0 +1,26 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import
+
+import sys
+
+from . import latest_version
+from .rnp import rnp_source_update
+
+FUNC_MAP = {
+    'latest_version': latest_version,
+    'rnp_source_update': rnp_source_update,
+}
+
+
+def main(args):
+    _func = args[1]
+    if _func in FUNC_MAP:
+        FUNC_MAP[_func](*args[2:])
+    else:
+        raise Exception("Unknown function: {}".format(args[0]))
+
+
+main(sys.argv)
new file mode 100644
--- /dev/null
+++ b/python/thirdroc/thirdroc/rnp.py
@@ -0,0 +1,124 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import
+
+import os
+try:
+    import cStringIO as StringIO
+except ImportError:
+    import StringIO
+from datetime import date
+import re
+from distutils.version import StrictVersion
+
+from mozbuild.preprocessor import Preprocessor
+
+
+def rnp_source_update(rnp_root, version_str, revision, timestamp, bug_report):
+    """
+    Update RNP source files: generate version.h and mangle config.h.in
+    :param rnp_root:
+    :type rnp_root:
+    :param string version_str: latest version
+    :param string revision: revision hash (short form)
+    :param float timestamp: UNIX timestamp from revision
+    :param string bug_report: where to report bugs for this RNP build
+    """
+    version = StrictVersion(version_str)
+    version_major = version.version[0]
+    version_minor = version.version[1]
+    version_patch = version.version[2]
+    date_str = date.fromtimestamp(float(timestamp)).strftime("%Y%m%d")
+    revision_short = revision[:8]
+    version_full = '{}+git{}.{}.MZLA'.format(version_str, date_str, revision_short)
+
+    defines = dict(
+        RNP_VERSION_MAJOR=version_major,
+        RNP_VERSION_MINOR=version_minor,
+        RNP_VERSION_PATCH=version_patch,
+        RNP_VERSION=version_str,
+        RNP_VERSION_FULL=version_full,
+        RNP_VERSION_COMMIT_TIMESTAMP=str(timestamp),
+        BUGREPORT_EMAIL=bug_report
+    )
+    src_lib = os.path.join(rnp_root, 'src', 'lib')
+    version_h_in = os.path.join(src_lib, 'version.h.in')
+    version_h = os.path.join(src_lib, 'version.h')
+    config_h_in = os.path.join(src_lib, 'config.h.in')
+    readme_rnp = os.path.join(rnp_root, '..', 'README.rnp')
+
+    generate_version_h(version_h_in, version_h, defines)
+    mangle_config_h_in(config_h_in, defines)
+    update_readme(readme_rnp, revision)
+
+
+def rnp_preprocess(tmpl, dest, defines):
+    """
+    Generic preprocessing
+    :param BinaryIO tmpl: open filehandle (read) input
+    :param BinaryIO dest: open filehandle (write) output
+    :param dict defines: result of get_defines()
+    :return boolean:
+    """
+    pp = Preprocessor()
+    pp.setMarker('%')
+    pp.addDefines(defines)
+    pp.do_filter('substitution')
+    pp.out = dest
+    pp.do_include(tmpl, True)
+    return True
+
+
+def generate_version_h(template, destination, defines):
+    """
+    Generate version.h for rnp from a the template file, write the
+    result to destination.
+    :param string template: path to template file (version.h.in)
+    :param string destination: path to write generated file (version.h)
+    :param dict defines: result of get_defines()
+    """
+    with open(template) as tmpl:
+        with open(destination, 'w') as dest:
+            rnp_preprocess(tmpl, dest, defines)
+
+
+def mangle_config_h_in(template, defines):
+    """
+    Mangle RNP's config.h.in so that it will work with CONFIGURE_DEFINE_FILES
+    :param string template: path to config.h.in
+    :param dict defines: result of get_defines()
+    """
+    with open(template) as tmpl:
+        tmp_string = StringIO.StringIO()
+        rnp_preprocess(tmpl, tmp_string, defines)
+
+    tmp_string.seek(0)
+
+    with open(template, 'w') as dest:
+        for line in tmp_string:
+            if line.startswith('#cmakedefine'):
+                line = line.replace('#cmakedefine', '#undef')
+            dest.write(line)
+        dest.write('\n')
+
+
+def update_readme(path, revision):
+    """
+    Updates the commit hash in README.rnp
+    :param string path: Path to README.rnp
+    :param string revision: revision to insert
+    """
+    commit_re = re.compile(r'^\[commit [\da-f]{40}\]$')
+    with open(path) as orig:
+        tmp_string = StringIO.StringIO()
+        tmp_string.write(orig.read())
+
+    tmp_string.seek(0)
+
+    with open(path, 'w') as dest:
+        for line in tmp_string:
+            if commit_re.match(line):
+                line = "[commit {}]\n".format(revision)
+            dest.write(line)
copy from third_party/README.libotr
copy to third_party/README.rnp
--- a/third_party/README.libotr
+++ b/third_party/README.rnp
@@ -1,7 +1,38 @@
-Directory ./libotr contains a copy of version 4.1.1 of the libotr library,
-which has been obtained from https://otr.im/dist/libotr/4.1.1/libotr-4.1.1.tar.gz .
+Directory ./rnp contains a copy of rnp which has been obtained from:
+https://github.com/rnpgp/rnp
+
+[commit 5f41ee12433d070d96d75b715d81b7af60104856]
 
 For licensing information, please refer to the included documentation.
 
-The SHA256SUM of the imported file is:
-8b3b182424251067a952fb4e6c7b95a21e644fbb27fbd5f8af2b2ed87ca419f5  libotr-4.1.1.tar.gz
+To update this copy, run "update_rnp.sh" in this directory from this directory
+within a complete build tree (including mozilla-central) as "mach python" is
+used.
+
+update_rnp.sh will generate rnp/src/lib/version.h from rnp/src/lib/version.h.in
+and modify rnp/src/lib/config.h.in so it can be processed by mozbuild at
+build time.
+
+You may pass a git revision to update_rnp.sh to update to that revision. Running
+without parameters updates to the latest master.
+
+The following files and directories are removed by update_rnp.sh:
+ci
+cmake
+git-hooks
+.github
+.cirrus.yml
+.clang-format
+.gitignore
+_config.yml
+docker.sh
+travis.sh
+Brewfile
+CMakeLists.txt
+
+
+The following files were added to the source's root by MZLA Technologies:
+Makefile.in
+moz.build
+module.ver
+rnp.symbols
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/LICENSE-OCB.md
@@ -0,0 +1,81 @@
+License for OCB Usage
+=====================
+
+This license has been graciously granted by Professor Phillip Rogaway to allow
+users of [`rnp`](https://github.com/rnpgp/rnp) to utilize the patented
+[OCB](http://web.cs.ucdavis.edu/~rogaway/ocb/) blockcipher mode of operation,
+which simultaneously provides privacy and authenticity.
+
+The license text is presented below in plain text form purely for referencial
+purposes. The original signed license is available on request from Ribose Inc.,
+reachable at open.source@ribose.com.
+
+This file adheres to the formatting guidelines of
+[readable-licenses](https://github.com/nevir/readable-licenses).
+
+OCB Patent License for Ribose Inc.
+----------------------------------
+
+1. Definitions
+
+1.1 "Licensor" means Phillip Rogaway, of 1212 Purdue Dr., Davis, California, USA.
+
+1.2 "Licensed Patents" means any patent that claims priority to United States
+Patent Application No. 09/918,615 entitled "Method and Apparatus for
+Facilitating Efficient Authenticated Encryption," and any utility, divisional,
+provisional, continuation, continuations in part, reexamination, reissue, or
+foreign counterpart patents that may issue with respect to the aforesaid patent
+application. This includes, but is not limited to, United States Patent No.
+7,046,802; United States Patent No. 7,200,227; United States Patent No.
+7,949,129; United States Patent No. 8,321,675; and any patent that issues out
+or United States Patent Application No. 13/669,114.
+
+1.3 "Licensee" means Ribose Inc., at Suite 1, 8/F, 10 Ice House Street,
+Central, Hong Kong, its affiliates, assignees, or successors in interest, or
+anyone using, making, copying, modifying, distributing, having made, importing,
+or having imported any program, software, or computer system including or based
+upon Open Source Software published by Ribose Inc., or their customers,
+suppliers, importers, manufacturers, distributors, or insurers.
+
+1.4 "Use in Licensee Products" means using, making, copying, modifying,
+distributing, having made, importing or having imported any program, software,
+or computer system published by Licensee, which contains or is based upon Open
+Source Software which may include any implementation of the Licensed Patents.
+
+1.5 "Open Source Software" means software whose source code is published and
+made available for inspection and use by anyone because either (a) the source
+code is subject to a license that permits recipients to copy, modify, and
+distribute the source code without payment of fees or royalties, or (b) the
+source code is in the public domain, including code released for public use
+through a CC0 waiver. All licenses certified by the Open Source Initiative at
+opensource.org as of January 1, 2017 and all Creative Commons licenses
+identified on the creativecommons.org website as of January 1, 2017, including
+the Public License Fallback of the CC0 waiver, satisfy these requirements for
+the purposes of this license.
+
+2. Grant of License
+
+2.1 Licensor hereby grants to Licensee a perpetual, worldwide, non-exclusive,
+nontransferable, non-sublicenseable, no-charge, royalty-free, irrevocable
+license to Use in Licensee Products any invention claimed in the Licensed
+Patents in any Open Source Software Implementation and in hardware as long as
+the Open Source Software incorporated in such hardware is freely licensed for
+hardware embodiment.
+
+3. Disclaimer
+
+3.1 LICENSEE'S USE OF THE LICENSED PATENTS IS AT LICENSEE'S OWN RISK AND UNLESS
+REQUIRED BY APPLICABLE LAW, LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ANY KIND CONCERNING THE LICENSED PATENTS OR ANY PRODUCT EMBODYING ANY LICENSED
+PATENT, EXPRESS OR IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT
+LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR
+PURPOSE, OR NONINFRINGEMENT. IN NO EVENT WILL LICENSOR BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING
+FROM OR RELATED TO ANY USE OF THE LICENSED PATENTS, INCLUDING, WITHOUT
+LIMITATION, DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR SPECIAL
+DAMAGES, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+PRIOR TO SUCH AN OCCURRENCE.
+
+[SIGNATURE by Phillip Rogaway]
+
+Date: August 28, 2017
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/LICENSE.md
@@ -0,0 +1,136 @@
+Licenses & Copyright
+====================
+
+This license file adheres to the formatting guidelines of
+[readable-licenses](https://github.com/nevir/readable-licenses).
+
+
+Ribose's BSD 2-Clause License
+-----------------------------
+
+Copyright (c) 2017, [Ribose Inc](https://www.ribose.com).
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1.  Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+2.  Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+NetBSD's BSD 2-Clause License
+-----------------------------
+
+This software contains source code originating from NetPGP, which
+carries the following copyright notice and license.
+
+Copyright (c) 2009-2016, [The NetBSD Foundation, Inc](https://www.netbsd.org).
+All rights reserved.
+
+This code is derived from software contributed to The NetBSD Foundation
+by [Alistair Crooks](mailto:agc@NetBSD.org)
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1.  Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+2.  Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Nominet UK's Apache 2.0 Licence
+-------------------------------
+
+This software contains source code originating from NetPGP, which
+carries the following copyright notice and license.
+
+Copyright (c) 2005-2008 [Nominet UK](www.nic.uk)
+All rights reserved.
+
+Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
+their moral rights under the UK Copyright Design and Patents Act 1988 to
+be recorded as the authors of this copyright work.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+this file except in compliance with the License.  You may obtain a copy of the
+License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed
+under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+CONDITIONS OF ANY KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations under the License.
+
+
+Nominet UK's BSD 3-Clause License
+-------------------------------
+
+This software contains source code originating from NetPGP, which
+carries the following copyright notice and license.
+
+Copyright (c) 2005 [Nominet UK](www.nic.uk)
+All rights reserved.
+
+Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
+their moral rights under the UK Copyright Design and Patents Act 1988 to
+be recorded as the authors of this copyright work.
+
+This is a BSD-style Open Source licence.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1.  Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+2.  Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+3.  The name of Nominet UK or the contributors may not be used to
+    endorse or promote products derived from this software without specific
+    prior written permission;
+
+and provided that the user accepts the terms of the following disclaimer:
+
+THIS SOFTWARE IS PROVIDED BY NOMINET UK AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL NOMINET UK OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/README.adoc
@@ -0,0 +1,58 @@
+= RNP
+
+image:https://github.com/rnpgp/rnp/workflows/macos/badge.svg["macOS Build Status", link="https://github.com/rnpgp/rnp/actions?workflow=macos"]
+image:https://github.com/rnpgp/rnp/workflows/ubuntu/badge.svg["Ubuntu Build Status", link="https://github.com/rnpgp/rnp/actions?workflow=ubuntu"]
+image:https://github.com/rnpgp/rnp/workflows/centos7/badge.svg["CentOS 7 Build Status", link="https://github.com/rnpgp/rnp/actions?workflow=centos7"]
+
+image:https://img.shields.io/coverity/scan/12616.svg["Coverity Scan Build Status", link="https://scan.coverity.com/projects/rnpgp-rnp"]
+image:https://codecov.io/gh/rnpgp/rnp/branch/master/graph/badge.svg["Code coverage", link="https://codecov.io/gh/rnpgp/rnp"]
+
+== Introduction
+
+RNP is a set of OpenPGP (RFC4880) tools that works on Linux, macOS, Windows and
+*BSD built with C++.
+
+`librnp` is the library used by RNP for all OpenPGP functions, useful
+for developers to build against, different from GPGME.
+
+
+== Supported Platforms
+
+Currently supported platforms:
+
+* Fedora 25
+* RHEL/CentOS 7
+* Ubuntu 14.04 LTS, 16.04 LTS, 18.04
+
+Upcoming supported platforms:
+
+* Debian 8, 9
+* OpenSUSE Leap 42.2, 42.3
+* SLES 12
+
+== link:docs/installation.adoc[Installation]
+
+== link:docs/cli-usage.adoc[Using CLI tool]
+
+== link:docs/c-usage.adoc[Using RNP’s C API in your projects]
+
+== Versioning
+
+RNP follows the http://semver.org/[semantic versioning] syntax.
+
+=== Checking versions
+
+The output of `rnp --version` contains the `git` hash of
+the version the binary was built from, which value is generated when
+`cmake` runs. Consequently, a release tarball generated with `make
+dist` will contain this hash version.
+
+=== Historic information
+
+The first version of rnp started at `0.8.0` to indicate its development
+completeness (or lack thereof).
+
+RNP originated as an attempt to modernize the NetPGP codebase originally
+created by Alistair Crooks of NetBSD in 2016. RNP has been heavily rewritten,
+and carries minimal if any code from the original codebase.
+
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/doc/tests/README.md
@@ -0,0 +1,72 @@
+# Test Case Guidelines for `rnp`
+
+The document aims to describe and capture various use cases for `rnp` in
+the form of the test cases. These can be used as acceptance tests for
+the maintenance of the project.
+
+
+## Naming conventions
+
+The test case name is composed of the three parts.
+
+* First being the module under test,
+* Second being the feature and third details the motivation of the test.
+
+Naming structure looks like: `<module>_<component>_<test-motivation>`.
+
+For example, when testing the `generatekey` feature of `rnpkeys`, the
+test case name would be `rnpkeys.generatekey.<test-motivation>`.
+
+
+## Test Case Specification Template
+
+The following template **SHOULD** be used for describing a test case.
+
+
+~~~~~~ md
+# <test-case-name>
+
+Component
+: <component-name>
+
+Feature
+: <feature-name>
+
+## Objective
+
+% Objective of test case
+
+## Description
+
+% Describe test case briefly
+
+## Preconditions
+
+% List of conditions prior to testing
+
+* condition 1
+* condition 2
+* condition 3
+
+## Test steps and expected behavior
+
+1. Test step 1
+
+1. Test step 2
+
+Expectation: expectation here
+
+## Verification steps and logic
+
+1. Verification step 1
+  * Rationale: verification logic
+
+1. Verification step 2
+  * Rationale: verification logic
+
+## Comments
+
+% if any
+
+~~~~~~
+
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/doc/tests/rnpkeys-generate-key.md
@@ -0,0 +1,192 @@
+# rnpkeys_generatekey_verifySupportedHashAlg
+
+Component
+: rnpkeys
+
+Feature
+: Generate-key
+
+## Objective
+
+Verify SupportedHashAlg.
+
+## Description
+
+The test aims to test key generation with all possible hash algorithm.
+Following hash algorithm are tested for the key generation:
+
+* `MD5`
+* `SHA-1`
+* `RIPEMD160`
+* `SHA256`
+* `SHA384`
+* `SHA512`
+* `SHA224`
+
+## Preconditions
+
+* Initialize RNP
+* Set the default value for `res`, `format`, `hash` via `rnp_setvar()`.
+
+## Test steps and expected behavior
+
+1. Set the hash algorithm via `rnp_setvar`
+
+1. Call the API to generate key (`rnp_generate_key`)
+
+Expectation: key is generated using options set via `rnp_setvar`
+
+## Verification steps and logic
+
+1. Load the newly generated RNP keys
+  * Rationale: Ensures keys are loaded in the `rnp` control structure
+  for verification.
+
+1. Find existence of key via `userId`.
+
+  * **Note**: If `userid` variable is not set, default is `always`.
+  * Rationale: Ensures the key exists by finding it.
+
+## Comments
+
+It is required to delete the old keys if the test case iterates over the
+hashing algorithm.
+
+
+# rnpkeys_generatekey_VerifyUserIdOption
+
+Component
+: rnpkeys
+
+Feature
+: Generate-key
+
+## Objective
+
+Verify `UserIdOption`
+
+## Description
+
+The test aims to test key generation with command line option `UserId`.
+
+Following different `userid`s are tested:
+
+* `rnpkeys_Generatekey_VerifyUserIdOption_MD5`
+* `rnpkeys_Generatekey_VerifyUserIdOption_SHA-1`
+* `rnpkeys_Generatekey_VerifyUserIdOption_RIPEMD160`
+* `rnpkeys_Generatekey_VerifyUserIdOption_SHA256`
+* `rnpkeys_Generatekey_VerifyUserIdOption_SHA384`
+* `rnpkeys_Generatekey_VerifyUserIdOption_SHA512`
+* `rnpkeys_Generatekey_VerifyUserIdOption_SHA224`
+
+
+## Preconditions
+
+* Initialize RNP
+* Set the default value for res, format, hash via `rnp_setvar`.
+
+## Test steps and expected behavior
+
+1. Set the userId via `rnp_setvar`
+
+1. Call the API to generate key (`rnp_generate_key`)
+
+Expectation: key is generated using options set via `rnp_setvar`
+
+## Verification steps and logic
+
+1. Load the newly generated RNP keys
+  * Rationale: Ensures keys are loaded in the rnp control structure for
+  verification.
+
+1. Find the existence of the key via finding the key with the userId.
+
+
+# rnpkeys_generatekey_verifykeyRingOptions
+
+Component
+: rnpkeys
+
+Feature
+: Generate-key
+
+## Objective
+
+Verify keyRingOptions.
+
+## Description
+
+The test aims to test key generation with the user specified keyring.
+
+## Preconditions
+
+* Initialize RNP
+* Set the default value for `res`, `format`, `hash` via `rnp_setvar()`.
+
+## Test steps and expected behavior
+
+1. Set the keyring via `rnp_setvar`
+
+1. Call the API to generate key (`rnp_generate_key`)
+
+Expectation: key is generated using options set via `rnp_setvar`
+
+## Verification steps and logic
+
+1. Delete the default keyring i.e. `pubring.gpg` and `secring.gpg` found
+   in the homedir
+
+  * Rationale: To ensure that default keyring is **NOT** available.
+
+1. Load the newly generated RNP keys
+
+  * Rationale: Ensures keys are loaded in the `rnp` control structure
+  for verification.
+
+1. Find existence of key via `userId`.
+
+  * **Note**: If `userid` variable is not set, default is `always`.
+  * Rationale: Ensures the key exists by finding it.
+
+
+# rnpkeys_generatekey_verifykeyHomeDirOption
+
+Component
+: rnpkeys
+
+Feature
+: Generate-key
+
+## Objective
+
+Verify keyHomeDirOption.
+
+## Description
+
+The test aims to test key generation with the user specified keyring.
+
+## Preconditions
+
+* Create new home dir with read/write permissions.
+* Delete the keys (if any) in the previous default directory.
+* Initialize RNP
+* Set the default value for `res`, `format`, `hash` via `rnp_setvar()`.
+
+## Test steps and expected behavior
+
+1. Call the API to generate key (`rnp_generate_key`)
+
+Expectation: key is generated using options set via `rnp_setvar`
+
+## Verification steps and logic
+
+1. Load the newly generated RNP keys
+
+  * Rationale: Ensures keys are loaded in the rnp control structure for
+  verification.
+
+1. Find existence of key via `userId`.
+
+  * **Note**: If `userid` variable is not set, default is `always`.
+  * Rationale: Ensures the key exists by finding it.
+
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/docs/c-usage.adoc
@@ -0,0 +1,101 @@
+= Using RNP’s C APIs
+
+If you’re a developer and wish to use the RNP library in your projects,
+you can use the examples below to see how it may be done.
+
+== Samples
+
+[TIP]
+.Where to find the examples
+====
+Find the source code for these examples
+under `https://github.com/rnpgp/rnp/blob/master/src/examples/[src/examples]`.
+
+If you’re building from source, the examples are built together with the RNP library
+and are available in `src/examples` directory of your build folder.
+====
+
+[TIP]
+====
+All samples below use APIs exposed via header file
+`https://github.com/rnpgp/rnp/blob/master/include/rnp/rnp.h[include/rnp/rnp.h]`,
+check it out for more documentation.
+====
+
+Following sample applications are available:
+
+`generate`:: Includes code which shows how to generate keys, save/load keyrings, export keys.
+
+`encrypt`:: Includes code which shows how to encrypt file, using the password and/or key.
+
+`decrypt`:: This one shows how to decrypt OpenPGP data, using the key or password.
+
+`sign`:: Shows how to sign messages, using the key(s) from loaded keyring.
+
+`verify`:: Shows how to verify signed messages using dynamic keys fetching (sample key provider implementation).
+
+`dump`:: Shows how to dump OpenPGP packet information.
+
+=== https://github.com/rnpgp/rnp/blob/master/src/examples/generate.c[generate.c]
+
+This example is composed from 2 functions:
+
+ * `ffi_generate_keys()`: this shows how to generate and save different key types
+   (RSA and EDDSA/Curve25519) using the JSON key description.
+   This also demonstrates the usage of password provider.
++
+Keyrings will be saved to files `pubring.pgp` and `secring.pgp` in the current directory.
+You can use `rnp --list-packets pubring.pgp` to check the properties of the generated key(s).
+
+ * `ffi_output_keys()`: This shows how to load keyrings,
+   search for the keys (in helper functions `ffi_print_key()`/`ffi_export_key()`),
+   and export them to memory or file in armored format.
+
+=== https://github.com/rnpgp/rnp/blob/master/src/examples/encrypt.c[encrypt.c]
+
+This code sample first loads public keyring (`pubring.pgp`) (created by the “generate.c” example),
+then creates encryption operation structure and configures it with various options
+(including the setup of password encryption and public-key encryption).
+
+The result is the encrypted and armored (for easier reading) message `RNP encryption sample message`.
+It is saved to the file `encrypted.asc` in current directory.
+
+You can investigate it via the `rnp --list-packets encrypted.asc` command.
+Also, you may want to decrypt saved file via `rnp --keyfile secring.pgp -d encrypted.asc`.
+
+=== https://github.com/rnpgp/rnp/blob/master/src/examples/decrypt.c[decrypt.c]
+
+This example uses keyrings generated in the “generate.c” sample to decrypt messages
+encrypted by the “encrypt.c” sample.
+
+It shows how to decrypt message with password or with a key
+and implements custom password provider for decryption or key password.
+
+Decrypted message is saved to the memory and then printed to the stdout.
+
+=== https://github.com/rnpgp/rnp/blob/master/src/examples/sign.c[sign.c]
+
+This sample uses keyrings generated in the preceding “generate.c” sample.
+
+This sample configures signing context and signs the message, saving it to the `signed.asc` file.
+Attached signature is used, i.e. the data is encapsulated into the resulting message.
+
+You can investigate the signed message by issuing `rnp --list-packets signed.asc` command.
+To verify message, use `rnp --keyfile pubring.pgp -v signed.asc`.
+
+=== https://github.com/rnpgp/rnp/blob/master/src/examples/verify.c[verify.c]
+
+This example uses keyrings generated in the “generate.c” sample.
+
+However, instead of loading the whole keyring, it implements dynamic key fetching
+via custom key provider (see function `example_key_provider`).
+
+After verification this sample outputs the verified embedded message
+and all signatures with signing key ids and statuses.
+
+=== https://github.com/rnpgp/rnp/blob/master/src/examples/dump.c[dump.c]
+
+This example dumps OpenPGP packet information from the input stream (stdin or filename), 
+tuned with flags passed via command line interface.
+
+Resulting human-readable text or JSON is dumped to stdout.
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/docs/cli-usage.adoc
@@ -0,0 +1,166 @@
+= Using the RNP command-line tool
+
+== Generating an RSA Private Key
+
+By default `rnpkeys  --generate-key` will generate 2048-bit RSA key.
+
+[source,console]
+----
+export keydir=/tmp
+rnpkeys --generate-key --homedir=${keydir}
+----
+
+=>
+
+[source,console]
+----
+rnpkeys: generated keys in directory ${keydir}/6ed2d908150b82e7
+----
+
+In case you're curious, `6ed2d...` is the key fingerprint.
+
+In order to use fully featured key pair generation ``--expert`` flag should be used. With this flag added to  ``rnpkeys --generate-key`` user has a possibility to generate keypair for any supported algorithm and/or key size.
+
+Example:
+
+[source,console]
+----
+> export keydir=/tmp
+> rnpkeys --generate-key --expert --homedir=${keydir}
+
+Please select what kind of key you want:
+    (1)  RSA (Encrypt or Sign)
+    (19) ECDSA
+    (22) EDDSA
+> 19
+
+Please select which elliptic curve you want:
+    (1) NIST P-256
+    (2) NIST P-384
+    (3) NIST P-521
+> 2
+
+Generating a new key...
+signature  384/ECDSA d45592277b75ada1 2017-06-21
+Key fingerprint: 4244 2969 07ca 42f7 b6d8 1636 d455 9227 7b75 ada1
+uid              ECDSA 384-bit key <flowher@localhost>
+rnp: generated keys in directory /tmp/.rnp
+Enter password for d45592277b75ada1:
+Repeat password for d45592277b75ada1:
+>
+----
+
+
+== Listing Keys
+
+[source,console]
+----
+export keyringdir=${keydir}/MYFINGERPRINT
+rnpkeys --list-keys --homedir=${keyringdir}
+
+----
+
+=>
+
+[source,console]
+----
+1 key found
+...
+----
+
+
+== Signing a File
+
+
+=== Signing in binary format
+
+[source,console]
+----
+rnp --sign --homedir=${keyringdir} ${filename}
+----
+
+=>
+
+Creates `${filename}.gpg` which is an OpenPGP message that includes the
+message together with the signature as a 'signed message'.
+
+This type of file can be verified by:
+
+* `rnp --verify --homedir=${keyringdir} ${filename}.gpg`
+
+
+=== Signing in binary detatched format
+
+[source,console]
+----
+rnp --sign --detach --homedir=${keyringdir} ${filename}
+----
+
+=>
+
+Creates `${filename}.sig` which is an OpenPGP message in binary
+format, that only contains the signature.
+
+This type of file can be verified by:
+
+* `rnp --verify --homedir=${keyringdir} ${filename}.sig`
+
+
+=== Signing in Armored (ASCII-Armored) format
+
+[source,console]
+----
+rnp --sign --armor --homedir=${keyringdir} ${filename}
+----
+
+=>
+
+Creates `${filename}.asc` which is an OpenPGP message in ASCII-armored
+format, including the message together with the signature as a 'signed
+message'.
+
+This type of file can be verified by:
+
+* `rnp --verify --homedir=${keyringdir} ${filename}.asc`
+
+
+=== Other options
+
+* `--clearsign` option will append a separate PGP Signaure to the end of
+  the message (the new output)
+
+* `--detach` option will append a separate PGP Signaure to the end of
+  the message (the new output)
+
+
+== Encrypt
+
+
+[source,console]
+----
+rnp --encrypt --homedir=${keyringdir} ${filename}
+----
+
+=>
+
+Creates `${filename}.gpg`.
+
+
+== Decrypt
+
+[source,console]
+----
+rnp --decrypt --homedir=${keyringdir} ${filename}.gpg
+----
+
+=>
+
+Creates `${filename}`.
+
+
+== Check binary version
+
+The output of `rnp --version` contains the `git` hash of the version
+the binary was built from, which value is generated when `cmake` runs.
+
+Consequently, a release tarball generated with `make dist` will contain this hash version.
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/docs/develop.adoc
@@ -0,0 +1,481 @@
+= RNP development guide
+
+The following are a set of conventions and items that are relevant to
+contributors.
+
+== Contributing
+
+=== Pull Requests
+
+See also: https://github.com/rnpgp/guides/tree/master/code-review[Guides - Code Review]
+
+Pull Requests should be used for any non-trivial changes. This presents
+an opportunity for feedback and allows the CI tests to complete prior to
+merging.
+
+The `master` branch should generally always be in a buildable and
+functional state.
+
+Pull Requests should be:
+
+* Focused. Do not include changes that are unrelated to the main purpose
+  of the PR.
+* As small as possible. Sometimes large pull requests may be necessary
+  for adding complex features, but generally they should be kept as small
+  as possible to ensure a quick and thorough review process.
+* Related to a GH issue to which you are assigned. If there is none,
+  file one (but search first!). This ensures there is no duplication of
+  effort and allows for a discussion prior to beginning work.
+  (This may not be necessary for PRs that are purely documentation updates)
+* Approved by **2** reviewers before merging.
+  (Updates related to policies, like this section, should be approved by
+  the project owner)
+* Merged by a reviewer via the most appropriate method
+  (see https://github.com/rnpgp/guides/tree/master/protocol/git[here]).
+
+=== Branches
+
+See also: https://github.com/rnpgp/guides/tree/master/protocol/git[Guides - Protocol / Git]
+
+Git branches should be used generously. Most branches should be topic branches,
+created for adding a specific feature or fixing a specific bug.
+
+Keep branches short-lived (treat them as disposable/transient) and try to
+avoid long-running branches.
+
+A good example of using a branch would be:
+
+* User `@joe` notices a bug where a NULL pointer is dereferenced during
+  key export. He creates GH issue `#500`.
+* He creates a new branch to fix this bug named
+  `joe-500-fix-null-deref-in-pgp_export_key`.
+* Joe commits a fix for the issue to this new branch.
+* Joe creates a Pull Request to merge this branch in to master.
+* Once merged, Joe deletes the branch since it is no longer useful.
+
+Branch names may vary but should be somewhat descriptive, with words
+separated by hyphens. It is also helpful to start the branch name with
+your github username, to make it clear who created the branch and
+prevent naming conflicts.
+
+Remember that branch names may be preserved permanently in the commit
+history of `master`, depending on how they are merged.
+
+=== Commits
+
+* Try to keep commits as small as possible. This may be difficult or
+  impractical at times, so use your best judgement.
+* Each commit should be buildable and should pass all tests. This helps
+  to ensure that git bisect remains a useful method of pinpointing issues.
+* Commit messages should follow 50/72 rule.
+* When integrating pull requests, merge function should be prefered over
+  squashing. From the other hand, developers should squash commits and
+  create meaningful commit stack before PR is merged into mainstream branch.
+  Merging commits like "Fix build" or "Implement comments from code review"
+  should be avoided.
+
+== Continuous Integration (Travis CI)
+
+Travis CI is used for continuously testing new commits and pull
+requests.
+
+We use the sudo-less beta Ubuntu Trusty containers, which do not permit
+root access.
+
+See the file `.travis.yml` and the scripts in `ci/` for the most
+up-to-date details.
+
+=== Reproducing Locally
+
+Sometimes tests fail in Travis CI and you will want to reproduce them
+locally for easier troubleshooting.
+
+We can use a container for this, like so:
+
+[source,console]
+--
+./travis.sh
+--
+
+Inside the container, you can do local CI runs like so:
+
+[source,console]
+--
+env GPG_VERSION=beta BUILD_MODE=sanitize ci/local.sh
+--
+
+== Code Coverage
+
+CodeCov is used for assessing our test coverage.
+The current coverage can always be viewed here: https://codecov.io/github/rnpgp/rnp/
+
+== Security / Bug Hunting
+
+=== Static Analysis
+
+==== Coverity Scan
+
+Coverity Scan is used for occasional static analysis of the code base.
+
+To initiate analysis, a developer must push to the `coverity_scan` branch.
+You may wish to perform a clean clone for this, like so:
+
+[source,console]
+--
+cd /tmp
+
+git clone https://github.com/rnpgp/rnp
+# or
+# git clone git@github.com:rnpgp/rnp.git
+cd rnp
+
+# switch to the coverity_scan branch
+git checkout coverity_scan
+
+# replay all commits from master onto coverity_scan
+git rebase master coverity_scan
+
+# forcefully push the coverity_scan branch
+git push -u origin coverity_scan -f
+--
+
+Note: The `master` and `coverity_scan` branches have separate
+`.travis.yml` files, so you may need to perform a manual merge. In
+general, the `coverity_scan` branch's `.travis.yml` is identical to
+`master`'s, but with a build matrix of only one entry.
+
+The results can be accessed on
+https://scan.coverity.com/projects/rnpgp-rnp. You will need to
+create an account and request access to the rnpgp/rnp project.
+
+Since the scan results are not updated live, line numbers may no longer
+be accurate against the `master` branch, issues may already be resolved,
+etc.
+
+==== Clang Static Analyzer
+
+Clang includes a useful static analyzer that can also be used to locate
+potential bugs.
+
+Note: It is normal for the build time to increase significantly when using this static analyzer.
+
+[source,console]
+--
+# it's important to start fresh for this!
+rm -rf build && mkdir build && cd build
+scan-build cmake .. && scan-build make -j8
+[...]
+scan-build: 61 bugs found.
+scan-build: Run 'scan-view /tmp/scan-build-2018-09-17-085354-22998-1' to examine bug reports.
+--
+
+Then use `scan-view`, as indicated above, to start a web server and use
+your web browser to view the results.
+
+=== Dynamic Analysis
+
+==== Fuzzer
+
+It is often useful to utilize a fuzzer like
+http://lcamtuf.coredump.cx/afl/["american fuzzy lop" ("AFL")] to find
+ways to improve the robustness of the code base.
+
+Currently, we have a very simple test program in
+`src/fuzzers/fuzz_keys`, which will attempt to load an armored key file
+passed on the command line. We can use this with AFL to try to produce
+crashes, which we can then analyze for issues.
+
+1. Install AFL.
+2. Rebuild, using the `afl-gcc` compiler.
+    * It's probably easiest to also do a static build, using the
+      `--disable-shared` option to `configure`.
+    * It may be helpful to occasionally enable the address sanitizer,
+      which tends to help produce crashes that may not otherwise be found.
+      Read the documentation for AFL first to understand the challenges
+      with ASan and AFL.
+3. Create directories for input files, and for AFL output.
+4. Run `afl-fuzz`.
+5. When satisfied, exit with `CTRL-C`.
+6. Analyze the crashes/hangs in the output directory.
+
+Here is an example:
+
+[source,console]
+--
+env CXX=afl-g++ AFL_HARDEN=1 CXXFLAGS=-ggdb ./configure --disable-shared
+make -j$(grep -c '^$' /proc/cpuinfo) clean all
+mkdir afl_in afl_out
+cp some_tests/*.asc afl_in/
+afl-fuzz -i afl_in -o afl_out src/fuzzing/fuzz_keys @@
+ctrl-c to exit
+valgrind -q src/fuzzing/fuzz_keys < afl_out/[...]
+--
+
+===== Further Reading
+
+* AFL's `README`, `parallel_fuzzing.txt`, and other bundled documentation.
+* See https://fuzzing-project.org/tutorial3.html[Tutorial: Instrumented fuzzing with american fuzzy lop]
+
+==== Clang Sanitizer
+
+Clang and GCC both support a number of sanitizers that can help locate
+issues in the code base during runtime.
+
+To use them, you should rebuild with the sanitizers enabled, and then
+run the tests (or any executable):
+
+[source,console]
+--
+env CXX=clang++ CXXFLAGS="-fsanitize=address,undefined" LDFLAGS="-fsanitize=address,undefined" ./configure
+make -j4
+src/tests/rnp_tests
+--
+
+Here we are using the
+https://clang.llvm.org/docs/AddressSanitizer.html[AddressSanitizer]
+and
+https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html[UndefinedBehaviorSanitizer].
+
+This will produce output showing any memory leaks, heap overflows, or
+other issues.
+
+== Code Conventions
+
+C is a very flexible and powerful language. Because of this, it is
+important to establish a set of conventions to avoid common problems and
+to maintain a consistent code base.
+
+=== Code Formatting
+
+`clang-format` (v9.0.0) can be used to format the code base, utilizing
+the `.clang-format` file included in the repository.
+
+==== clang-format git hook
+
+A git pre-commit hook exists to perform this task automatically, and can
+be enabled like so:
+
+[source,console]
+--
+cd rnp
+git-hooks/enable.sh
+--
+
+If you do not have clang-format v9.0.0 available, you can use a docker
+container for this purpose by setting `USE_DOCKER="yes"` in
+`git-hooks/pre-commit.sh`.
+
+This should generally work if you commit from the command line.
+
+Note that if you have unstaged changes on some of the files you are
+attempting to commit, which have formatting issues detected, you will
+have to resolve this yourself (the script will inform you of this).
+
+If your commit does not touch any `.c`/`.h` files, you can skip the
+pre-commit hook with git's `--no-verify`/`-n` option.
+
+==== clang-format (manually)
+
+If you are not able to use the git hook, you can run `clang-format`
+manually in a docker container.
+
+Create a suitable container image with:
+
+[source,console]
+--
+docker run --name=clang-format alpine:latest apk --no-cache add clang
+docker commit clang-format clang-format
+docker rm clang-format
+--
+
+You can then reformat a file (say, `src/lib/crypto/bn.cpp`) like so:
+
+[source,console]
+--
+cd rnp
+docker run --rm -v $PWD:/rnp -w /rnp clang-format clang-format -style=file -i src/lib/crypto/bn.cpp
+--
+
+Also you may wish to reformat all modified uncommited files:
+
+[source,console]
+--
+docker run --rm -v $PWD:/rnp -w /rnp clang-format clang-format -style=file -i `git ls-files -m |grep "\.\(c\|h\|cpp\)\$"`
+--
+
+...or files, modified since referenced commit, say `54c5476`:
+
+[source,console]
+--
+docker run --rm -v $PWD:/rnp -w /rnp clang-format clang-format -style=file -i `git diff --name-only 54c5476..HEAD |grep "\.\(c\|h\|cpp\)\$"`
+--
+
+=== Style Guide
+
+In order to keep the code base consistent, we should define and adhere
+to a single style.
+
+When in doubt, consult the existing code base.
+
+==== Naming
+
+The following are samples that demonstrate the style for naming
+different things.
+
+* Functions: `some_function`
+* Variables: `some_variable`
+* Filenames: `packet-parse.c` `packet-parse.h`
+* Struct: `pgp_key_t`
+* Typedefed Enums: `pgp_pubkey_alg_t`
+* Enum Values: `PGP_PKA_RSA = 1`
+* Constants (macro): `RNP_BUFSIZ`
+
+==== General Guidelines
+
+Do:
+
+* Do use header guards (`#ifndef SOME_HEADER_H [...]`) in headers.
+* Do use `sizeof(variable)`, rather than `sizeof(type)`. Or
+  `sizeof(*variable)` as appropriate.
+* Do use commit messages that close GitHub issues automatically, when
+  applicable. `Fix XYZ. Closes #78.` See
+  https://help.github.com/articles/closing-issues-via-commit-messages/[here].
+* Do declare functions `static` when they do not need to be referenced
+  outside the current source file.
+* Do always use braces for conditionals, even if the block only contains a
+  single statement.
++
+[source,c]
+--
+if (something) {
+  return val;
+}
+--
+
+* Do use a default failure (not success) value for `ret` variables. Example:
++
+[source,c]
+--
+rnp_result_t ret = RNP_ERROR_GENERIC;
+// ...
+
+return ret;
+--
+
+Do not:
+
+* Do not use the static storage class for local variables, *unless* they
+  are constant.
++
+**Not OK**
++
+[source,c]
+--
+int somefunc() {
+  static char buffer[256];
+  //...
+}
+--
++
+**OK**
++
+[source,c]
+--
+int somefunc() {
+  static const uint16_t some_data[] = {
+    0x00, 0x01, 0x02, //...
+  };
+}
+--
+
+* Do not use `pragma`, and try to avoid `__attribute__` as well.
+
+* Do not use uninitialized memory. Try to ensure your code will not cause any errors in valgrind and other memory checkers.
+
+==== Documentation
+
+Documentation is done in Doxygen comments format, which must be put in header files.
+
+Exception are static or having only definition functions - it is not required to document them,
+however if they are documented then this should be done in the source file and using the @private tag.
+
+Comments should use doxygen markdown style, like the following example:
+
+[source,c]
+--
+/** Some comments regarding the file purpose, like 'PGP packet parsing utilities'
+ *  @file
+ */
+
+/** brief description of the sample function which does something, keyword 'brief' is ommitted
+ *  Which may be continued here
+ *
+ *  After an empty line you may add detailed description in case it is needed. You may put
+ *  details about the memory allocation, what happens if function fails and so on.
+ *
+ *  @param param1 first parameter, null-terminated string which should not be NULL
+ *  @param param2 integer, some number representing something
+ *  @param size number of bytes available to store in buffer
+ *  @param buffer buffer to store results, may be NULL. In this case size can be used to
+ *                obtain the required buffer length
+ *  @return 0 if operation succeeds, or error code otherwise. If operation succeeds then buffer
+ *          is populated with the resulting data, and size contains the length of this data.
+ *          if error code is E_BUF_TOOSMALL then size will contain the required size to store
+ *          the result
+ **/
+rnp_result_t
+rnp_do_operation(const char *param1, const int param2, int *size, char *buffer);
+--
+
+== OpenPGP protocol specification
+
+During development you'll need to reference OpenPGP protocol and related documents.
+Here is the list of RFCs and Internet Drafts available at the moment:
+* https://www.ietf.org/rfc/rfc1991.txt[RFC 1991]: PGP Message Exchange Formats. Now obsolete, but may have some historical interest.
+* https://www.ietf.org/rfc/rfc2440.txt[RFC 2440]: OpenPGP Message Format. Superceded by RFC 4880.
+* https://www.ietf.org/rfc/rfc4880.txt[RFC 4880]: OpenPGP Message Format. Latest RFC available at the moment, however has a lot of suggested changes via RFC 4880bis
+* https://tools.ietf.org/rfc/rfc5581.txt[RFC 5581]: The Camellia cipher in OpenPGP.
+* https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-04.txt[RFC 4880bis-04]: OpenPGP Message Format. Latest suggested update to the RFC 4880.
+
+More information sources:
+* https://mailarchive.ietf.org/arch/browse/openpgp/[OpenPGP Working Group mailing list]. Here you can pick up all the latest discussions and suggestions regarding the update of RFC 4880
+* https://gitlab.com/openpgp-wg/rfc4880bis[OpenPGP Working Group gitlab]. Latest work on RFC update is available here.
+
+== Reviewers and Responsibility areas
+
+The individuals are responsible for the following areas of `rnp`.
+When submitting a Pull Request please seek reviews by whoever is
+responsible according to this list.
+
+General:
+
+* Code style: @dewyatt
+* Algorithms: @randombit, @dewyatt, @flowher, @catap, @ni4
+* Performance: @catap, @ni4
+* CLI: @ni4
+* GnuPG compatibility: @MohitKumarAgniotri, @frank-trampe, @ni4
+* Security Testing/Analysis: @MohitKumarAgniotri, @flowher
+* Autotools: @randombit, @zgyarmati, @catap
+
+Data formats:
+
+* OpenPGP Packet: @randombit, @catap, @ni4
+* Keystore: @catap
+* JSON: @zgyarmati
+* SSH: @ni4
+
+Bindings:
+
+* FFI: @dewyatt
+* Ruby: @dewyatt
+* Java/JNI: @catap
+* Obj-C/Swift: @ni4
+* Python: @dewyatt, @ni4
+
+Platforms:
+
+* RHEL/CentOS: @dewyatt
+* BSD:
+* Windows:
+* macOS / iOS / homebrew: @ni4
+* Debian: @zgyarmati
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/docs/develop/cpp-usage.adoc
@@ -0,0 +1,49 @@
+= Usage of {cpp} within RNP
+
+This is a provisional document reflecting the recent conversion from C
+to {cpp}. It should be revisited as experience with using {cpp} within RNP
+codebase increases.
+
+== Encouraged Features
+
+These are features which seem broadly useful, their downsides are minimal
+and well understood.
+
+ - STL types std::vector, std::string, std::unique_ptr, std::map
+
+ - RAII techniques (destructors, smart pointers) to minimize use of
+   goto to handle cleanup.
+
+ - Value types, that is to say types which simply encapsulate some
+   data.
+
+ - std::function or virtual functions to replace function pointers.
+
+ - Prefer virtual functions only on "interface" classes (with no data),
+   and derive only one level of classes from this interface class.
+
+ - Anonymous namespaces are an alternative to `static` functions.
+
+== Questionable Features
+
+These are features that may be useful in certain situations, but should
+be used carefully.
+
+ - Exceptions. While convenient, they do have a non-zero cost in runtime
+   and binary size.
+
+== Forbidden Features
+
+These are {cpp} features that simply should be avoided, at least until a
+very clear use case for them has been identified and no other approach
+suffices.
+
+ - RTTI. This has a significant runtime cost and usually there are
+   better alternatives.
+
+ - Multiple inheritence. This leads to many confusing and problematic
+   scenarios.
+
+ - Template metaprogramming. If you have a problem, and you think
+   template metaprogramming will solve it, now you have two problems,
+   and one of them is incomprehensible.
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/docs/develop/packaging.adoc
@@ -0,0 +1,77 @@
+= Packaging
+
+== CentOS 7
+
+=== 1. Retrieve the source
+
+==== Tarball
+
+[source,console]
+--
+curl -LO https://github.com/rnpgp/rnp/archive/v0.9.0.tar.gz
+tar xzf v0.9.0.tar.gz
+cd rnp-0.9.0
+--
+
+==== Git
+
+[source,console]
+--
+git clone https://github.com/rnpgp/rnp
+cd rnp
+git checkout v0.9.0
+--
+
+=== 2. Launch a container
+
+[source,console]
+--
+docker run -ti --rm -v $PWD:/usr/local/rnp centos:7 bash
+--
+
+From this point, all commands are executed in the container.
+
+==== 3. Install pre-requisites
+
+[source,console]
+--
+# for newer cmake and other things
+yum -y install epel-release
+
+# rnp
+yum -y install git cmake3 make gcc-c++
+yum -y install bzip2-devel zlib-devel json-c12-devel
+
+# botan
+rpm --import https://github.com/riboseinc/yum/raw/master/ribose-packages.pub
+curl -L https://github.com/riboseinc/yum/raw/master/ribose.repo > /etc/yum.repos.d/ribose.repo
+yum -y install botan2-devel
+--
+
+=== 4. Build the RPM
+
+[source,console]
+--
+yum -y install rpm-build
+mkdir ~/build
+cd ~/build
+cmake3 -DBUILD_SHARED_LIBS=on -DBUILD_TESTING=off -DCPACK_GENERATOR=RPM /usr/local/rnp
+make package
+--
+
+=== 5. Check and Install the RPM
+
+It may be helpful to run rpmlint on the RPM and note new warnings or errors.
+
+[source,console]
+--
+yum -y install rpmlint
+rpmlint rnp-0.9.0-1.el7.centos.x86_64.rpm
+--
+
+At this point, you can test that the RPM installs successfully:
+
+[source,console]
+--
+yum localinstall rnp-0.9.0-1.el7.centos.x86_64.rpm
+--
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/docs/develop/release-workflow.adoc
@@ -0,0 +1,107 @@
+= Releases
+
+== General Notes
+
+* Avoid tagging commits in the `master` branch.
+* Release branches should have annotated tags and a CHANGELOG.md.
+* The steps below detail creation of a brand new 1.0.0 release.
+  Some steps would be omitted for minor releases.
+
+== Creating an Initial Release
+
+=== Update the Documentation
+
+Update references to version numbers in relevant documentation to the new
+version you intend to release.
+
+[source,console]
+--
+git checkout master
+vim docs/installation.adoc
+git add docs/installation.adoc
+git commit
+git push
+--
+
+=== Create the Branch
+
+Release branches have names of the form `release/N.x`, where N is the major
+version (and x is a literal -- not a placeholder).
+
+[source,console]
+--
+git checkout -b release/1.x master
+--
+
+[[update-changelog-and-version]]
+=== Update CHANGELOG and version
+
+[source,console]
+--
+vim CHANGELOG.md
+# Add/update CHANGELOG entry for the new version
+git add CHANGELOG.md
+
+echo 1.0.0 > version.txt
+git add -f version.txt
+
+git commit
+--
+
+=== Create a Tag
+
+An initial release would be tagged as follows:
+
+[source,console]
+--
+git tag -a v1.0.0 -m ''
+--
+
+=== Push
+
+[source,console]
+--
+# push the branch
+git push origin release/1.x
+
+# push the tag
+git push origin v1.0.0
+--
+
+== Creating a New Release
+
+Maintaining a release branch involves cherry-picking hotfixes and similar commits
+from the `master` branch, while following the rules for Semantic Versioning.
+
+The steps below will show the release of version 1.0.1.
+
+=== Add the Desired Changes
+
+Cherry-pick the appropriate commits into the appropriate `release/N.x` branch.
+
+To see what commits are in `master` that are not in the release branch, you
+can observe the lines starting with `+` in:
+
+[source,console]
+--
+git cherry -v release/1.x master
+--
+
+It is often useful to pick a range of commits. For example:
+
+[source,console]
+--
+git checkout release/0.x
+git cherry-pick a57b36f^..e23352c
+--
+
+If there are merge commits in this range, this will not work. Instead, try:
+
+[source,console]
+--
+git checkout release/0.x
+git cherry release/0.x master | grep '^+ ' | cut -c 3-9 | while read commit; do git cherry-pick $commit; done
+--
+
+From here, you can follow the steps for an initial release,
+starting with link:#update-changelog-and-version[Update CHANGELOG and version].
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/docs/installation.adoc
@@ -0,0 +1,113 @@
+= Installing RNP
+
+Binaries that will be installed:
+
+* `rnp`
+* `rnpkeys`
+
+== On macOS using Homebrew
+
+[source,console]
+----
+brew tap rnpgp/rnp
+brew install rnp
+----
+
+== On RHEL and CentOS via YUM
+
+[source,console]
+----
+rpm --import https://github.com/riboseinc/yum/raw/master/ribose-packages.pub
+curl -L https://github.com/riboseinc/yum/raw/master/ribose.repo > /etc/yum.repos.d/ribose.repo
+yum install -y rnp
+----
+
+== On Ubuntu 18
+
+[source,console]
+----
+# Clone the repository by version tag (or omit it to get the latest sources)
+sudo apt install git
+git clone https://github.com/rnpgp/rnp.git -b v0.13.1
+
+# Install required packages
+sudo apt install g++-8 cmake libbz2-dev zlib1g-dev libjson-c-dev build-essential python-minimal
+
+# Download, build and install Botan2
+wget -qO- https://botan.randombit.net/releases/Botan-2.12.1.tar.xz | tar xvJ
+cd Botan-2.12.1
+./configure.py --prefix=/usr
+make
+sudo make install
+cd ..
+
+# Cmake recommend out-of-source builds
+mkdir rnp-build
+cd rnp-build
+
+# Cmake it
+cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=on -DBUILD_TESTING=off ../rnp/
+make
+sudo make install
+----
+
+== On Debian
+
+[source,console]
+----
+# Clone the repository by version tag (or omit it to get the latest sources)
+sudo apt install git
+git clone https://github.com/rnpgp/rnp.git -b v0.13.1
+
+# Enable access to `testing` packages by editing /etc/apt/sources.list
+# deb http://deb.debian.org/debian testing main
+# Install required packages
+sudo apt install g++-8 cmake libbz2-dev zlib1g-dev libjson-c-dev libbotan-2-dev build-essential
+
+# Cmake recommend out-of-source builds
+mkdir rnp-build
+cd rnp-build
+
+# Cmake it
+cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=on -DBUILD_TESTING=off ../rnp/
+make install
+----
+
+== Compiling from source
+
+Clone this repo, or download a release and expand it. Then:
+
+[source,console]
+----
+cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DBUILD_SHARED_LIBS=on -DBUILD_TESTING=off .
+make install
+----
+
+== On Windows using MSYS/MinGW
+
+Having the clean MSYS2 installation, you'll first need to update pacman and install needed packages via msys console:
+
+[source, console]
+----
+pacman -Syu --noconfirm --needed
+# Then most likely you'll need to close msys console and run it agian:
+pacman -Syu --noconfirm --needed
+# Install packages
+pacman --noconfirm -S --needed tar zlib-devel libbz2-devel git automake autoconf libtool automake-wrapper gnupg2 make pkgconfig mingw64/mingw-w64-x86_64-cmake mingw64/mingw-w64-x86_64-gcc mingw64/mingw-w64-x86_64-json-c mingw64/mingw-w64-x86_64-libbotan mingw64/mingw-w64-x86_64-python2
+----
+
+Then clone the repository, say to rnp folder, and:
+[source, console]
+----
+# CMake encourages out-of source builds.
+mkdir rnp-build
+cd rnp-build
+# Add MinGW's lib and bin to PATH so dependency dll/lib can be found
+export PATH="/c/msys64/mingw64/lib:/c/msys64/mingw64/bin:$PATH"
+# Run cmake
+cmake -DBUILD_SHARED_LIBS=yes -G "MSYS Makefiles" ../rnp
+make && make install
+----
+
+Depending on how do you run rnp.exe and rnpkeys.exe you'll need to make sure that librnp-0.dll is on path or in the same folder as well as all dependencies.
+You may check dependenices and their pathes via ntldd.exe in MSYS command prompt. 
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/docs/navigation.adoc
@@ -0,0 +1,19 @@
+---
+items:
+- { title: Installation, path: installation/ }
+- { title: Command-line usage, path: cli-usage/ }
+- { title: C API usage, path: c-usage/ }
+- title: Developing RNP
+  path: develop/
+  items:
+  - { title: "C++ usage", path: develop/cpp-usage/ }
+  - { title: "Development guide", path: develop/guide/ }
+  - { title: "Packaging", path: develop/packaging/ }
+  - { title: "Release workflow", path: develop/release-workflow/ }
+  # - title: "Acceptance tests"
+  #   path: develop/acceptance-tests/
+  #   items:
+  #   - { title: "rnpkeys-generate-key", path: develop/acceptance-tests/rnpkeys-generate-key }
+---
+
+= Navigation
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/include/rekey/rnp_key_store.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ *
+ * This code is originally derived from software contributed to
+ * The NetBSD Foundation by Alistair Crooks (agc@netbsd.org), and
+ * carried further by Ribose Inc (https://www.ribose.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef KEY_STORE_H_
+#define KEY_STORE_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "rnp.h"
+#include "librepgp/stream-common.h"
+
+typedef struct pgp_key_t pgp_key_t;
+
+typedef enum {
+    KBX_EMPTY_BLOB = 0,
+    KBX_HEADER_BLOB = 1,
+    KBX_PGP_BLOB = 2,
+    KBX_X509_BLOB = 3
+} kbx_blob_type;
+
+typedef struct {
+    uint32_t      length;
+    kbx_blob_type type;
+
+    uint8_t *image;
+} kbx_blob_t;
+
+typedef struct {
+    kbx_blob_t blob;
+    uint8_t    version;
+    uint16_t   flags;
+    uint32_t   file_created_at;
+    uint32_t   last_maintenance_run;
+} kbx_header_blob_t;
+
+typedef struct {
+    uint8_t  fp[PGP_FINGERPRINT_SIZE];
+    uint32_t keyid_offset;
+    uint16_t flags;
+} kbx_pgp_key_t;
+
+typedef struct {
+    uint32_t offset;
+    uint32_t length;
+    uint16_t flags;
+    uint8_t  validity;
+} kbx_pgp_uid_t;
+
+typedef struct {
+    uint32_t expired;
+} kbx_pgp_sig_t;
+
+typedef struct {
+    kbx_blob_t blob;
+    uint8_t    version;
+    uint16_t   flags;
+    uint32_t   keyblock_offset;
+    uint32_t   keyblock_length;
+
+    uint16_t nkeys;
+    uint16_t keys_len;
+    list     keys; // list of kbx_pgp_key_t
+
+    uint16_t sn_size;
+    uint8_t *sn;
+
+    uint16_t nuids;
+    uint16_t uids_len;
+    list     uids; // list of kbx_pgp_uid_t
+
+    uint16_t nsigs;
+    uint16_t sigs_len;
+    list     sigs; // list of kbx_pgp_sig_t
+
+    uint8_t ownertrust;
+    uint8_t all_Validity;
+
+    uint32_t recheck_after;
+    uint32_t latest_timestamp;
+    uint32_t blob_created_at;
+} kbx_pgp_blob_t;
+
+typedef enum pgp_key_store_format_t {
+    PGP_KEY_STORE_UNKNOWN = 0,
+    PGP_KEY_STORE_GPG,
+    PGP_KEY_STORE_KBX,
+    PGP_KEY_STORE_G10,
+} pgp_key_store_format_t;
+
+/* Key import status. Order of elements is important. */
+typedef enum pgp_key_import_status_t {
+    PGP_KEY_IMPORT_STATUS_UNKNOWN = 0,
+    PGP_KEY_IMPORT_STATUS_UNCHANGED,
+    PGP_KEY_IMPORT_STATUS_UPDATED,
+    PGP_KEY_IMPORT_STATUS_NEW,
+} pgp_key_import_status_t;
+
+typedef enum pgp_sig_import_status_t {
+    PGP_SIG_IMPORT_STATUS_UNKNOWN = 0,
+    PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY,
+    PGP_SIG_IMPORT_STATUS_UNCHANGED,
+    PGP_SIG_IMPORT_STATUS_NEW
+} pgp_sig_import_status_t;
+
+typedef struct rnp_key_store_t {
+    const char *           path;
+    pgp_key_store_format_t format;
+    bool disable_validation; /* do not automatically validate keys, added to this key store */
+
+    list keys;  // list of pgp_key_t
+    list blobs; // list of kbx_blob_t
+} rnp_key_store_t;
+
+rnp_key_store_t *rnp_key_store_new(pgp_key_store_format_t format, const char *path);
+
+bool rnp_key_store_load_from_path(rnp_key_store_t *, const pgp_key_provider_t *key_provider);
+bool rnp_key_store_load_from_src(rnp_key_store_t *,
+                                 pgp_source_t *,
+                                 const pgp_key_provider_t *key_provider);
+
+bool rnp_key_store_write_to_path(rnp_key_store_t *);
+bool rnp_key_store_write_to_dst(rnp_key_store_t *, pgp_dest_t *);
+
+void rnp_key_store_clear(rnp_key_store_t *);
+void rnp_key_store_free(rnp_key_store_t *);
+
+size_t     rnp_key_store_get_key_count(const rnp_key_store_t *);
+pgp_key_t *rnp_key_store_get_key(const rnp_key_store_t *, size_t);
+list       rnp_key_store_get_keys(const rnp_key_store_t *);
+
+pgp_key_t *rnp_key_store_add_key(rnp_key_store_t *, pgp_key_t *);
+
+pgp_key_t *rnp_key_store_import_key(rnp_key_store_t *,
+                                    pgp_key_t *,
+                                    bool,
+                                    pgp_key_import_status_t *);
+
+/**
+ * @brief Get signer's key from key store.
+ *
+ * @param store populated key store, cannot be NULL.
+ * @param sig signature, cannot be NULL.
+ * @return pointer to pgp_key_t structure if key was found or NULL otherwise.
+ */
+pgp_key_t *rnp_key_store_get_signer_key(rnp_key_store_t *store, const pgp_signature_t *sig);
+
+/**
+ * @brief Import revocation or direct-key signature to the keyring.
+ *
+ * @param keyring populated keyring, cannot be NULL.
+ * @param sig signature to import.
+ * @param status signature import status will be put here, if not NULL.
+ * @return pointer to the key to which this signature belongs (or NULL if key was not found)
+ */
+pgp_key_t *rnp_key_store_import_signature(rnp_key_store_t *        keyring,
+                                          const pgp_signature_t *  sig,
+                                          pgp_sig_import_status_t *status);
+
+bool rnp_key_store_remove_key(rnp_key_store_t *, const pgp_key_t *);
+
+pgp_key_t *rnp_key_store_get_key_by_id(const rnp_key_store_t *,
+                                       const unsigned char *,
+                                       pgp_key_t *);
+
+bool rnp_key_store_get_key_grip(const pgp_key_material_t *, uint8_t *);
+
+pgp_key_t *rnp_key_store_get_key_by_grip(const rnp_key_store_t *, const uint8_t *);
+pgp_key_t *rnp_key_store_get_key_by_fpr(const rnp_key_store_t *, const pgp_fingerprint_t *fpr);
+pgp_key_t *rnp_key_store_get_primary_key(const rnp_key_store_t *, const pgp_key_t *);
+pgp_key_t *rnp_key_store_search(const rnp_key_store_t *,
+                                const pgp_key_search_t *,
+                                pgp_key_t *);
+
+#endif /* KEY_STORE_H_ */
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/include/repgp/repgp_def.h
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2017-2020, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ *
+ * This code is originally derived from software contributed to
+ * The NetBSD Foundation by Alistair Crooks (agc@netbsd.org), and
+ * carried further by Ribose Inc (https://www.ribose.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef REPGP_DEF_H_
+#define REPGP_DEF_H_
+
+/************************************/
+/* Packet Tags - RFC4880, 4.2 */
+/************************************/
+
+/** Packet Tag - Bit 7 Mask (this bit is always set).
+ * The first byte of a packet is the "Packet Tag".  It always
+ * has bit 7 set.  This is the mask for it.
+ *
+ * \see RFC4880 4.2
+ */
+#define PGP_PTAG_ALWAYS_SET 0x80
+
+/** Packet Tag - New Format Flag.
+ * Bit 6 of the Packet Tag is the packet format indicator.
+ * If it is set, the new format is used, if cleared the
+ * old format is used.
+ *
+ * \see RFC4880 4.2
+ */
+#define PGP_PTAG_NEW_FORMAT 0x40
+
+/** Old Packet Format: Mask for content tag.
+ * In the old packet format bits 5 to 2 (including)
+ * are the content tag.  This is the mask to apply
+ * to the packet tag.  Note that you need to
+ * shift by #PGP_PTAG_OF_CONTENT_TAG_SHIFT bits.
+ *
+ * \see RFC4880 4.2
+ */
+#define PGP_PTAG_OF_CONTENT_TAG_MASK 0x3c
+/** Old Packet Format: Offset for the content tag.
+ * As described at #PGP_PTAG_OF_CONTENT_TAG_MASK the
+ * content tag needs to be shifted after being masked
+ * out from the Packet Tag.
+ *
+ * \see RFC4880 4.2
+ */
+#define PGP_PTAG_OF_CONTENT_TAG_SHIFT 2
+/** Old Packet Format: Mask for length type.
+ * Bits 1 and 0 of the packet tag are the length type
+ * in the old packet format.
+ *
+ * See #pgp_ptag_of_lt_t for the meaning of the values.
+ *
+ * \see RFC4880 4.2
+ */
+#define PGP_PTAG_OF_LENGTH_TYPE_MASK 0x03
+
+/* Maximum block size for symmetric crypto */
+#define PGP_MAX_BLOCK_SIZE 16
+
+/* Maximum key size for symmetric crypto */
+#define PGP_MAX_KEY_SIZE 32
+
+/* Salt size for hashing */
+#define PGP_SALT_SIZE 8
+
+/* Size of the keyid */
+#define PGP_KEY_ID_SIZE 8
+
+/* Size of the fingerprint */
+#define PGP_FINGERPRINT_SIZE 20
+#define PGP_FINGERPRINT_HEX_SIZE (PGP_FINGERPRINT_SIZE * 3) + 1
+
+/* Size of the key grip */
+#define PGP_KEY_GRIP_SIZE 20
+
+/** Old Packet Format Lengths.
+ * Defines the meanings of the 2 bits for length type in the
+ * old packet format.
+ *
+ * \see RFC4880 4.2.1
+ */
+typedef enum {
+    PGP_PTAG_OLD_LEN_1 = 0x00,            /* Packet has a 1 byte length -
+                                           * header is 2 bytes long. */
+    PGP_PTAG_OLD_LEN_2 = 0x01,            /* Packet has a 2 byte length -
+                                           * header is 3 bytes long. */
+    PGP_PTAG_OLD_LEN_4 = 0x02,            /* Packet has a 4 byte
+                                           * length - header is 5 bytes
+                                           * long. */
+    PGP_PTAG_OLD_LEN_INDETERMINATE = 0x03 /* Packet has a
+                                           * indeterminate length. */
+} pgp_ptag_of_lt_t;
+
+/** New Packet Format: Mask for content tag.
+ * In the new packet format the 6 rightmost bits
+ * are the content tag.  This is the mask to apply
+ * to the packet tag.  Note that you need to
+ * shift by #PGP_PTAG_NF_CONTENT_TAG_SHIFT bits.
+ *
+ * \see RFC4880 4.2
+ */
+#define PGP_PTAG_NF_CONTENT_TAG_MASK 0x3f
+/** New Packet Format: Offset for the content tag.
+ * As described at #PGP_PTAG_NF_CONTENT_TAG_MASK the
+ * content tag needs to be shifted after being masked
+ * out from the Packet Tag.
+ *
+ * \see RFC4880 4.2
+ */
+#define PGP_PTAG_NF_CONTENT_TAG_SHIFT 0
+
+#define MDC_PKT_TAG 0xd3
+#define MDC_V1_SIZE 22
+
+typedef enum {
+    PGP_REVOCATION_NO_REASON = 0,
+    PGP_REVOCATION_SUPERSEDED = 1,
+    PGP_REVOCATION_COMPROMISED = 2,
+    PGP_REVOCATION_RETIRED = 3,
+    PGP_REVOCATION_NO_LONGER_VALID = 0x20
+} pgp_revocation_type_t;
+
+/**
+ * @brief OpenPGP packet tags. See section 4.3 of RFC4880 for the detailed description.
+ *
+ */
+typedef enum {
+    PGP_PKT_RESERVED = 0,       /* Reserved - a packet tag must not have this value */
+    PGP_PKT_PK_SESSION_KEY = 1, /* Public-Key Encrypted Session Key Packet */
+    PGP_PKT_SIGNATURE = 2,      /* Signature Packet */
+    PGP_PKT_SK_SESSION_KEY = 3, /* Symmetric-Key Encrypted Session Key Packet */
+    PGP_PKT_ONE_PASS_SIG = 4,   /* One-Pass Signature Packet */
+    PGP_PKT_SECRET_KEY = 5,     /* Secret Key Packet */
+    PGP_PKT_PUBLIC_KEY = 6,     /* Public Key Packet */
+    PGP_PKT_SECRET_SUBKEY = 7,  /* Secret Subkey Packet */
+    PGP_PKT_COMPRESSED = 8,     /* Compressed Data Packet */
+    PGP_PKT_SE_DATA = 9,        /* Symmetrically Encrypted Data Packet */
+    PGP_PKT_MARKER = 10,        /* Marker Packet */
+    PGP_PKT_LITDATA = 11,       /* Literal Data Packet */
+    PGP_PKT_TRUST = 12,         /* Trust Packet */
+    PGP_PKT_USER_ID = 13,       /* User ID Packet */
+    PGP_PKT_PUBLIC_SUBKEY = 14, /* Public Subkey Packet */
+    PGP_PKT_RESERVED2 = 15,     /* Reserved */
+    PGP_PKT_RESERVED3 = 16,     /* Reserved */
+    PGP_PKT_USER_ATTR = 17,     /* User Attribute Packet */
+    PGP_PKT_SE_IP_DATA = 18,    /* Sym. Encrypted and Integrity Protected Data Packet */
+    PGP_PKT_MDC = 19,           /* Modification Detection Code Packet */
+    PGP_PKT_AEAD_ENCRYPTED = 20 /* AEAD Encrypted Data Packet, RFC 4880bis */
+} pgp_pkt_type_t;
+
+/** Public Key Algorithm Numbers.
+ * OpenPGP assigns a unique Algorithm Number to each algorithm that is part of OpenPGP.
+ *
+ * This lists algorithm numbers for public key algorithms.
+ *
+ * \see RFC4880 9.1
+ */
+typedef enum {
+    PGP_PKA_NOTHING = 0,                  /* No PKA */
+    PGP_PKA_RSA = 1,                      /* RSA (Encrypt or Sign) */
+    PGP_PKA_RSA_ENCRYPT_ONLY = 2,         /* RSA Encrypt-Only (deprecated -
+                                           * \see RFC4880 13.5) */
+    PGP_PKA_RSA_SIGN_ONLY = 3,            /* RSA Sign-Only (deprecated -
+                                           * \see RFC4880 13.5) */
+    PGP_PKA_ELGAMAL = 16,                 /* Elgamal (Encrypt-Only) */
+    PGP_PKA_DSA = 17,                     /* DSA (Digital Signature Algorithm) */
+    PGP_PKA_ECDH = 18,                    /* ECDH public key algorithm */
+    PGP_PKA_ECDSA = 19,                   /* ECDSA public key algorithm [FIPS186-3] */
+    PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN = 20, /* Elgamal Encrypt or Sign. Implementation MUST not
+                                             generate such keys and elgamal signatures. */
+    PGP_PKA_RESERVED_DH = 21,             /* Reserved for Diffie-Hellman
+                                           * (X9.42, as defined for
+                                           * IETF-S/MIME) */
+    PGP_PKA_EDDSA = 22,                   /* EdDSA from draft-ietf-openpgp-rfc4880bis */
+    PGP_PKA_SM2 = 99,                     /* SM2 encryption/signature schemes */
+
+    PGP_PKA_PRIVATE00 = 100, /* Private/Experimental Algorithm */
+    PGP_PKA_PRIVATE01 = 101, /* Private/Experimental Algorithm */
+    PGP_PKA_PRIVATE02 = 102, /* Private/Experimental Algorithm */
+    PGP_PKA_PRIVATE03 = 103, /* Private/Experimental Algorithm */
+    PGP_PKA_PRIVATE04 = 104, /* Private/Experimental Algorithm */
+    PGP_PKA_PRIVATE05 = 105, /* Private/Experimental Algorithm */
+    PGP_PKA_PRIVATE06 = 106, /* Private/Experimental Algorithm */
+    PGP_PKA_PRIVATE07 = 107, /* Private/Experimental Algorithm */
+    PGP_PKA_PRIVATE08 = 108, /* Private/Experimental Algorithm */
+    PGP_PKA_PRIVATE09 = 109, /* Private/Experimental Algorithm */
+    PGP_PKA_PRIVATE10 = 110  /* Private/Experimental Algorithm */
+} pgp_pubkey_alg_t;
+
+/**
+ * Enumeration of elliptic curves used by PGP.
+ *
+ * \see RFC4880-bis01 9.2. ECC Curve OID
+ *
+ * Values in this enum correspond to order in ec_curve array (in ec.c)
+ */
+typedef enum {
+    PGP_CURVE_UNKNOWN = 0,
+    PGP_CURVE_NIST_P_256,
+    PGP_CURVE_NIST_P_384,
+    PGP_CURVE_NIST_P_521,
+    PGP_CURVE_ED25519,
+    PGP_CURVE_25519,
+    PGP_CURVE_BP256,
+    PGP_CURVE_BP384,
+    PGP_CURVE_BP512,
+    PGP_CURVE_P256K1,
+
+    PGP_CURVE_SM2_P_256,
+
+    // Keep always last one
+    PGP_CURVE_MAX
+} pgp_curve_t;
+
+/** Symmetric Key Algorithm Numbers.
+ * OpenPGP assigns a unique Algorithm Number to each algorithm that is
+ * part of OpenPGP.
+ *
+ * This lists algorithm numbers for symmetric key algorithms.
+ *
+ * \see RFC4880 9.2
+ */
+typedef enum {
+    PGP_SA_PLAINTEXT = 0,     /* Plaintext or unencrypted data */
+    PGP_SA_IDEA = 1,          /* IDEA */
+    PGP_SA_TRIPLEDES = 2,     /* TripleDES */
+    PGP_SA_CAST5 = 3,         /* CAST5 */
+    PGP_SA_BLOWFISH = 4,      /* Blowfish */
+    PGP_SA_AES_128 = 7,       /* AES with 128-bit key (AES) */
+    PGP_SA_AES_192 = 8,       /* AES with 192-bit key */
+    PGP_SA_AES_256 = 9,       /* AES with 256-bit key */
+    PGP_SA_TWOFISH = 10,      /* Twofish with 256-bit key (TWOFISH) */
+    PGP_SA_CAMELLIA_128 = 11, /* Camellia with 128-bit key (CAMELLIA) */
+    PGP_SA_CAMELLIA_192 = 12, /* Camellia with 192-bit key */
+    PGP_SA_CAMELLIA_256 = 13, /* Camellia with 256-bit key */
+
+    PGP_SA_SM4 = 105, /* RNP extension - SM4 */
+    PGP_SA_UNKNOWN = 255
+} pgp_symm_alg_t;
+
+typedef enum {
+    PGP_CIPHER_MODE_NONE = 0,
+    PGP_CIPHER_MODE_CFB = 1,
+    PGP_CIPHER_MODE_CBC = 2,
+    PGP_CIPHER_MODE_OCB = 3,
+} pgp_cipher_mode_t;
+
+typedef enum {
+    PGP_AEAD_NONE = 0,
+    PGP_AEAD_EAX = 1,
+    PGP_AEAD_OCB = 2,
+    PGP_AEAD_UNKNOWN = 255
+} pgp_aead_alg_t;
+
+/** s2k_usage_t
+ */
+typedef enum {
+    PGP_S2KU_NONE = 0,
+    PGP_S2KU_ENCRYPTED_AND_HASHED = 254,
+    PGP_S2KU_ENCRYPTED = 255
+} pgp_s2k_usage_t;
+
+/** s2k_specifier_t
+ */
+typedef enum {
+    PGP_S2KS_SIMPLE = 0,
+    PGP_S2KS_SALTED = 1,
+    PGP_S2KS_ITERATED_AND_SALTED = 3
+} pgp_s2k_specifier_t;
+
+/** Signature Type.
+ * OpenPGP defines different signature types that allow giving
+ * different meanings to signatures.  Signature types include 0x10 for
+ * generitc User ID certifications (used when Ben signs Weasel's key),
+ * Subkey binding signatures, document signatures, key revocations,
+ * etc.
+ *
+ * Different types are used in different places, and most make only
+ * sense in their intended location (for instance a subkey binding has
+ * no place on a UserID).
+ *
+ * \see RFC4880 5.2.1
+ */
+typedef enum {
+    PGP_SIG_BINARY = 0x00,     /* Signature of a binary document */
+    PGP_SIG_TEXT = 0x01,       /* Signature of a canonical text document */
+    PGP_SIG_STANDALONE = 0x02, /* Standalone signature */
+
+    PGP_CERT_GENERIC = 0x10,  /* Generic certification of a User ID and
+                               * Public Key packet */
+    PGP_CERT_PERSONA = 0x11,  /* Persona certification of a User ID and
+                               * Public Key packet */
+    PGP_CERT_CASUAL = 0x12,   /* Casual certification of a User ID and
+                               * Public Key packet */
+    PGP_CERT_POSITIVE = 0x13, /* Positive certification of a
+                               * User ID and Public Key packet */
+
+    PGP_SIG_SUBKEY = 0x18,  /* Subkey Binding Signature */
+    PGP_SIG_PRIMARY = 0x19, /* Primary Key Binding Signature */
+    PGP_SIG_DIRECT = 0x1f,  /* Signature directly on a key */
+
+    PGP_SIG_REV_KEY = 0x20,    /* Key revocation signature */
+    PGP_SIG_REV_SUBKEY = 0x28, /* Subkey revocation signature */
+    PGP_SIG_REV_CERT = 0x30,   /* Certification revocation signature */
+
+    PGP_SIG_TIMESTAMP = 0x40, /* Timestamp signature */
+
+    PGP_SIG_3RD_PARTY = 0x50 /* Third-Party Confirmation signature */
+} pgp_sig_type_t;
+
+/** Signature Subpacket Type
+ * Signature subpackets contains additional information about the signature
+ *
+ * \see RFC4880 5.2.3.1-5.2.3.26
+ */
+
+typedef enum {
+    PGP_SIG_SUBPKT_CREATION_TIME = 2,       /* signature creation time */
+    PGP_SIG_SUBPKT_EXPIRATION_TIME = 3,     /* signature expiration time */
+    PGP_SIG_SUBPKT_EXPORT_CERT = 4,         /* exportable certification */
+    PGP_SIG_SUBPKT_TRUST = 5,               /* trust signature */
+    PGP_SIG_SUBPKT_REGEXP = 6,              /* regular expression */
+    PGP_SIG_SUBPKT_REVOCABLE = 7,           /* revocable */
+    PGP_SIG_SUBPKT_KEY_EXPIRY = 9,          /* key expiration time */
+    PGP_SIG_SUBPKT_RESERVED = 10,           /* reserved */
+    PGP_SIG_SUBPKT_PREFERRED_SKA = 11,      /* preferred symmetric algs */
+    PGP_SIG_SUBPKT_REVOCATION_KEY = 12,     /* revocation key */
+    PGP_SIG_SUBPKT_ISSUER_KEY_ID = 16,      /* issuer key ID */
+    PGP_SIG_SUBPKT_NOTATION_DATA = 20,      /* notation data */
+    PGP_SIG_SUBPKT_PREFERRED_HASH = 21,     /* preferred hash algs */
+    PGP_SIG_SUBPKT_PREF_COMPRESS = 22,      /* preferred compression algorithms */
+    PGP_SIG_SUBPKT_KEYSERV_PREFS = 23,      /* key server preferences */
+    PGP_SIG_SUBPKT_PREF_KEYSERV = 24,       /* preferred key Server */
+    PGP_SIG_SUBPKT_PRIMARY_USER_ID = 25,    /* primary user ID */
+    PGP_SIG_SUBPKT_POLICY_URI = 26,         /* policy URI */
+    PGP_SIG_SUBPKT_KEY_FLAGS = 27,          /* key flags */
+    PGP_SIG_SUBPKT_SIGNERS_USER_ID = 28,    /* signer's user ID */
+    PGP_SIG_SUBPKT_REVOCATION_REASON = 29,  /* reason for revocation */
+    PGP_SIG_SUBPKT_FEATURES = 30,           /* features */
+    PGP_SIG_SUBPKT_SIGNATURE_TARGET = 31,   /* signature target */
+    PGP_SIG_SUBPKT_EMBEDDED_SIGNATURE = 32, /* embedded signature */
+    PGP_SIG_SUBPKT_ISSUER_FPR = 33,         /* issuer fingerprint */
+    PGP_SIG_SUBPKT_PREFERRED_AEAD = 34      /* preferred AEAD algorithms */
+} pgp_sig_subpacket_type_t;
+
+/** Key Flags
+ *
+ * \see RFC4880 5.2.3.21
+ */
+typedef enum {
+    PGP_KF_CERTIFY = 0x01,         /* This key may be used to certify other keys. */
+    PGP_KF_SIGN = 0x02,            /* This key may be used to sign data. */
+    PGP_KF_ENCRYPT_COMMS = 0x04,   /* This key may be used to encrypt communications. */
+    PGP_KF_ENCRYPT_STORAGE = 0x08, /* This key may be used to encrypt storage. */
+    PGP_KF_SPLIT = 0x10,           /* The private component of this key may have been split
+                                            by a secret-sharing mechanism. */
+    PGP_KF_AUTH = 0x20,            /* This key may be used for authentication. */
+    PGP_KF_SHARED = 0x80,          /* The private component of this key may be in the
+                                            possession of more than one person. */
+    /* pseudo flags */
+    PGP_KF_NONE = 0x00,
+    PGP_KF_ENCRYPT = PGP_KF_ENCRYPT_COMMS | PGP_KF_ENCRYPT_STORAGE,
+} pgp_key_flags_t;
+
+/** Types of Compression */
+typedef enum {
+    PGP_C_NONE = 0,
+    PGP_C_ZIP = 1,
+    PGP_C_ZLIB = 2,
+    PGP_C_BZIP2 = 3,
+    PGP_C_UNKNOWN = 255
+} pgp_compression_type_t;
+
+enum { PGP_SE_IP_DATA_VERSION = 1, PGP_PKSK_V3 = 3, PGP_SKSK_V4 = 4, PGP_SKSK_V5 = 5 };
+
+/** Version.
+ * OpenPGP has two different protocol versions: version 3 and version 4.
+ *
+ * \see RFC4880 5.2
+ */
+typedef enum {
+    PGP_V2 = 2, /* Version 2 (essentially the same as v3) */
+    PGP_V3 = 3, /* Version 3 */
+    PGP_V4 = 4  /* Version 4 */
+} pgp_version_t;
+
+typedef enum pgp_op_t {
+    PGP_OP_UNKNOWN = 0,
+    PGP_OP_ADD_SUBKEY = 1,  /* adding a subkey, primary key password required */
+    PGP_OP_SIGN = 2,        /* signing file or data */
+    PGP_OP_DECRYPT = 3,     /* decrypting file or data */
+    PGP_OP_UNLOCK = 4,      /* unlocking a key with pgp_key_unlock */
+    PGP_OP_PROTECT = 5,     /* adding protection to a key */
+    PGP_OP_UNPROTECT = 6,   /* removing protection from a (locked) key */
+    PGP_OP_DECRYPT_SYM = 7, /* symmetric decryption */
+    PGP_OP_ENCRYPT_SYM = 8, /* symmetric encryption */
+    PGP_OP_VERIFY = 9,      /* signature verification */
+    PGP_OP_ADD_USERID = 10, /* adding a userid */
+    PGP_OP_MERGE_INFO = 11, /* merging information from one key to another */
+    PGP_OP_ENCRYPT = 12     /* public-key encryption */
+} pgp_op_t;
+
+/** Hashing Algorithm Numbers.
+ * OpenPGP assigns a unique Algorithm Number to each algorithm that is
+ * part of OpenPGP.
+ *
+ * This lists algorithm numbers for hash algorithms.
+ *
+ * \see RFC4880 9.4
+ */
+typedef enum {
+    PGP_HASH_UNKNOWN = 0, /* used to indicate errors */
+    PGP_HASH_MD5 = 1,
+    PGP_HASH_SHA1 = 2,
+    PGP_HASH_RIPEMD = 3,
+
+    PGP_HASH_SHA256 = 8,
+    PGP_HASH_SHA384 = 9,
+    PGP_HASH_SHA512 = 10,
+    PGP_HASH_SHA224 = 11,
+    PGP_HASH_SHA3_256 = 12,
+    PGP_HASH_SHA3_512 = 14,
+
+    /* Private range */
+    PGP_HASH_SM3 = 105,
+    PGP_HASH_CRC24 = 106
+} pgp_hash_alg_t;
+
+#endif
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/include/rnp.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com).
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is originally derived from software contributed to
+ * The NetBSD Foundation by Alistair Crooks (agc@netbsd.org), and
+ * carried further by Ribose Inc (https://www.ribose.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RNP_RNP_H
+#define RNP_RNP_H
+
+#include "types.h"
+#include "pass-provider.h"
+#include "key-provider.h"
+#include "list.h"
+#include "crypto/rng.h"
+#include <rnp/rnp_def.h>
+#include <rekey/rnp_key_store.h>
+#include "utils.h"
+
+#endif // RNP_RNP_H
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/include/rnp/rnp.h
@@ -0,0 +1,2128 @@
+/*-
+ * Copyright (c) 2017,2018 Ribose Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ * Function return type. 0 == SUCCESS, all other values indicate an error.
+ */
+typedef uint32_t rnp_result_t;
+
+#define RNP_KEY_EXPORT_ARMORED (1U << 0)
+#define RNP_KEY_EXPORT_PUBLIC (1U << 1)
+#define RNP_KEY_EXPORT_SECRET (1U << 2)
+#define RNP_KEY_EXPORT_SUBKEYS (1U << 3)
+
+#define RNP_KEY_REMOVE_PUBLIC (1U << 0)
+#define RNP_KEY_REMOVE_SECRET (1U << 1)
+
+#define RNP_KEY_UNLOAD_PUBLIC (1U << 0)
+#define RNP_KEY_UNLOAD_SECRET (1U << 1)
+
+/**
+ * Flags for optional details to include in JSON.
+ */
+#define RNP_JSON_PUBLIC_MPIS (1U << 0)
+#define RNP_JSON_SECRET_MPIS (1U << 1)
+#define RNP_JSON_SIGNATURES (1U << 2)
+#define RNP_JSON_SIGNATURE_MPIS (1U << 3)
+
+/**
+ * Flags to include additional data in packet dumping
+ */
+#define RNP_JSON_DUMP_MPI (1U << 0)
+#define RNP_JSON_DUMP_RAW (1U << 1)
+#define RNP_JSON_DUMP_GRIP (1U << 2)
+
+#define RNP_DUMP_MPI (1U << 0)
+#define RNP_DUMP_RAW (1U << 1)
+#define RNP_DUMP_GRIP (1U << 2)
+
+/**
+ * Flags for the key loading/saving functions.
+ */
+#define RNP_LOAD_SAVE_PUBLIC_KEYS (1U << 0)
+#define RNP_LOAD_SAVE_SECRET_KEYS (1U << 1)
+
+/**
+ * Flags for output structure creation.
+ */
+#define RNP_OUTPUT_FILE_OVERWRITE (1U << 0)
+#define RNP_OUTPUT_FILE_RANDOM (1U << 1)
+
+/**
+ * Return a constant string describing the result code
+ */
+const char *rnp_result_to_string(rnp_result_t result);
+
+const char *rnp_version_string();
+const char *rnp_version_string_full();
+
+/** return a value representing the version of librnp
+ *
+ *  This function is only useful for releases. For non-releases,
+ *  it will return 0.
+ *
+ *  The value returned can be used in comparisons by utilizing
+ *  rnp_version_for.
+ *
+ *  @return a value representing the librnp version
+ **/
+uint32_t rnp_version();
+
+/** return a value representing a specific version of librnp
+ *
+ *  This value can be used in comparisons.
+ *
+ *  @return a value representing a librnp version
+ **/
+uint32_t rnp_version_for(uint32_t major, uint32_t minor, uint32_t patch);
+
+/** return the librnp major version
+ *
+ *  @return
+ **/
+uint32_t rnp_version_major(uint32_t version);
+
+/** return the librnp minor version
+ *
+ *  @return
+ **/
+uint32_t rnp_version_minor(uint32_t version);
+
+/** return the librnp patch version
+ *
+ *  @return
+ **/
+uint32_t rnp_version_patch(uint32_t version);
+
+/** return a unix timestamp of the last commit, if available
+ *
+ *  This function is only useful for non-releases. For releases,
+ *  it will return 0.
+ *
+ *  The intended usage is to provide a form of versioning for the master
+ *  branch.
+ *
+ *  @return the unix timestamp of the last commit, or 0 if unavailable
+ **/
+uint64_t rnp_version_commit_timestamp();
+
+/** Enable debugging for the specified source file. Use 'all' or NULL as parameter to
+ *  enable debug for all sources.
+ *  Note: this must be only used during development since may print out confidential data.
+ *
+ * @param file name of the sourcer file. Use 'all' to enable debug for all code.
+ */
+rnp_result_t rnp_enable_debug(const char *file);
+
+/**
+ * @brief Disable previously enabled debug for all files.
+ *
+ */
+rnp_result_t rnp_disable_debug();
+
+/*
+ * Opaque structures
+ */
+typedef struct rnp_ffi_st *                rnp_ffi_t;
+typedef struct rnp_key_handle_st *         rnp_key_handle_t;
+typedef struct rnp_input_st *              rnp_input_t;
+typedef struct rnp_output_st *             rnp_output_t;
+typedef struct rnp_op_generate_st *        rnp_op_generate_t;
+typedef struct rnp_op_sign_st *            rnp_op_sign_t;
+typedef struct rnp_op_sign_signature_st *  rnp_op_sign_signature_t;
+typedef struct rnp_op_verify_st *          rnp_op_verify_t;
+typedef struct rnp_op_verify_signature_st *rnp_op_verify_signature_t;
+typedef struct rnp_op_encrypt_st *         rnp_op_encrypt_t;
+typedef struct rnp_identifier_iterator_st *rnp_identifier_iterator_t;
+typedef struct rnp_uid_handle_st *         rnp_uid_handle_t;
+typedef struct rnp_signature_handle_st *   rnp_signature_handle_t;
+
+/* Callbacks */
+/**
+ * @brief Callback, used to read data from the source.
+ *
+ * @param app_ctx custom parameter, passed back to the function.
+ * @param buf on successfull call data should be put here. Cannot be NULL,
+ *            and must be capable to store at least len bytes.
+ * @param len number of bytes to read.
+ * @param read on successfull call number of read bytes must be put here.
+ * @return true on success (including EOF condition), or false on read error.
+ *         EOF case is indicated by zero bytes read on non-zero read call.
+ */
+typedef bool rnp_input_reader_t(void *app_ctx, void *buf, size_t len, size_t *read);
+/**
+ * @brief Callback, used to close input stream.
+ *
+ * @param app_ctx custom parameter, passed back to the function.
+ * @return void
+ */
+typedef void rnp_input_closer_t(void *app_ctx);
+/**
+ * @brief Callback, used to write data to the output stream.
+ *
+ * @param app_ctx custom parameter, passed back to the function.
+ * @param buf buffer with data, cannot be NULL.
+ * @param len number of bytes to write.
+ * @return true if call was successfull and all data is written, or false otherwise.
+ */
+typedef bool rnp_output_writer_t(void *app_ctx, const void *buf, size_t len);
+
+/**
+ * @brief Callback, used to close output stream.
+ *
+ * @param app_ctx custom parameter, passed back to the function.
+ * @param discard true if the already written data should be deleted.
+ * @return void
+ */
+typedef void rnp_output_closer_t(void *app_ctx, bool discard);
+
+/**
+ * Callback used for getting a password.
+ *
+ * @param ffi
+ * @param app_ctx provided by application
+ * @param key the key, if any, for which the password is being requested.
+ *        Note: this key handle should not be held by the application,
+ *        it is destroyed after the callback. It should only be used to
+ *        retrieve information like the userids, grip, etc.
+ * @param pgp_context a descriptive string on why the password is being
+ *        requested, may have one of the following values:
+ *         - "add subkey": add subkey to the encrypted secret key
+ *         - "add userid": add userid to the encrypted secret key
+ *         - "sign": sign data
+ *         - "decrypt": decrypt data using the encrypted secret key
+ *         - "unlock": temporary unlock secret key (decrypting it's fields), so it may be used
+ *           later without need to decrypt
+ *         - "protect": encrypt secret key fields
+ *         - "unprotect": decrypt secret key fields, leaving those in a raw format
+ *         - "decrypt (symmetric)": decrypt data, using the password
+ *         - "encrypt (symmetric)": encrypt data, using the password
+ * @param buf to which the callback should write the returned password, NULL terminated.
+ * @param buf_len the size of buf
+ * @return true if a password was provided, false otherwise
+ */
+typedef bool (*rnp_password_cb)(rnp_ffi_t        ffi,
+                                void *           app_ctx,
+                                rnp_key_handle_t key,
+                                const char *     pgp_context,
+                                char             buf[],
+                                size_t           buf_len);
+
+/** callback used to signal the application that a key is needed
+ *
+ *  The application should use the appropriate functions (rnp_load_public_keys, etc)
+ *  to load the requested key.
+ *
+ *  This may be called multiple times for the same key. For example, if attempting
+ *  to verify a signature, the signer's keyid may be used first to request the key.
+ *  If that is not successful, the signer's fingerprint (if available) may be used.
+ *
+ *  Situations in which this callback would be used include:
+ *   - When decrypting data that includes a public-key encrypted session key,
+ *     and the key is not found in the keyrings.
+ *   - When attempting to verify a signature, when the signer's key is not found in
+ *     the keyrings.
+ *
+ *  @param ffi
+ *  @param app_ctx provided by application in rnp_keyring_open
+ *  @param identifier_type the type of identifier ("userid", "keyid", "grip")
+ *  @param identifier the identifier for locating the key
+ *  @param secret true if a secret key is being requested
+ */
+typedef void (*rnp_get_key_cb)(rnp_ffi_t   ffi,
+                               void *      app_ctx,
+                               const char *identifier_type,
+                               const char *identifier,
+                               bool        secret);
+
+/** create the top-level object used for interacting with the library
+ *
+ *  @param ffi pointer that will be set to the created ffi object
+ *  @param pub_format the format of the public keyring, RNP_KEYSTORE_GPG or other
+ *         RNP_KEYSTORE_* constant
+ *  @param sec_format the format of the secret keyring, RNP_KEYSTORE_GPG or other
+ *         RNP_KEYSTORE_* constant
+ *  @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_ffi_create(rnp_ffi_t *ffi, const char *pub_format, const char *sec_format);
+
+/** destroy the top-level object used for interacting with the library
+ *
+ *  Note that this invalidates key handles, keyrings, and any other
+ *  objects associated with this particular object.
+ *
+ *  @param ffi the ffi object
+ *  @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_ffi_destroy(rnp_ffi_t ffi);
+
+rnp_result_t rnp_ffi_set_log_fd(rnp_ffi_t ffi, int fd);
+rnp_result_t rnp_ffi_set_key_provider(rnp_ffi_t      ffi,
+                                      rnp_get_key_cb getkeycb,
+                                      void *         getkeycb_ctx);
+rnp_result_t rnp_ffi_set_pass_provider(rnp_ffi_t       ffi,
+                                       rnp_password_cb getpasscb,
+                                       void *          getpasscb_ctx);
+
+/* Operations on key rings */
+
+/** retrieve the default homedir (example: /home/user/.rnp)
+ *
+ * @param homedir pointer that will be set to the homedir path.
+ *        The caller should free this with rnp_buffer_free.
+ * @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_get_default_homedir(char **homedir);
+
+/** try to detect the formats and paths of the homedir keyrings
+ *
+ * @param homedir the path to the home directory (example: /home/user/.rnp)
+ * @param pub_format pointer that will be set to the format of the public keyring.
+ *        The caller should free this with rnp_buffer_free.
+ * @param pub_path pointer that will be set to the path to the public keyring.
+ *        The caller should free this with rnp_buffer_free.
+ * @param sec_format pointer that will be set to the format of the secret keyring.
+ *        The caller should free this with rnp_buffer_free.
+ * @param sec_path pointer that will be set to the path to the secret keyring.
+ *        The caller should free this with rnp_buffer_free.
+ * @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_detect_homedir_info(
+  const char *homedir, char **pub_format, char **pub_path, char **sec_format, char **sec_path);
+
+/** try to detect the key format of the provided data
+ *
+ * @param buf the key data, must not be NULL
+ * @param buf_len the size of the buffer, must be > 0
+ * @param format pointer that will be set to the format of the keyring.
+ *        Must not be NULL. The caller should free this with rnp_buffer_free.
+ * @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_detect_key_format(const uint8_t buf[], size_t buf_len, char **format);
+
+/** Get the number of s2k hash iterations, based on calculation time requested.
+ *  Number of iterations is used to derive encryption key from password.
+ *
+ * @param hash hash algorithm to try
+ * @param msec number of milliseconds which will be needed to derive key from the password.
+ *             Since it depends on CPU speed the calculated value will make sense only for the
+ *             system it was calculated for.
+ * @param iterations approximate number of iterations to satisfy time complexity.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_calculate_iterations(const char *hash, size_t msec, size_t *iterations);
+
+/** Check whether rnp supports specific feature (algorithm, elliptic curve, whatever else).
+ *
+ * @param type string with the feature type:
+ *             - 'symmetric algorithm'
+ *             - 'aead algorithm'
+ *             - 'protection mode'
+ *             - 'public key algorithm'
+ *             - 'hash algorithm'
+ *             - 'compression algorithm'
+ *             - 'elliptic curve'
+ * @param name value of the feature to check whether it is supported.
+ * @param supported will contain true or false depending whether feature is supported or not.
+ * @return RNP_SUCCESS on success or any other value on error.
+ */
+rnp_result_t rnp_supports_feature(const char *type, const char *name, bool *supported);
+
+/** Get the JSON with array of supported rnp feature values (algorithms, curves, etc) by type.
+ *
+ * @param type type of the feature. See rnp_supports_feature() function for possible values.
+ * @param result after successfull execution will contain the JSON with supported feature
+ * values. You must destroy it using the rnp_buffer_destroy() function.
+ * @return RNP_SUCCESS on success or any other value on error.
+ */
+rnp_result_t rnp_supported_features(const char *type, char **result);
+
+/**
+ * @brief Request password via configured FFI's callback
+ *
+ * @param ffi initialized FFI structure
+ * @param key key handle for which password is requested. May be NULL.
+ * @param context string describing the purpose of password request. See description of
+ *                rnp_password_cb for the list of possible values. Also you may use any
+ *                custom one as far as your password callback handles it.
+ * @param password password will be put here on success. Must be destroyed via
+ *                 rnp_buffer_destroy(), also it is good idea to securely clear it via
+ *                 rnp_buffer_clear().
+ * @return RNP_SUCCESS or other value on error.
+ */
+rnp_result_t rnp_request_password(rnp_ffi_t        ffi,
+                                  rnp_key_handle_t key,
+                                  const char *     context,
+                                  char **          password);
+
+/** load keys
+ *
+ * Note that for G10, the input must be a directory (which must already exist).
+ *
+ * @param ffi
+ * @param format the key format of the data (GPG, KBX, G10). Must not be NULL.
+ * @param input source to read from.
+ * @param flags the flags. See RNP_LOAD_SAVE_*.
+ * @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_load_keys(rnp_ffi_t   ffi,
+                           const char *format,
+                           rnp_input_t input,
+                           uint32_t    flags);
+
+/** unload public and/or secret keys
+ *  Note: After unloading all key handles will become invalid and must be destroyed.
+ * @param ffi
+ * @param flags choose which keys should be unloaded (pubic, secret or both).
+ *              See RNP_KEY_UNLOAD_PUBLIC/RNP_KEY_UNLOAD_SECRET.
+ * @return RNP_SUCCESS on success, or any other value on error.
+ */
+rnp_result_t rnp_unload_keys(rnp_ffi_t ffi, uint32_t flags);
+
+/** import keys to the keyring and receive JSON list of the new/updated keys.
+ *  Note: this will work only with keys in OpenPGP format, use rnp_load_keys for other formats.
+ * @param ffi
+ * @param input source to read from. Cannot be NULL.
+ * @param flags see RNP_LOAD_SAVE_* constants.
+ * @param results if not NULL then after the successfull execution will contain JSON with
+ *                information about new and updated keys. You must free it using the
+ *                rnp_buffer_destroy() function.
+ * @return RNP_SUCCESS on success, or any other value on error.
+ */
+rnp_result_t rnp_import_keys(rnp_ffi_t ffi, rnp_input_t input, uint32_t flags, char **results);
+
+/** import standalone signatures to the keyring and receive JSON list of the updated keys.
+ *
+ *  @param ffi
+ *  @param input source to read from. Cannot be NULL.
+ *  @param flags additional import flags, currently must be 0.
+ *  @param results if not NULL then after the successfull execution will contain JSON with
+ *                 information about the updated keys. You must free it using the
+ *                 rnp_buffer_destroy() function.
+ *  @return RNP_SUCCESS on success, or any other value on error.
+ */
+rnp_result_t rnp_import_signatures(rnp_ffi_t   ffi,
+                                   rnp_input_t input,
+                                   uint32_t    flags,
+                                   char **     results);
+
+/** save keys
+ *
+ * Note that for G10, the output must be a directory (which must already exist).
+ *
+ * @param ffi
+ * @param format the key format of the data (GPG, KBX, G10). Must not be NULL.
+ * @param output the output destination to write to.
+ * @param flags the flags. See RNP_LOAD_SAVE_*.
+ * @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_save_keys(rnp_ffi_t    ffi,
+                           const char * format,
+                           rnp_output_t output,
+                           uint32_t     flags);
+
+rnp_result_t rnp_get_public_key_count(rnp_ffi_t ffi, size_t *count);
+rnp_result_t rnp_get_secret_key_count(rnp_ffi_t ffi, size_t *count);
+
+/** search for the key
+ *
+ *  @param ffi
+ *  @param identifier_type string with type of the identifier: userid, keyid, fingerprint, grip
+ *  @param identifier for userid is the userid string, for other search types - hex string
+ *         representation of the value
+ *  @param key if key was found then the resulting key handle will be stored here, otherwise it
+ *         will contain NULL value. You must free handle after use with rnp_key_handle_destroy.
+ *  @return RNP_SUCCESS on success (including case where key is not found), or any other value
+ * on error
+ */
+rnp_result_t rnp_locate_key(rnp_ffi_t         ffi,
+                            const char *      identifier_type,
+                            const char *      identifier,
+                            rnp_key_handle_t *key);
+
+rnp_result_t rnp_key_handle_destroy(rnp_key_handle_t key);
+
+/** generate a key or pair of keys using a JSON description
+ *
+ *  Notes:
+ *  - When generating a subkey, the  pass provider may be required.
+ *
+ *  @param ffi
+ *  @param json the json data that describes the key generation.
+ *         Must not be NULL.
+ *  @param results pointer that will be set to the JSON results.
+ *         Must not be NULL. The caller should free this with rnp_buffer_destroy.
+ *  @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_generate_key_json(rnp_ffi_t ffi, const char *json, char **results);
+
+/* Key operations */
+
+/** Shortcut function for rsa key-subkey pair generation. See rnp_generate_key_ex() for the
+ *  detailed parameters description.
+ */
+rnp_result_t rnp_generate_key_rsa(rnp_ffi_t         ffi,
+                                  uint32_t          bits,
+                                  uint32_t          subbits,
+                                  const char *      userid,
+                                  const char *      password,
+                                  rnp_key_handle_t *key);
+
+/** Shortcut function for DSA/ElGamal key-subkey pair generation. See rnp_generate_key_ex() for
+ *  the detailed parameters description.
+ */
+rnp_result_t rnp_generate_key_dsa_eg(rnp_ffi_t         ffi,
+                                     uint32_t          bits,
+                                     uint32_t          subbits,
+                                     const char *      userid,
+                                     const char *      password,
+                                     rnp_key_handle_t *key);
+
+/** Shortcut function for ECDSA/ECDH key-subkey pair generation. See rnp_generate_key_ex() for
+ *  the detailed parameters description.
+ */
+rnp_result_t rnp_generate_key_ec(rnp_ffi_t         ffi,
+                                 const char *      curve,
+                                 const char *      userid,
+                                 const char *      password,
+                                 rnp_key_handle_t *key);
+
+/** Shortcut function for EdDSA/x25519 key-subkey pair generation. See rnp_generate_key_ex()
+ *  for the detailed parameters description.
+ */
+rnp_result_t rnp_generate_key_25519(rnp_ffi_t         ffi,
+                                    const char *      userid,
+                                    const char *      password,
+                                    rnp_key_handle_t *key);
+
+/** Shortcut function for SM2/SM2 key-subkey pair generation. See rnp_generate_key_ex() for
+ *  for the detailed parameters description.
+ */
+rnp_result_t rnp_generate_key_sm2(rnp_ffi_t         ffi,
+                                  const char *      userid,
+                                  const char *      password,
+                                  rnp_key_handle_t *key);
+
+/**
+ * @brief Shortcut for quick key generation. While it is used in other shortcut functions for
+ *        key generation
+ *
+ * @param ffi
+ * @param key_alg string with primary key algorithm. Cannot be NULL.
+ * @param sub_alg string with subkey algorithm. If NULL then subkey will not be generated.
+ * @param key_bits size of key in bits. If zero then default value will be used.
+ *             Must be zero for EC-based primary key algorithm (use curve instead).
+ * @param sub_bits size of subkey in bits. If zero then default value will be used.
+ *              Must be zero for EC-based subkey algorithm (use scurve instead).
+ * @param key_curve Curve name. Must be non-NULL only with EC-based primary key algorithm,
+ *              otherwise error will be returned.
+ * @param sub_curve Subkey curve name. Must be non-NULL only with EC-based subkey algorithm,
+ *               otherwise error will be returned.
+ * @param userid String with userid. Cannot be NULL.
+ * @param key if non-NULL, then handle of the primary key will be stored here on success.
+ *            Caller must destroy it with rnp_key_handle_destroy() call.
+ * @return RNP_SUCCESS or error code instead.
+ */
+rnp_result_t rnp_generate_key_ex(rnp_ffi_t         ffi,
+                                 const char *      key_alg,
+                                 const char *      sub_alg,
+                                 uint32_t          key_bits,
+                                 uint32_t          sub_bits,
+                                 const char *      key_curve,
+                                 const char *      sub_curve,
+                                 const char *      userid,
+                                 const char *      password,
+                                 rnp_key_handle_t *key);
+
+/** Create key generation context for the primary key.
+ *  To generate a subkey use function rnp_op_generate_subkey_create() instead.
+ *  Note: pass provider is required if generated key needs protection.
+ *
+ * @param op pointer to opaque key generation context.
+ * @param ffi
+ * @param alg key algorithm as string. Must be able to sign. Currently the following algorithms
+ *            are supported (case-insensetive) : 'rsa', 'dsa', 'ecdsa', 'eddsa', 'sm2'.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_create(rnp_op_generate_t *op, rnp_ffi_t ffi, const char *alg);
+
+/** Create key generation context for the subkey.
+ *  Note: you need to have primary key before calling this function. It can be loaded from
+ * keyring or generated via the function rnp_op_generate_create(). Also pass provider is needed
+ * if primary key is encrypted (protected and locked).
+ *
+ * @param op pointer to opaque key generation context.
+ * @param ffi
+ * @param primary primary key handle, must have secret part.
+ * @param alg key algorithm as string. Currently the following algorithms are supported
+ * (case-insensetive) : 'rsa', 'dsa', 'elgamal', 'ecdsa', 'eddsa', 'ecdh', 'sm2'.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_subkey_create(rnp_op_generate_t *op,
+                                           rnp_ffi_t          ffi,
+                                           rnp_key_handle_t   primary,
+                                           const char *       alg);
+
+/** Set bits of the generated key or subkey.
+ *  Note: this is applicable only to rsa, dsa and el-gamal keys.
+ *
+ * @param op pointer to opaque key generation context.
+ * @param bits number of bits
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_set_bits(rnp_op_generate_t op, uint32_t bits);
+
+/** Set hash algorithm used in self signature or subkey binding signature.
+ *
+ * @param op pointer to opaque key generation context.
+ * @param hash string with hash algorithm name. Following hash algorithms are supported:
+ *             "MD5", "SHA1", "RIPEMD160", "SHA256", "SHA384", "SHA512", "SHA224", "SM3"
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_set_hash(rnp_op_generate_t op, const char *hash);
+
+/** Set size of q parameter for DSA key.
+ *  Note: appropriate default value will be set, depending on key bits. However you may
+ *        override it if needed.
+ * @param op pointer to opaque key generation context.
+ * @param qbits number of bits
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_set_dsa_qbits(rnp_op_generate_t op, uint32_t qbits);
+
+/** Set the curve used for ECC key
+ *  Note: this is only applicable for ECDSA, ECDH and SM2 keys.
+ * @param op pointer to opaque key generation context.
+ * @param curve string with curve name. Following curve names may be used:
+ *              "NIST P-256", "NIST P-384", "NIST P-521", "Curve25519" (ECDH only),
+ *              "brainpoolP256r1", "brainpoolP384r1", "brainpoolP512r1", "secp256k1",
+ *              "SM2 P-256" (SM2 only)
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_set_curve(rnp_op_generate_t op, const char *curve);
+
+/** Set password, used to encrypt secret key data. If this method is not called then
+ *  key will be generated without protection (unencrypted).
+ *
+ * @param op pointer to opaque key generation context.
+ * @param password string with password, could not be NULL. Will be copied internally so may
+ *                 be safely freed after the call.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_set_protection_password(rnp_op_generate_t op,
+                                                     const char *      password);
+
+/**
+ * @brief Enable or disable password requesting via ffi's password provider. This password
+ *        then will be used for key encryption.
+ *        Note: this will be ignored if password was set via
+ *        rnp_op_generate_set_protection_password().
+ *
+ * @param op pointer to opaque key generation context.
+ * @param request true to enable password requesting or false otherwise. Default value is false
+ *                (i.e. key will be generated unencrypted).
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_set_request_password(rnp_op_generate_t op, bool request);
+
+/** Set cipher used to encrypt secret key data. If not called then default one will be used.
+ *
+ * @param op pointer to opaque key generation context.
+ * @param cipher string with cipher name. Following ciphers are supported:
+ *               "Idea", "Tripledes", "Cast5", "Blowfish", "AES128", "AES192", "AES256",
+ *               "Twofish", "Camellia128", "Camellia192", "Camellia256", "SM4".
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_set_protection_cipher(rnp_op_generate_t op, const char *cipher);
+
+/** Set hash algorithm, used to derive key from password for secret key data encryption.
+ *  If not called then default one will be used.
+ *
+ * @param op pointer to opaque key generation context.
+ * @param hash string with hash algorithm, see rnp_op_generate_set_hash() for the whole list.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_set_protection_hash(rnp_op_generate_t op, const char *hash);
+
+/** Set encryption mode, used for secret key data encryption.
+ *  Note: currently this makes sense only for G10 key format
+ *
+ * @param op pointer to opaque key generation context.
+ * @param mode string with mode name: "CFB", "CBC", "OCB"
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_set_protection_mode(rnp_op_generate_t op, const char *mode);
+
+/** Set number of iterations used to derive key from password for secret key encryption.
+ *  If not called then default one will be used.
+ *
+ * @param op pointer to opaque key generation context.
+ * @param iterations number of iterations
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_set_protection_iterations(rnp_op_generate_t op,
+                                                       uint32_t          iterations);
+
+/** Add key usage flag to the key or subkey.
+ *  Note: use it only if you need to override defaults, which depend on primary key or subkey,
+ *        and public key algorithm.
+ *
+ * @param op pointer to opaque key generation context.
+ * @param usage string, representing key usage. Following values are supported: "sign",
+ *              "certify", "encrypt", "authenticate".
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_add_usage(rnp_op_generate_t op, const char *usage);
+
+/** Reset key usage flags, so default ones will be used during key/subkey generation
+ *
+ * @param op pointer to opaque key generation context.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_clear_usage(rnp_op_generate_t op);
+
+/** Set the userid which will represent the generate key.
+ *  Note: Makes sense only for primary key generation.
+ *
+ * @param op pointer to opaque key generation context.
+ * @param userid NULL-terminated string with userid.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_set_userid(rnp_op_generate_t op, const char *userid);
+
+/** Set the key or subkey expiration time.
+ *
+ * @param op pointer to opaque key generation context.
+ * @param expiration expiration time in seconds. 0 value means that key doesn't expire.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_set_expiration(rnp_op_generate_t op, uint32_t expiration);
+
+/** Add preferred hash to user preferences.
+ *  Note: the first added hash algorithm has the highest priority, then the second and so on.
+ *        Applicable only for the primary key generation.
+ *
+ * @param op pointer to opaque key generation context.
+ * @param hash string, representing the hash algorithm. See the rnp_op_generate_set_hash()
+ *             function description for the list of possible values.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_add_pref_hash(rnp_op_generate_t op, const char *hash);
+
+/** Clear the preferred hash algorithms list, so default ones will be used.
+ *
+ * @param op pointer to opaque key generation context.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_clear_pref_hashes(rnp_op_generate_t op);
+
+/** Add preferred compression algorithm to user preferences.
+ *  Note: the first added algorithm has the highest priority, then the second and so on.
+ *        Applicable only for the primary key generation.
+ *
+ * @param op pointer to opaque key generation context.
+ * @param compression string, representing the compression algorithm. Possible values are:
+ *                    "zip", "zlib", "bzip2"
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_add_pref_compression(rnp_op_generate_t op,
+                                                  const char *      compression);
+
+/** Clear the preferred compression algorithms list, so default ones will be used.
+ *
+ * @param op pointer to opaque key generation context.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_clear_pref_compression(rnp_op_generate_t op);
+
+/** Add preferred encryption algorithm to user preferences.
+ *  Note: the first added algorithm has the highest priority, then the second and so on.
+ *        Applicable only for the primary key generation.
+ *
+ * @param op pointer to opaque key generation context.
+ * @param cipher string, representing the encryption algorithm.
+ *               See the rnp_op_generate_set_protection_cipher() function description for
+ *               the list of possible values.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_add_pref_cipher(rnp_op_generate_t op, const char *cipher);
+
+/** Clear the preferred encryption algorithms list, so default ones will be used.
+ *
+ * @param op pointer to opaque key generation context.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_clear_pref_ciphers(rnp_op_generate_t op);
+
+/** Set the preferred key server. Applicable only for the primary key.
+ *
+ * @param op pointer to opaque key generation context.
+ * @param keyserver NULL-terminated string with key server's URL, or NULL to delete it from
+ *                  user preferences.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_set_pref_keyserver(rnp_op_generate_t op, const char *keyserver);
+
+/** Execute the prepared key or subkey generation operation.
+ *  Note: if you set protection algorithm, then you need to specify ffi password provider to
+ *        be able to request password for key encryption.
+ *
+ * @param op pointer to opaque key generation context.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_execute(rnp_op_generate_t op);
+
+/** Get the generated key's handle. Should be called only after successfull execution of
+ *  rnp_op_generate_execute().
+ *
+ * @param op pointer to opaque key generation context.
+ * @param handle pointer to key handle will be stored here.
+ *            You must free handle after use with rnp_key_handle_destroy.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_get_key(rnp_op_generate_t op, rnp_key_handle_t *handle);
+
+/** Free resources associated with signing operation.
+ *
+ *  @param op opaque key generation context. Must be successfully initialized with one of the
+ *         rnp_op_generate_*_create functions.
+ *  @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_generate_destroy(rnp_op_generate_t op);
+
+/** export a key
+ *
+ *  @param key the key to export
+ *  @param output the stream to write to
+ *  @param flags see RNP_KEY_EXPORT_*.
+ *  @return RNP_SUCCESS on success, or any other value on error
+ **/
+rnp_result_t rnp_key_export(rnp_key_handle_t key, rnp_output_t output, uint32_t flags);
+
+/**
+ * @brief Generate and export primary key revocation signature.
+ *        Note: to revoke a key you'll need to import this signature into the keystore or use
+ *        rnp_key_revoke() function.
+ * @param key primary key to be revoked. Must have secret key, otherwise keyrings will be
+ *            searched for the authorized to issue revocation signature secret key. If secret
+ *            key is locked then password will be asked via password provider.
+ * @param output signature contents will be saved here.
+ * @param flags currently must be 0.
+ * @param hash hash algorithm used to calculate signature. Pass NULL for default algorithm
+ *             selection.
+ * @param code reason for revocation code. Possible values: 'no', 'superseded', 'compromised',
+ *             'retired'. May be NULL - then 'no' value will be used.
+ * @param reason textual representation of the reason for revocation. May be NULL or empty
+ *               string.
+ * @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_key_export_revocation(rnp_key_handle_t key,
+                                       rnp_output_t     output,
+                                       uint32_t         flags,
+                                       const char *     hash,
+                                       const char *     code,
+                                       const char *     reason);
+
+/** remove a key from keyring(s)
+ *  Note: you need to call rnp_save_keys() to write updated keyring(s) out.
+ *        Other handles of the same key should not be used after this call.
+ * @param key pointer to the key handle.
+ * @param flags see RNP_KEY_REMOVE_* constants.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_remove(rnp_key_handle_t key, uint32_t flags);
+
+/** guess contents of the OpenPGP data stream.
+ *
+ * @param input stream with data. Must be opened and cannot be NULL.
+ * @param contents string with guessed data format will be stored here.
+ *                 Possible values: 'message', 'public key', 'secret key', 'signature',
+ * 'unknown'. May be used as type in rnp_enarmor() function. Must be deallocated with
+ * rnp_buffer_destroy() call.
+ * @return RNP_SUCCESS on success, or any other value on error.
+ */
+rnp_result_t rnp_guess_contents(rnp_input_t input, char **contents);
+
+/** Add ASCII Armor
+ *
+ *  @param input stream to read data from
+ *  @param output stream to write armored data to
+ *  @param type the type of armor to add ("message", "public key",
+ *         "secret key", "signature", "cleartext"). Use NULL to try
+ *         to guess the type.
+ *  @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_enarmor(rnp_input_t input, rnp_output_t output, const char *type);
+
+/** Remove ASCII Armor
+ *
+ *  @param input stream to read armored data from
+ *  @param output stream to write dearmored data to
+ *  @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_dearmor(rnp_input_t input, rnp_output_t output);
+
+/** Get key's primary user id.
+ *
+ * @param key key handle.
+ * @param uid pointer to the string with primary user id will be stored here.
+ *            You must free it using the rnp_buffer_destroy().
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_get_primary_uid(rnp_key_handle_t key, char **uid);
+
+/** Get number of the key's user ids.
+ *
+ * @param key key handle.
+ * @param count number of user ids will be stored here.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_get_uid_count(rnp_key_handle_t key, size_t *count);
+
+/** Get key's user id by it's index.
+ *
+ * @param key key handle.
+ * @param idx zero-based index of the userid.
+ * @param uid pointer to the string with user id will be stored here.
+ *            You must free it using the rnp_buffer_destroy().
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_get_uid_at(rnp_key_handle_t key, size_t idx, char **uid);
+
+/** Get key's user id handle by it's index.
+ *  Note: user id handle may become invalid once corresponding user id or key is removed.
+ *
+ * @param key key handle
+ * @param idx zero-based index of the userid.
+ * @param uid user id handle will be stored here on success. You must destroy it
+ *            using the rnp_uid_handle_destroy().
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_get_uid_handle_at(rnp_key_handle_t  key,
+                                       size_t            idx,
+                                       rnp_uid_handle_t *uid);
+
+/** Get number of key's signatures.
+ *  Note: this will not count user id certifications and subkey(s) signatures if any.
+ *        I.e. it will return only number of direct-key and key revocation signatures for the
+ *        primary key, and number of subkey bindings/revocation signatures for the subkey.
+ *        Use rnp_uid_get_signature_count() or call this function on subkey's handle.
+ *
+ * @param key key handle
+ * @param count number of key's signatures will be stored here.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_get_signature_count(rnp_key_handle_t key, size_t *count);
+
+/** Get key's signature, based on it's index.
+ *  Note: see the rnp_key_get_signature_count() description for the details.
+ *
+ * @param key key handle
+ * @param idx zero-based signature index.
+ * @param sig signature handle will be stored here on success. You must free it after use with
+ *            the rnp_signature_handle_destroy() function.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_get_signature_at(rnp_key_handle_t        key,
+                                      size_t                  idx,
+                                      rnp_signature_handle_t *sig);
+
+/** Get the number of user id's signatures.
+ *
+ * @param uid user id handle.
+ * @param count number of uid's signatures will be stored here.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_uid_get_signature_count(rnp_uid_handle_t uid, size_t *count);
+
+/** Get user id's signature, based on it's index.
+ *
+ * @param uid uid handle.
+ * @param idx zero-based signature index.
+ * @param sig signature handle will be stored here on success. You must free it after use with
+ *            the rnp_signature_handle_destroy() function.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_uid_get_signature_at(rnp_uid_handle_t        uid,
+                                      size_t                  idx,
+                                      rnp_signature_handle_t *sig);
+
+/** Get signature's algorithm.
+ *
+ * @param sig signature handle.
+ * @param alg on success string with algorithm name will be saved here. Cannot be NULL.
+*            You must free it using the rnp_buffer_destroy().
+
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_signature_get_alg(rnp_signature_handle_t sig, char **alg);
+
+/** Get signature's hash algorithm.
+ *
+ * @param sig signature handle.
+ * @param alg on success string with algorithm name will be saved here. Cannot be NULL.
+ *            You must free it using the rnp_buffer_destroy().
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_signature_get_hash_alg(rnp_signature_handle_t sig, char **alg);
+
+/** Get the signature creation time as number of seconds since Jan, 1 1970 UTC
+ *
+ * @param sig signature handle.
+ * @param create on success result will be stored here. Cannot be NULL.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_signature_get_creation(rnp_signature_handle_t sig, uint32_t *create);
+
+/** Get signer's key id from the signature.
+ *  Note: if key id is not available from the signature then NULL value will
+ *        be stored to result.
+ * @param sig signature handle
+ * @param result hex-encoded key id will be stored here. Cannot be NULL. You must free it
+ *               later on using the rnp_buffer_destroy() function.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_signature_get_keyid(rnp_signature_handle_t sig, char **result);
+
+/** Get signing key handle, if available.
+ *  Note: if signing key is not available then NULL will be stored in key.
+ * @param sig signature handle
+ * @param key on success and key availability will contain signing key's handle. You must
+ *            destroy it using the rnp_key_handle_destroy() function.
+ * @return RNP_SUCCESS or error code if f4ailed.
+ */
+rnp_result_t rnp_signature_get_signer(rnp_signature_handle_t sig, rnp_key_handle_t *key);
+
+/** Dump signature packet to JSON, obtaining the whole information about it.
+ *
+ * @param sig sigmature handle, cannot be NULL
+ * @param flags include additional fields in JSON (see RNP_JSON_DUMP_MPI and other
+ *              RNP_JSON_DUMP_* flags)
+ * @param result resulting JSON string will be stored here. You must free it using the
+ *               rnp_buffer_destroy() function.
+ * @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_signature_packet_to_json(rnp_signature_handle_t sig,
+                                          uint32_t               flags,
+                                          char **                json);
+
+/** Free signature handle.
+ *
+ * @param sig signature handle.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_signature_handle_destroy(rnp_signature_handle_t sig);
+
+/** Check whether user id is revoked.
+ *
+ * @param uid user id handle, should not be NULL.
+ * @param result boolean result will be stored here on success. Cannot be NULL.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_uid_is_revoked(rnp_uid_handle_t uid, bool *result);
+
+/** Destroy previously allocated user id handle.
+ *
+ * @param uid user id handle.
+ * @return RNP_SUCCESS or error code
+ */
+rnp_result_t rnp_uid_handle_destroy(rnp_uid_handle_t uid);
+
+/** Get number of the key's subkeys.
+ *
+ * @param key key handle.
+ * @param count number of subkeys will be stored here.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_get_subkey_count(rnp_key_handle_t key, size_t *count);
+
+/** Get the handle of one of the key's subkeys, using it's index in the list.
+ *
+ * @param key handle of the primary key.
+ * @param idx zero-based index of the subkey.
+ * @param subkey on success handle for the subkey will be stored here. You must free it
+ *               using the rnp_key_handle_destroy() function.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_get_subkey_at(rnp_key_handle_t key, size_t idx, rnp_key_handle_t *subkey);
+
+/** Get the key's algorithm.
+ *
+ * @param key key handle
+ * @param alg string with algorithm name will be stored here. You must free it using the
+ *            rnp_buffer_destroy() function.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_get_alg(rnp_key_handle_t key, char **alg);
+
+/** Get number of bits in the key. For EC-based keys it will return size of the curve.
+ *
+ * @param key key handle
+ * @param bits number of bits will be stored here.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_get_bits(rnp_key_handle_t key, uint32_t *bits);
+
+/** Get the number of bits in q parameter of the DSA key. Makes sense only for DSA keys.
+ *
+ * @param key key handle
+ * @param qbits number of bits will be stored here.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_get_dsa_qbits(rnp_key_handle_t key, uint32_t *qbits);
+
+/** Get the curve of EC-based key.
+ *
+ * @param key key handle
+ * @param curve string with name of the curve will be stored here. You must free it using the
+ *              rnp_buffer_destroy() function.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_get_curve(rnp_key_handle_t key, char **curve);
+
+/** Add a new user identifier to a key
+ *
+ *  @param ffi
+ *  @param key the key to add - must be a secret key
+ *  @param uid the UID to add
+ *  @param hash name of the hash function to use for the uid binding
+ *         signature (eg "SHA256")
+ *  @param expiration time when this user id expires
+ *  @param key_flags usage flags, see section 5.2.3.21 of RFC 4880
+ *         or just provide zero to indicate no special handling.
+ *  @param primary indicates if this is the primary UID
+ *  @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_add_uid(rnp_key_handle_t key,
+                             const char *     uid,
+                             const char *     hash,
+                             uint32_t         expiration,
+                             uint8_t          key_flags,
+                             bool             primary);
+
+/* The following output hex encoded strings */
+
+/**
+ * @brief Get key's fingerprint as hex-encoded string.
+ *
+ * @param key key handle, should not be NULL
+ * @param fprint pointer to the NULL-terminated string with hex-encoded fingerprint will be
+ *        stored here. You must free it later using rnp_buffer_destroy function.
+ * @return RNP_SUCCESS or error code on failure.
+ */
+rnp_result_t rnp_key_get_fprint(rnp_key_handle_t key, char **fprint);
+
+/**
+ * @brief Get key's id as hex-encoded string
+ *
+ * @param key key handle, should not be NULL
+ * @param keyid pointer to the NULL-terminated string with hex-encoded key id will be
+ *        stored here. You must free it later using rnp_buffer_destroy function.
+ * @return RNP_SUCCESS or error code on failure.
+ */
+rnp_result_t rnp_key_get_keyid(rnp_key_handle_t key, char **keyid);
+
+/**
+ * @brief Get key's grip as hex-encoded string
+ *
+ * @param key key handle, should not be NULL
+ * @param grip pointer to the NULL-terminated string with hex-encoded key grip will be
+ *        stored here. You must free it later using rnp_buffer_destroy function.
+ * @return RNP_SUCCESS or error code on failure.
+ */
+rnp_result_t rnp_key_get_grip(rnp_key_handle_t key, char **grip);
+
+/**
+ * @brief Get primary's key grip for the subkey, if available.
+ *
+ * @param key key handle, should not be NULL
+ * @param grip pointer to the NULL-terminated string with hex-encoded key grip or NULL will be
+ *        stored here, depending whether primary key is available or not.
+ *        You must free it later using rnp_buffer_destroy function.
+ * @return RNP_SUCCESS or error code on failure.
+ */
+rnp_result_t rnp_key_get_primary_grip(rnp_key_handle_t key, char **grip);
+
+/**
+ * @brief Check whether certain usage type is allowed for the key.
+ *
+ * @param key key handle, should not be NULL
+ * @param usage string describing the key usage. For the list of allowed values see the
+ *              rnp_op_generate_add_usage() function description.
+ * @param result function result will be stored here. Could not be NULL.
+ * @return RNP_SUCCESS or error code on failure.
+ */
+rnp_result_t rnp_key_allows_usage(rnp_key_handle_t key, const char *usage, bool *result);
+
+/**
+ * @brief Get the key's creation time.
+ *
+ * @param key key handle, should not be NULL.
+ * @param result creation time will be stored here. Cannot be NULL.
+ * @return RNP_SUCCESS or error code on failure.
+ */
+rnp_result_t rnp_key_get_creation(rnp_key_handle_t key, uint32_t *result);
+
+/**
+ * @brief Get the key's expiration time in seconds.
+ *        Note: 0 means that the key doesn't expire.
+ *
+ * @param key key handle, should not be NULL
+ * @param result expiration time will be stored here. Could not be NULL.
+ * @return RNP_SUCCESS or error code on failure.
+ */
+rnp_result_t rnp_key_get_expiration(rnp_key_handle_t key, uint32_t *result);
+
+/**
+ * @brief Check whether key is revoked.
+ *
+ * @param key key handle, should not be NULL
+ * @param result on success result will be stored here. Could not be NULL.
+ * @return RNP_SUCCESS or error code on failure.
+ */
+rnp_result_t rnp_key_is_revoked(rnp_key_handle_t key, bool *result);
+
+/**
+ * @brief Get textual description of the key's revocation reason (if any)
+ *
+ * @param key key handle, should not be NULL
+ * @param result on success pointer to the NULL-terminated string will be stored here.
+ *               You must free it later using rnp_buffer_destroy() function.
+ * @return RNP_SUCCESS or error code on failure.
+ */
+rnp_result_t rnp_key_get_revocation_reason(rnp_key_handle_t key, char **result);
+
+/**
+ * @brief Check whether revoked key was superseded by other key.
+ *
+ * @param key key handle, should not be NULL
+ * @param result on success result will be stored here. Could not be NULL.
+ * @return RNP_SUCCESS or error code on failure.
+ */
+rnp_result_t rnp_key_is_superseded(rnp_key_handle_t key, bool *result);
+
+/**
+ * @brief Check whether revoked key's material was compromised.
+ *
+ * @param key key handle, should not be NULL
+ * @param result on success result will be stored here. Could not be NULL.
+ * @return RNP_SUCCESS or error code on failure.
+ */
+rnp_result_t rnp_key_is_compromised(rnp_key_handle_t key, bool *result);
+
+/**
+ * @brief Check whether revoked key was retired.
+ *
+ * @param key key handle, should not be NULL
+ * @param result on success result will be stored here. Could not be NULL.
+ * @return RNP_SUCCESS or error code on failure.
+ */
+rnp_result_t rnp_key_is_retired(rnp_key_handle_t key, bool *result);
+
+/** check if a key is currently locked
+ *
+ *  @param key
+ *  @param result pointer to hold the result. This will be set to true if
+ *         the key is currently locked, or false otherwise. Must not be NULL.
+ *  @return RNP_SUCCESS on success, or any other value on error
+ **/
+rnp_result_t rnp_key_is_locked(rnp_key_handle_t key, bool *result);
+
+/** lock the key
+ *
+ *  A locked key does not have the secret key material immediately
+ *  available for use. A locked and protected (aka encrypted) key
+ *  is safely encrypted in memory and requires a password for
+ *  performing any operations involving the secret key material.
+ *
+ *  Generally lock/unlock are not useful for unencrypted (not protected) keys.
+ *
+ *  @param key
+ *  @return RNP_SUCCESS on success, or any other value on error
+ **/
+rnp_result_t rnp_key_lock(rnp_key_handle_t key);
+
+/** unlock the key
+ *
+ *  An unlocked key has unencrypted secret key material available for use
+ *  without a password.
+ *
+ *  Generally lock/unlock are not useful for unencrypted (not protected) keys.
+ *
+ *  @param key
+ *  @param password the password to unlock the key. If NULL, the password
+ *         provider will be used.
+ *  @param result pointer to hold the result. This will be set to true if
+ *         the key is currently locked, or false otherwise. Must not be NULL.
+ *  @return RNP_SUCCESS on success, or any other value on error
+ **/
+rnp_result_t rnp_key_unlock(rnp_key_handle_t key, const char *password);
+
+/** check if a key is currently protected
+ *
+ *  A protected key is one that is encrypted and can be safely held in memory
+ *  and locked/unlocked as needed.
+ *
+ *  @param key
+ *  @param result pointer to hold the result. This will be set to true if
+ *         the key is currently protected, or false otherwise. Must not be NULL.
+ *  @return RNP_SUCCESS on success, or any other value on error
+ **/
+rnp_result_t rnp_key_is_protected(rnp_key_handle_t key, bool *result);
+
+/** protect the key
+ *
+ *  This can be used to set a new password on a key or to protect an unprotected
+ *  key.
+ *
+ *  Note that the only required parameter is "password".
+ *
+ *  @param key
+ *  @param password the new password to encrypt/re-encrypt the key with.
+ *         Must not be NULL.
+ *  @param cipher the cipher (AES256, etc) used to encrypt the key. May be NULL,
+ *         in which case a default will be used.
+ *  @param cipher_mode the cipher mode (CFB, CBC, OCB). This parameter is not
+ *         well supported currently and is mostly relevant for G10.
+ *         May be NULL.
+ *  @param hash the hash algorithm (SHA512, etc) used for the String-to-Key key
+ *         derivation. May be NULL, in which case a default will be used.
+ *  @param iterations the number of iterations used for the String-to-Key key
+ *         derivation. Use 0 to select a reasonable default.
+ *  @return RNP_SUCCESS on success, or any other value on error
+ **/
+rnp_result_t rnp_key_protect(rnp_key_handle_t handle,
+                             const char *     password,
+                             const char *     cipher,
+                             const char *     cipher_mode,
+                             const char *     hash,
+                             size_t           iterations);
+
+/** unprotect the key
+ *
+ *  This removes the encryption from the key.
+ *
+ *  @param key
+ *  @param password the password to unlock the key. If NULL, the password
+ *         provider will be used.
+ *  @return RNP_SUCCESS on success, or any other value on error
+ **/
+rnp_result_t rnp_key_unprotect(rnp_key_handle_t key, const char *password);
+
+rnp_result_t rnp_key_is_primary(rnp_key_handle_t key, bool *result);
+rnp_result_t rnp_key_is_sub(rnp_key_handle_t key, bool *result);
+rnp_result_t rnp_key_have_secret(rnp_key_handle_t key, bool *result);
+rnp_result_t rnp_key_have_public(rnp_key_handle_t key, bool *result);
+
+/* TODO: function to add a userid to a key */
+
+/** Get the information about key packets in JSON string.
+ *  Note: this will not work for G10 keys.
+ *
+ * @param key key's handle, cannot be NULL
+ * @param secret dump secret key instead of public
+ * @param flags include additional fields in JSON (see RNP_JSON_DUMP_MPI and other
+ *              RNP_JSON_DUMP_* flags)
+ * @param result resulting JSON string will be stored here. You must free it using the
+ *               rnp_buffer_destroy() function.
+ * @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_key_packets_to_json(rnp_key_handle_t key,
+                                     bool             secret,
+                                     uint32_t         flags,
+                                     char **          result);
+
+/** Dump OpenPGP packets stream information to the JSON string.
+ * @param input source with OpenPGP data
+ * @param flags include additional fields in JSON (see RNP_JSON_DUMP_MPI and other
+ *              RNP_JSON_DUMP_* flags)
+ * @result resulting JSON string will be stored here. You must free it using the
+ *         rnp_buffer_destroy() function.
+ * @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_dump_packets_to_json(rnp_input_t input, uint32_t flags, char **result);
+
+/** Dump OpenPGP packets stream information to output in humand-readable format.
+ * @param input source with OpenPGP data
+ * @param output text, describing packet sequence, will be written here
+ * @param flags see RNP_DUMP_MPI and other RNP_DUMP_* constants.
+ * @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_dump_packets_to_output(rnp_input_t  input,
+                                        rnp_output_t output,
+                                        uint32_t     flags);
+
+/* Signing operations */
+
+/** @brief Create signing operation context. This method should be used for embedded
+ *         signatures of binary data. For detached and cleartext signing corresponding
+ *         function should be used.
+ *  @param op pointer to opaque signing context
+ *  @param ffi
+ *  @param input stream with data to be signed. Could not be NULL.
+ *  @param output stream to write results to. Could not be NULL.
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_create(rnp_op_sign_t *op,
+                                rnp_ffi_t      ffi,
+                                rnp_input_t    input,
+                                rnp_output_t   output);
+
+/** @brief Create cleartext signing operation context. Input should be text data. Output will
+ *         contain source data with additional headers and armored signature.
+ *  @param op pointer to opaque signing context
+ *  @param ffi
+ *  @param input stream with data to be signed. Could not be NULL.
+ *  @param output stream to write results to. Could not be NULL.
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_cleartext_create(rnp_op_sign_t *op,
+                                          rnp_ffi_t      ffi,
+                                          rnp_input_t    input,
+                                          rnp_output_t   output);
+
+/** @brief Create detached signing operation context. Output will contain only signature of the
+ *         source data.
+ *  @param op pointer to opaque signing context
+ *  @param ffi
+ *  @param input stream with data to be signed. Could not be NULL.
+ *  @param output stream to write results to. Could not be NULL.
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_detached_create(rnp_op_sign_t *op,
+                                         rnp_ffi_t      ffi,
+                                         rnp_input_t    input,
+                                         rnp_output_t   signature);
+
+/** @brief Add information about the signature so it could be calculated later in execute
+ *         function call. Multiple signatures could be added.
+ *  @param op opaque signing context. Must be successfully initialized with one of the
+ *         rnp_op_sign_*_create functions.
+ *  @param key handle of the private key. Private key should be capable for signing.
+ *  @param sig pointer to opaque structure holding the signature information. May be NULL.
+ *         You should not free it as it will be destroyed together with signing context.
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_add_signature(rnp_op_sign_t            op,
+                                       rnp_key_handle_t         key,
+                                       rnp_op_sign_signature_t *sig);
+
+/** @brief Set hash algorithm used during signature calculation instead of default one, or one
+ *         set by rnp_op_encrypt_set_hash/rnp_op_sign_set_hash
+ *  @param sig opaque signature context, returned via rnp_op_sign_add_signature
+ *  @param hash hash algorithm to be used
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_signature_set_hash(rnp_op_sign_signature_t sig, const char *hash);
+
+/** @brief Set signature creation time. By default current time is used or value set by
+ *         rnp_op_encrypt_set_creation_time/rnp_op_sign_set_creation_time
+ *  @param sig opaque signature context, returned via rnp_op_sign_add_signature
+ *  @param create creation time in seconds since Jan, 1 1970 UTC
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_signature_set_creation_time(rnp_op_sign_signature_t sig,
+                                                     uint32_t                create);
+
+/** @brief Set signature expiration time. By default is set to never expire or to value set by
+ *         rnp_op_encrypt_set_expiration_time/rnp_op_sign_set_expiration_time
+ *  @param sig opaque signature context, returned via rnp_op_sign_add_signature
+ *  @param expire expiration time in seconds since the creation time. 0 value is used to mark
+ *         signature as non-expiring (default value)
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_signature_set_expiration_time(rnp_op_sign_signature_t sig,
+                                                       uint32_t                expires);
+
+/** @brief Set data compression parameters. Makes sense only for embedded signatures.
+ *  @param op opaque signing context. Must be initialized with rnp_op_sign_create function
+ *  @param compression compression algorithm (zlib, zip, bzip2)
+ *  @param level compression level, 0-9. 0 disables compression.
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_set_compression(rnp_op_sign_t op, const char *compression, int level);
+
+/** @brief Enabled or disable armored (textual) output. Doesn't make sense for cleartext sign.
+ *  @param op opaque signing context. Must be initialized with rnp_op_sign_create or
+ *         rnp_op_sign_detached_create function.
+ *  @param armored true if armoring should be used (it is disabled by default)
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_set_armor(rnp_op_sign_t op, bool armored);
+
+/** @brief Set hash algorithm used during signature calculation. This will set hash function
+ *         for all signature. To change it for a single signature use
+ *         rnp_op_sign_signature_set_hash function.
+ *  @param op opaque signing context. Must be successfully initialized with one of the
+ *         rnp_op_sign_*_create functions.
+ *  @param hash hash algorithm to be used
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_set_hash(rnp_op_sign_t op, const char *hash);
+
+/** @brief Set signature creation time. By default current time is used.
+ *  @param op opaque signing context. Must be successfully initialized with one of the
+ *         rnp_op_sign_*_create functions.
+ *  @param create creation time in seconds since Jan, 1 1970 UTC
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_set_creation_time(rnp_op_sign_t op, uint32_t create);
+
+/** @brief Set signature expiration time.
+ *  @param op opaque signing context. Must be successfully initialized with one of the
+ *         rnp_op_sign_*_create functions.
+ *  @param expire expiration time in seconds since the creation time. 0 value is used to mark
+ *         signature as non-expiring (default value)
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_set_expiration_time(rnp_op_sign_t op, uint32_t expire);
+
+/** @brief Set input's file name. Makes sense only for embedded signature.
+ *  @param op opaque signing context. Must be initialized with rnp_op_sign_create function
+ *  @param filename source data file name. Special value _CONSOLE may be used to mark message
+ *         as 'for your eyes only', i.e. it should not be stored anywhere but only displayed
+ *         to the receiver. Default is the empty string.
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_set_file_name(rnp_op_sign_t op, const char *filename);
+
+/** @brief Set input's file modification date. Makes sense only for embedded signature.
+ *  @param op opaque signing context. Must be initialized with rnp_op_sign_create function
+ *  @param mtime modification time in seconds since Jan, 1 1970 UTC.
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_sign_set_file_mtime(rnp_op_sign_t op, uint32_t mtime);
+
+/** @brief Execute previously initialized signing operation.
+ *  @param op opaque signing context. Must be successfully initialized with one of the
+ *         rnp_op_sign_*_create functions. At least one signing key should be added.
+ *  @return RNP_SUCCESS or error code if failed. On success output stream, passed in the create
+ *          function call, will be populated with signed data
+ */
+rnp_result_t rnp_op_sign_execute(rnp_op_sign_t op);
+
+/** @brief Free resources associated with signing operation.
+ *  @param op opaque signing context. Must be successfully initialized with one of the
+ *         rnp_op_sign_*_create functions.
+ *  @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_sign_destroy(rnp_op_sign_t op);
+
+/* Verification */
+
+/** @brief Create verification operation context. This method should be used for embedded
+ *         signatures or cleartext signed data. For detached verification corresponding
+ *         function should be used.
+ *  @param op pointer to opaque verification context
+ *  @param ffi
+ *  @param input stream with signed data. Could not be NULL.
+ *  @param output stream to write results to. Could not be NULL, but may be null output stream
+ *         if verified data should be discarded.
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_verify_create(rnp_op_verify_t *op,
+                                  rnp_ffi_t        ffi,
+                                  rnp_input_t      input,
+                                  rnp_output_t     output);
+
+/** @brief Create verification operation context for detached signature.
+ *  @param op pointer to opaque verification context
+ *  @param ffi
+ *  @param input stream with raw data. Could not be NULL.
+ *  @param signature stream with detached signature data
+ *  @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_verify_detached_create(rnp_op_verify_t *op,
+                                           rnp_ffi_t        ffi,
+                                           rnp_input_t      input,
+                                           rnp_input_t      signature);
+
+/** @brief Execute previously initialized verification operation.
+ *  @param op opaque verification context. Must be successfully initialized.
+ *  @return RNP_SUCCESS if data was processed successfully and all signatures are valid.
+ *          Otherwise error code is returned. After rnp_op_verify_execute()
+ *          rnp_op_verify_get_* functions may be used to query information about the
+ *          signature(s).
+ */
+rnp_result_t rnp_op_verify_execute(rnp_op_verify_t op);
+
+/** @brief Get number of the signatures for verified data.
+ *  @param op opaque verification context. Must be initialized and have execute() called on it.
+ *  @param count result will be stored here on success.
+ *  @return RNP_SUCCESS if call succeeded.
+ */
+rnp_result_t rnp_op_verify_get_signature_count(rnp_op_verify_t op, size_t *count);
+
+/** @brief Get single signature information based on it's index.
+ *  @param op opaque verification context. Must be initialized and have execute() called on it.
+ *  @param sig opaque signature context data will be stored here on success.
+ *  @return RNP_SUCCESS if call succeeded.
+ */
+rnp_result_t rnp_op_verify_get_signature_at(rnp_op_verify_t            op,
+                                            size_t                     idx,
+                                            rnp_op_verify_signature_t *sig);
+
+/** @brief Get embedded in OpenPGP data file name and modification time. Makes sense only for
+ *         embedded signature verification.
+ *  @param op opaque verification context. Must be initialized and have execute() called on it.
+ *  @param filename pointer to the filename. On success caller is responsible for freeing it
+ *                  via the rnp_buffer_free function call. May be NULL if this information is
+ *                  not needed.
+ *  @param mtime file modification time will be stored here on success. May be NULL.
+ *  @return RNP_SUCCESS if call succeeded.
+ */
+rnp_result_t rnp_op_verify_get_file_info(rnp_op_verify_t op, char **filename, uint32_t *mtime);
+
+/** @brief Free resources allocated in verification context.
+ *  @param op opaque verification context. Must be initialized.
+ *  @return RNP_SUCCESS if call succeeded.
+ */
+rnp_result_t rnp_op_verify_destroy(rnp_op_verify_t op);
+
+/** @brief Get signature verification status.
+ *  @param sig opaque signature context obtained via rnp_op_verify_get_signature_at call.
+ *  @return signature verification status:
+ *          RNP_SUCCESS : signature is valid
+ *          RNP_ERROR_SIGNATURE_EXPIRED : signature is valid but expired
+ *          RNP_ERROR_KEY_NOT_FOUND : public key to verify signature was not available
+ *          RNP_ERROR_SIGNATURE_INVALID : data or signature was modified
+ */
+rnp_result_t rnp_op_verify_signature_get_status(rnp_op_verify_signature_t sig);
+
+/** Get the signature handle from the verified signature. This would allow to query extended
+ * information on the signature.
+ *
+ * @param sig verified signature context, cannot be NULL.
+ * @param handle signature handle will be stored here on success. You must free it after use
+ * with
+ *            the rnp_signature_handle_destroy() function.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_op_verify_signature_get_handle(rnp_op_verify_signature_t sig,
+                                                rnp_signature_handle_t *  handle);
+
+/** @brief Get hash function used to calculate signature
+ *  @param sig opaque signature context obtained via rnp_op_verify_get_signature_at call.
+ *  @param hash pointer to string with hash algorithm name will be put here on success.
+ *              Caller is responsible for freeing it with rnp_buffer_free
+ *  @return RNP_SUCCESS or error code otherwise
+ */
+rnp_result_t rnp_op_verify_signature_get_hash(rnp_op_verify_signature_t sig, char **hash);
+
+/** @brief Get key used for signing
+ *  @param sig opaque signature context obtained via rnp_op_verify_get_signature_at call.
+ *  @param key pointer to opaque key handle structure.
+ *  @return RNP_SUCCESS or error code otherwise
+ */
+rnp_result_t rnp_op_verify_signature_get_key(rnp_op_verify_signature_t sig,
+                                             rnp_key_handle_t *        key);
+
+/** @brief Get signature creation and expiration times
+ *  @param sig opaque signature context obtained via rnp_op_verify_get_signature_at call.
+ *  @param create signature creation time will be put here. It is number of seconds since
+ *                Jan, 1 1970 UTC. May be NULL if called doesn't need this data.
+ *  @param expires signature expiration time will be stored here. It is number of seconds since
+ *                 the creation time or 0 if signature never expires. May be NULL.
+ *  @return RNP_SUCCESS or error code otherwise
+ */
+rnp_result_t rnp_op_verify_signature_get_times(rnp_op_verify_signature_t sig,
+                                               uint32_t *                create,
+                                               uint32_t *                expires);
+
+/* TODO define functions for encrypt+sign */
+
+/**
+ * @brief Free buffer allocated by a function in this header.
+ *
+ * @param ptr previously allocated buffer. May be NULL, then nothing is done.
+ */
+void rnp_buffer_destroy(void *ptr);
+
+/**
+ * @brief Securely clear buffer contents.
+ *
+ * @param ptr pointer to the buffer contents, may be NULL.
+ * @param size number of bytes in buffer.
+ */
+void rnp_buffer_clear(void *ptr, size_t size);
+
+/**
+ * @brief Initialize input struct to read from a path
+ *
+ * @param input pointer to the input opaque structure
+ * @param path path of the file to read from
+ * @return RNP_SUCCESS if operation succeeded and input struct is ready to read, or error code
+ * otherwise
+ */
+rnp_result_t rnp_input_from_path(rnp_input_t *input, const char *path);
+
+/**
+ * @brief Initialize input struct to read from memory
+ *
+ * @param input pointer to the input opaque structure
+ * @param buf memory buffer. Could not be NULL.
+ * @param buf_len number of bytes available to read from buf
+ * @param do_copy if true then the buffer will be copied internally. If
+ *        false then the application should ensure that the buffer
+ *        is valid and not modified during the lifetime of this object.
+ * @return RNP_SUCCESS if operation succeeded or error code otherwise
+ */
+rnp_result_t rnp_input_from_memory(rnp_input_t * input,
+                                   const uint8_t buf[],
+                                   size_t        buf_len,
+                                   bool          do_copy);
+
+/**
+ * @brief Initialize input struct to read via callbacks
+ *
+ * @param input pointer to the input opaque structure
+ * @param reader callback used for reading
+ * @param closer callback used to close the stream
+ * @param app_ctx context to pass as parameter to reader and closer
+ * @return RNP_SUCCESS if operation succeeded or error code otherwise
+ */
+rnp_result_t rnp_input_from_callback(rnp_input_t *       input,
+                                     rnp_input_reader_t *reader,
+                                     rnp_input_closer_t *closer,
+                                     void *              app_ctx);
+
+/**
+ * @brief Close previously opened input and free all corresponding resources
+ *
+ * @param input previously opened input structure
+ * @return RNP_SUCCESS if operation succeeded or error code otherwise
+ */
+rnp_result_t rnp_input_destroy(rnp_input_t input);
+
+/**
+ * @brief Initialize output structure to write to a path. If path is a file
+ * that already exists then it will be overwritten.
+ *
+ * @param output pointer to the opaque output structure.
+ * @param path path to the file.
+ * @return RNP_SUCCESS if file was opened successfully and ready for writing or error code
+ * otherwise.
+ */
+rnp_result_t rnp_output_to_path(rnp_output_t *output, const char *path);
+
+/**
+ * @brief Initialize structure to write to a file.
+ *        Note: it doesn't allow output to directory like rnp_output_to_path does, but
+ *        allows additional options to be specified.
+ *        When RNP_OUTPUT_FILE_RANDOM flag is included then you may want to call
+ *        rnp_output_finish() to make sure that final rename succeeded.
+ * @param output pointer to the opaque output structure. After use you must free it using the
+ *               rnp_output_destroy() function.
+ * @param path path to the file.
+ * @param flags additional flags, see RNP_OUTPUT_* flags.
+ * @return RNP_SUCCESS if file was opened successfully and ready for writing or error code
+ *         otherwise.
+ */
+rnp_result_t rnp_output_to_file(rnp_output_t *output, const char *path, uint32_t flags);
+
+/**
+ * @brief Initialize output structure to write to the memory.
+ *
+ * @param output pointer to the opaque output structure.
+ * @param max_alloc maximum amount of memory to allocate. 0 value means unlimited.
+ * @return RNP_SUCCESS if operation succeeded or error code otherwise.
+ */
+rnp_result_t rnp_output_to_memory(rnp_output_t *output, size_t max_alloc);
+
+/**
+ * @brief Output data to armored stream (and then output to other destination), allowing
+ *        streamed output.
+ *
+ * @param base initialized output structure, where armored data will be written to.
+ * @param output pointer to the opaque output structure. You must free it later using the
+ *               rnp_output_destroy() function.
+ * @param type type of the armored stream. See rnp_enarmor() for possible values.
+ * @return RNP_SUCCESS if operation succeeded or error code otherwise.
+ */
+rnp_result_t rnp_output_to_armor(rnp_output_t base, rnp_output_t *output, const char *type);
+
+/**
+ * @brief Get the pointer to the buffer of output, initialized by rnp_output_to_memory
+ *
+ * @param output output structure, initialized by rnp_output_to_memory and populated with data
+ * @param buf pointer to the buffer will be stored here, could not be NULL
+ * @param len number of bytes in buffer will be stored here, could not be NULL
+ * @param do_copy if true then a newly-allocated buffer will be returned and the application
+ *        will be responsible for freeing it with rnp_buffer_destroy. If false
+ *        then the internal buffer is returned and the application must not modify the
+ *        buffer or access it after this object is destroyed.
+ * @return RNP_SUCCESS if operation succeeded or error code otherwise.
+ */
+rnp_result_t rnp_output_memory_get_buf(rnp_output_t output,
+                                       uint8_t **   buf,
+                                       size_t *     len,
+                                       bool         do_copy);
+
+/**
+ * @brief Initialize output structure to write to callbacks.
+ *
+ * @param output pointer to the opaque output structure.
+ * @param writer write callback.
+ * @param closer close callback.
+ * @param app_ctx context parameter which will be passed to writer and closer.
+ * @return RNP_SUCCESS if operation succeeded or error code otherwise.
+ */
+rnp_result_t rnp_output_to_callback(rnp_output_t *       output,
+                                    rnp_output_writer_t *writer,
+                                    rnp_output_closer_t *closer,
+                                    void *               app_ctx);
+
+/**
+ * @brief Initialize output structure which will discard all data
+ *
+ * @param output pointer to the opaque output structure.
+ * @return RNP_SUCCESS if operation succeeded or error code otherwise.
+ */
+rnp_result_t rnp_output_to_null(rnp_output_t *output);
+
+/**
+ * @brief write some data to the output structure.
+ *
+ * @param output pointer to the initialized opaque output structure.
+ * @param data pointer to data which should be written.
+ * @param size number of bytes to write.
+ * @param written on success will contain the number of bytes written. May be NULL.
+ * @return rnp_result_t RNP_SUCCESS if operation succeeded or error code otherwise.
+ */
+rnp_result_t rnp_output_write(rnp_output_t output,
+                              const void * data,
+                              size_t       size,
+                              size_t *     written);
+
+/**
+ * @brief Finish writing to the output.
+ *        Note: on most output types you'll need just to call rnp_output_destroy().
+ *        However, for file output with RNP_OUTPUT_FILE_RANDOM flag, you need to call this
+ *        to make sure that rename from random to required name succeeded.
+ *
+ * @param output pointer to the opaque output structure.
+ * @return RNP_SUCCESS if operation succeeded or error code otherwise.
+ */
+rnp_result_t rnp_output_finish(rnp_output_t output);
+
+/**
+ * @brief Close previously opened output and free all associated data.
+ *
+ * @param output previously opened output structure.
+ * @return RNP_SUCCESS if operation succeeds or error code otherwise.
+ */
+rnp_result_t rnp_output_destroy(rnp_output_t output);
+
+/* encrypt */
+rnp_result_t rnp_op_encrypt_create(rnp_op_encrypt_t *op,
+                                   rnp_ffi_t         ffi,
+                                   rnp_input_t       input,
+                                   rnp_output_t      output);
+
+rnp_result_t rnp_op_encrypt_add_recipient(rnp_op_encrypt_t op, rnp_key_handle_t key);
+
+/**
+ * @brief Add signature to encrypting context, so data will be encrypted and signed.
+ *
+ * @param op opaque encrypting context. Must be allocated and initialized.
+ * @param key private key, used for signing.
+ * @param sig pointer to the newly added signature will be stored here. May be NULL.
+ * @return RNP_SUCCESS if signature was added or error code otherwise.
+ */
+rnp_result_t rnp_op_encrypt_add_signature(rnp_op_encrypt_t         op,
+                                          rnp_key_handle_t         key,
+                                          rnp_op_sign_signature_t *sig);
+
+/**
+ * @brief Set hash function used for signature calculation. Makes sense if encrypt-and-sign is
+ * used. To set hash function for each signature separately use rnp_op_sign_signature_set_hash.
+ *
+ * @param op opaque encrypting context. Must be allocated and initialized.
+ * @param hash hash algorithm to be used as NULL-terminated string. Following values are
+ *        supported: "MD5", "SHA1", "RIPEMD160", "SHA256", "SHA384", "SHA512", "SHA224", "SM3".
+ *        However, some signature types may require specific hash function or hash function
+ *        output length.
+ * @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_encrypt_set_hash(rnp_op_encrypt_t op, const char *hash);
+
+/**
+ * @brief Set signature creation time. By default current time is used.
+ *
+ * @param op opaque encrypting context. Must be allocated and initialized.
+ * @param create creation time in seconds since Jan, 1 1970 UTC
+ * @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_encrypt_set_creation_time(rnp_op_encrypt_t op, uint32_t create);
+
+/**
+ * @brief Set signature expiration time. By default signatures do not expire.
+ *
+ * @param op opaque encrypting context. Must be allocated and initialized.
+ * @param expire expiration time in seconds since the creation time. 0 value is used to mark
+ *        signature as non-expiring
+ * @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_encrypt_set_expiration_time(rnp_op_encrypt_t op, uint32_t expire);
+
+/**
+ * @brief Add password which is used to encrypt data. Multiple passwords can be added.
+ *
+ * @param op opaque encrypting context. Must be allocated and initialized.
+ * @param password NULL-terminated password string, or NULL if password should be requested
+ *                 via password provider.
+ * @param s2k_hash hash algorithm, used in key-from-password derivation. Pass NULL for default
+ *        value. See rnp_op_encrypt_set_hash for possible values.
+ * @param iterations number of iterations, used in key derivation function.
+ *        According to RFC 4880, chapter 3.7.1.3, only 256 distinct values within the range
+ *        [1024..0x3e00000] can be encoded. Thus, the number will be increased to the closest
+ *        encodable value. In case it exceeds the maximum encodable value, it will be decreased
+ *        to the maximum encodable value.
+ *        If 0 is passed, an optimal number (greater or equal to 1024) will be calculated based
+ *        on performance measurement.
+ * @param s2k_cipher symmetric cipher, used for key encryption. Pass NULL for default value.
+ * See rnp_op_encrypt_set_cipher for possible values.
+ * @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_encrypt_add_password(rnp_op_encrypt_t op,
+                                         const char *     password,
+                                         const char *     s2k_hash,
+                                         size_t           iterations,
+                                         const char *     s2k_cipher);
+
+/**
+ * @brief Set whether output should be ASCII-armored, or binary.
+ *
+ * @param op opaque encrypting context. Must be allocated and initialized.
+ * @param armored true for armored, false for binary
+ * @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_encrypt_set_armor(rnp_op_encrypt_t op, bool armored);
+
+/**
+ * @brief set the encryption algorithm
+ *
+ * @param op opaque encrypting context. Must be allocated and initialized.
+ * @param cipher NULL-terminated string with cipher's name. One of the "IDEA", "TRIPLEDES",
+ *        "CAST5", "BLOWFISH", "AES128", "AES192", "AES256", "TWOFISH", "CAMELLIA128",
+ *        "CAMELLIA192", "CAMELLIA256", "SM4".
+ * @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_encrypt_set_cipher(rnp_op_encrypt_t op, const char *cipher);
+
+/**
+ * @brief set AEAD mode algorithm or disable AEAD usage. By default it is disabled.
+ *
+ * @param op opaque encrypting context. Must be allocated and initialized.
+ * @param alg NULL-terminated AEAD algorithm name. Use "None" to disable AEAD, or "EAX", "OCB"
+ * to use the corresponding algorithm.
+ * @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_encrypt_set_aead(rnp_op_encrypt_t op, const char *alg);
+
+/**
+ * @brief set chunk length for AEAD mode via number of chunk size bits (refer OpenPGP
+ * specificationf for the details).
+ *
+ * @param op opaque encrypting context. Must be allocated and initialized.
+ * @param bits number of bits, currently it must be between 0 to 56.
+ * @return RNP_SUCCESS or error code if failed
+ */
+rnp_result_t rnp_op_encrypt_set_aead_bits(rnp_op_encrypt_t op, int bits);
+
+/**
+ * @brief set the compression algorithm and level for the inner raw data
+ *
+ * @param op opaque encrypted context. Must be allocated and initialized
+ * @param compression compression algorithm name. Can be one of the "Uncompressed", "ZIP",
+ *        "ZLIB", "BZip2". Please note that ZIP is not PkWare's ZIP file format but just a
+ *        DEFLATE compressed data (RFC 1951).
+ * @param level 0 - 9, where 0 is no compression and 9 is maximum compression level.
+ * @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_op_encrypt_set_compression(rnp_op_encrypt_t op,
+                                            const char *     compression,
+                                            int              level);
+
+/**
+ * @brief set the internally stored file name for the data being encrypted
+ *
+ * @param op opaque encrypted context. Must be allocated and initialized
+ * @param filename file name as NULL-terminated string. May be empty string. Value "_CONSOLE"
+ * may have specific processing (see RFC 4880 for the details), depending on implementation.
+ * @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_op_encrypt_set_file_name(rnp_op_encrypt_t op, const char *filename);
+
+/**
+ * @brief set the internally stored file modification date for the data being encrypted
+ *
+ * @param op opaque encrypted context. Must be allocated and initialized
+ * @param mtime time in seconds since Jan, 1 1970.
+ * @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_op_encrypt_set_file_mtime(rnp_op_encrypt_t op, uint32_t mtime);
+
+rnp_result_t rnp_op_encrypt_execute(rnp_op_encrypt_t op);
+rnp_result_t rnp_op_encrypt_destroy(rnp_op_encrypt_t op);
+
+rnp_result_t rnp_decrypt(rnp_ffi_t ffi, rnp_input_t input, rnp_output_t output);
+
+/** retrieve the raw data for a public key
+ *
+ *  This will always be PGP packets and will never include ASCII armor.
+ *
+ *  @param handle the key handle
+ *  @param buf
+ *  @param buf_len
+ *  @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_get_public_key_data(rnp_key_handle_t handle, uint8_t **buf, size_t *buf_len);
+
+/** retrieve the raw data for a secret key
+ *
+ *  If this is a G10 key, this will be the s-expr data. Otherwise, it will
+ *  be PGP packets.
+ *
+ *  Note that this result will never include ASCII armor.
+ *
+ *  @param handle the key handle
+ *  @param buf
+ *  @param buf_len
+ *  @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_get_secret_key_data(rnp_key_handle_t handle, uint8_t **buf, size_t *buf_len);
+
+/** output key information to JSON structure and serialize it to the string
+ *
+ * @param handle the key handle, could not be NULL
+ * @param flags controls which key data is printed, see RNP_JSON_* constants.
+ * @param result pointer to the resulting string will be stored here on success. You must
+ *               release it afterwards via rnp_buffer_destroy() function call.
+ * @return RNP_SUCCESS or error code if failed.
+ */
+rnp_result_t rnp_key_to_json(rnp_key_handle_t handle, uint32_t flags, char **result);
+
+/** create an identifier iterator
+ *
+ *  @param ffi
+ *  @param it pointer that will be set to the created iterator
+ *  @param identifier_type the type of identifier ("userid", "keyid", "grip")
+ *  @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_identifier_iterator_create(rnp_ffi_t                  ffi,
+                                            rnp_identifier_iterator_t *it,
+                                            const char *               identifier_type);
+
+/** retrieve the next item from an iterator
+ *
+ *  @param it the iterator
+ *  @param identifier pointer that will be set to the identifier value.
+ *         Must not be NULL. This buffer should not be freed by the application.
+ *         It will be modified by subsequent calls to this function, and its
+ *         life is tied to the iterator.
+ *  @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_identifier_iterator_next(rnp_identifier_iterator_t it,
+                                          const char **             identifier);
+
+/** destroy an identifier iterator
+ *
+ *  @param it the iterator object
+ *  @return RNP_SUCCESS on success, or any other value on error
+ */
+rnp_result_t rnp_identifier_iterator_destroy(rnp_identifier_iterator_t it);
+
+#if defined(__cplusplus)
+}
+
+#include "utils.h"
+
+#endif
+
+/** Algorithm Strings
+ */
+#ifndef RNP_ALGNAME_PLAINTEXT
+
+#define RNP_ALGNAME_PLAINTEXT "PLAINTEXT"
+#define RNP_ALGNAME_RSA "RSA"
+#define RNP_ALGNAME_ELGAMAL "ELGAMAL"
+#define RNP_ALGNAME_DSA "DSA"
+#define RNP_ALGNAME_ECDH "ECDH"
+#define RNP_ALGNAME_ECDSA "ECDSA"
+#define RNP_ALGNAME_EDDSA "EDDSA"
+#define RNP_ALGNAME_IDEA "IDEA"
+#define RNP_ALGNAME_TRIPLEDES "TRIPLEDES"
+#define RNP_ALGNAME_CAST5 "CAST5"
+#define RNP_ALGNAME_BLOWFISH "BLOWFISH"
+#define RNP_ALGNAME_TWOFISH "TWOFISH"
+#define RNP_ALGNAME_AES_128 "AES128"
+#define RNP_ALGNAME_AES_192 "AES192"
+#define RNP_ALGNAME_AES_256 "AES256"
+#define RNP_ALGNAME_CAMELLIA_128 "CAMELLIA128"
+#define RNP_ALGNAME_CAMELLIA_192 "CAMELLIA192"
+#define RNP_ALGNAME_CAMELLIA_256 "CAMELLIA256"
+#define RNP_ALGNAME_SM2 "SM2"
+#define RNP_ALGNAME_SM3 "SM3"
+#define RNP_ALGNAME_SM4 "SM4"
+#define RNP_ALGNAME_MD5 "MD5"
+#define RNP_ALGNAME_SHA1 "SHA1"
+#define RNP_ALGNAME_SHA256 "SHA256"
+#define RNP_ALGNAME_SHA384 "SHA384"
+#define RNP_ALGNAME_SHA512 "SHA512"
+#define RNP_ALGNAME_SHA224 "SHA224"
+#define RNP_ALGNAME_SHA3_256 "SHA3-256"
+#define RNP_ALGNAME_SHA3_512 "SHA3-512"
+#define RNP_ALGNAME_RIPEMD160 "RIPEMD160"
+#define RNP_ALGNAME_CRC24 "CRC24"
+
+/* SHA1 is not considered secured anymore and SHOULD NOT be used to create messages (as per
+ * Appendix C of RFC 4880-bis-02). SHA2 MUST be implemented.
+ * Let's pre-empt this by specifying SHA256 - gpg interoperates just fine with SHA256 - agc,
+ * 20090522
+ */
+#define DEFAULT_HASH_ALG RNP_ALGNAME_SHA256
+
+/* Default symmetric algorithm */
+#define DEFAULT_SYMM_ALG RNP_ALGNAME_AES_256
+
+/* Keystore format: GPG, KBX (pub), G10 (sec), GPG21 ( KBX for pub, G10 for sec) */
+#define RNP_KEYSTORE_GPG ("GPG")
+#define RNP_KEYSTORE_KBX ("KBX")
+#define RNP_KEYSTORE_G10 ("G10")
+#define RNP_KEYSTORE_GPG21 ("GPG21")
+
+#endif
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/include/rnp/rnp_def.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef RNP_DEF_H_
+#define RNP_DEF_H_
+
+#include <stdint.h>
+#include "rnp_err.h"
+
+/* The dot directory relative to the user's home directory where keys
+ * are stored.
+ *
+ * TODO: Consider making this an overridable config setting.
+ *
+ * TODO: For now the dot dot directory is .rnp to prevent competition with
+ *       developers' .gnupg installations.
+ */
+
+#define SUBDIRECTORY_GNUPG ".gnupg"
+#define SUBDIRECTORY_RNP ".rnp"
+#define PUBRING_KBX "pubring.kbx"
+#define SECRING_KBX "secring.kbx"
+#define PUBRING_GPG "pubring.gpg"
+#define SECRING_GPG "secring.gpg"
+#define PUBRING_G10 "public-keys-v1.d"
+#define SECRING_G10 "private-keys-v1.d"
+
+#define MAX_PASSWORD_ATTEMPTS 3
+#define INFINITE_ATTEMPTS -1
+
+/* rnp_result_t is the type used for return codes from the APIs. */
+typedef uint32_t rnp_result_t;
+
+enum { MAX_ID_LENGTH = 128, MAX_PASSWORD_LENGTH = 256 };
+
+#endif
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/include/rnp/rnp_err.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2019, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef RNP_ERR_H_
+#define RNP_ERR_H_
+
+/*
+ * Error code definitions
+ */
+enum {
+
+    RNP_SUCCESS = 0x00000000,
+
+    /* Common error codes */
+    RNP_ERROR_GENERIC = 0x10000000,
+    RNP_ERROR_BAD_FORMAT,
+    RNP_ERROR_BAD_PARAMETERS,
+    RNP_ERROR_NOT_IMPLEMENTED,
+    RNP_ERROR_NOT_SUPPORTED,
+    RNP_ERROR_OUT_OF_MEMORY,
+    RNP_ERROR_SHORT_BUFFER,
+    RNP_ERROR_NULL_POINTER,
+
+    /* Storage */
+    RNP_ERROR_ACCESS = 0x11000000,
+    RNP_ERROR_READ,
+    RNP_ERROR_WRITE,
+
+    /* Crypto */
+    RNP_ERROR_BAD_STATE = 0x12000000,
+    RNP_ERROR_MAC_INVALID,
+    RNP_ERROR_SIGNATURE_INVALID,
+    RNP_ERROR_KEY_GENERATION,
+    RNP_ERROR_BAD_PASSWORD,
+    RNP_ERROR_KEY_NOT_FOUND,
+    RNP_ERROR_NO_SUITABLE_KEY,
+    RNP_ERROR_DECRYPT_FAILED,
+    RNP_ERROR_RNG,
+    RNP_ERROR_SIGNING_FAILED,
+    RNP_ERROR_NO_SIGNATURES_FOUND,
+
+    RNP_ERROR_SIGNATURE_EXPIRED,
+
+    /* Parsing */
+    RNP_ERROR_NOT_ENOUGH_DATA = 0x13000000,
+    RNP_ERROR_UNKNOWN_TAG,
+    RNP_ERROR_PACKET_NOT_CONSUMED,
+    RNP_ERROR_NO_USERID,
+    RNP_ERROR_EOF
+
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/include/rnp/rnp_sdk.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com).
+ * Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is originally derived from software contributed to
+ * The NetBSD Foundation by Alistair Crooks (agc@netbsd.org), and
+ * carried further by Ribose Inc (https://www.ribose.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef RNPSDK_H_
+#define RNPSDK_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <rnp/rnp_def.h>
+
+#ifndef PRINTFLIKE
+#define PRINTFLIKE(n, m) __attribute__((format(printf, n, m)))
+#endif
+
+typedef enum { RNP_HEX_LOWERCASE, RNP_HEX_UPPERCASE } rnp_hex_format_t;
+
+void rnp_log(const char *, ...) PRINTFLIKE(1, 2);
+
+int rnp_strcasecmp(const char *, const char *);
+
+char *rnp_strhexdump_upper(char *dest, const uint8_t *src, size_t length, const char *sep);
+
+int64_t rnp_filemtime(const char *path);
+
+char *rnp_compose_path(const char *first, ...);
+char *rnp_compose_path_ex(char **buf, size_t *buf_len, const char *first, ...);
+
+bool rnp_path_exists(const char *path);
+bool rnp_dir_exists(const char *path);
+bool rnp_file_exists(const char *path);
+
+bool rnp_hex_encode(
+  const uint8_t *buf, size_t buf_len, char *hex, size_t hex_len, rnp_hex_format_t format);
+size_t rnp_hex_decode(const char *hex, uint8_t *buf, size_t buf_len);
+
+char *rnp_strlwr(char *s);
+
+/** @brief strip eol symbols (\r, \n) from the end of the string
+ *  @param s NULL-terminated string, which will be modified
+ *  @return string s itself
+ */
+char *rnp_strip_eol(char *s);
+
+bool hex2bin(const char *hex, size_t hexlen, uint8_t *bin, size_t len, size_t *out);
+
+void pgp_forget(void *, size_t);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/src/examples/CMakeLists.txt
@@ -0,0 +1,108 @@
+# Copyright (c) 2018 Ribose Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+add_executable(generate generate.c)
+
+target_include_directories(generate
+  PRIVATE
+    "${PROJECT_SOURCE_DIR}/src"
+    "${PROJECT_SOURCE_DIR}/src/lib"
+)
+
+target_link_libraries(generate
+  PRIVATE
+    librnp
+)
+
+add_executable(encrypt encrypt.c)
+
+target_include_directories(encrypt
+  PRIVATE
+    "${PROJECT_SOURCE_DIR}/src"
+    "${PROJECT_SOURCE_DIR}/src/lib"
+)
+
+target_link_libraries(encrypt
+  PRIVATE
+    librnp
+)
+
+add_executable(decrypt decrypt.c)
+
+target_include_directories(decrypt
+  PRIVATE
+    "${PROJECT_SOURCE_DIR}/src"
+    "${PROJECT_SOURCE_DIR}/src/lib"
+)
+
+target_link_libraries(decrypt
+  PRIVATE
+    librnp
+)
+
+add_executable(sign sign.c)
+
+target_include_directories(sign
+  PRIVATE
+    "${PROJECT_SOURCE_DIR}/src"
+    "${PROJECT_SOURCE_DIR}/src/lib"
+)
+
+target_link_libraries(sign
+  PRIVATE
+    librnp
+)
+
+add_executable(verify verify.c)
+
+target_include_directories(verify
+  PRIVATE
+    "${PROJECT_SOURCE_DIR}/src"
+    "${PROJECT_SOURCE_DIR}/src/lib"
+)
+
+target_link_libraries(verify
+  PRIVATE
+    librnp
+)
+
+add_executable(dump dump.c)
+
+target_include_directories(dump
+  PRIVATE
+    "${PROJECT_SOURCE_DIR}/src"
+    "${PROJECT_SOURCE_DIR}/src/lib"
+)
+
+target_link_libraries(dump
+  PRIVATE
+    librnp
+)
+
+if (ENABLE_SANITIZERS)
+  foreach(tgt generate encrypt decrypt sign verify dump)
+    set_target_properties(${tgt} PROPERTIES LINKER_LANGUAGE CXX)
+  endforeach()
+endif()
+
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/src/examples/README.md
@@ -0,0 +1,5 @@
+# RNP C API usage samples
+
+This folder includes examples of RNP library usage for developers.
+
+See [Using RNP’s C APIs](/docs/c-usage.adoc) for more details.
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/src/examples/decrypt.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2018, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ * 2.  Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rnp/rnp.h>
+#include <string.h>
+
+#define RNP_SUCCESS 0
+
+/* sample pass provider implementation, which always return 'password' for key decryption and
+ * 'encpassword' when password is needed for file decryption. You may ask for password via
+ * stdin, or choose password based on key properties, whatever else */
+static bool
+example_pass_provider(rnp_ffi_t        ffi,
+                      void *           app_ctx,
+                      rnp_key_handle_t key,
+                      const char *     pgp_context,
+                      char             buf[],
+                      size_t           buf_len)
+{
+    if (!strcmp(pgp_context, "decrypt (symmetric)")) {
+        strncpy(buf, "encpassword", buf_len);
+        return true;
+    }
+    if (!strcmp(pgp_context, "decrypt")) {
+        strncpy(buf, "password", buf_len);
+        return true;
+    }
+
+    return false;
+}
+
+static int
+ffi_decrypt(bool usekeys)
+{
+    rnp_ffi_t    ffi = NULL;
+    rnp_input_t  keyfile = NULL;
+    rnp_input_t  input = NULL;
+    rnp_output_t output = NULL;
+    uint8_t *    buf = NULL;
+    size_t       buf_len = 0;
+    int          result = 1;
+
+    /* initialize FFI object */
+    if (rnp_ffi_create(&ffi, "GPG", "GPG") != RNP_SUCCESS) {
+        return result;
+    }
+
+    /* check whether we want to use key or password for decryption */
+    if (usekeys) {
+        /* load secret keyring, as it is required for public-key decryption. However, you may
+         * need to load public keyring as well to validate key's signatures. */
+        if (rnp_input_from_path(&keyfile, "secring.pgp") != RNP_SUCCESS) {
+            fprintf(stdout, "failed to open secring.pgp. Did you run ./generate sample?\n");
+            goto finish;
+        }
+
+        /* we may use RNP_LOAD_SAVE_SECRET_KEYS | RNP_LOAD_SAVE_PUBLIC_KEYS as well*/
+        if (rnp_load_keys(ffi, "GPG", keyfile, RNP_LOAD_SAVE_SECRET_KEYS) != RNP_SUCCESS) {
+            fprintf(stdout, "failed to read secring.pgp\n");
+            goto finish;
+        }
+        rnp_input_destroy(keyfile);
+        keyfile = NULL;
+    }
+
+    /* set the password provider */
+    rnp_ffi_set_pass_provider(ffi, example_pass_provider, NULL);
+
+    /* create file input and memory output objects for the encrypted message and decrypted
+     * message */
+    if (rnp_input_from_path(&input, "encrypted.asc") != RNP_SUCCESS) {
+        fprintf(stdout, "failed to create input object\n");
+        goto finish;
+    }
+
+    if (rnp_output_to_memory(&output, 0) != RNP_SUCCESS) {
+        fprintf(stdout, "failed to create output object\n");
+        goto finish;
+    }
+
+    if (rnp_decrypt(ffi, input, output) != RNP_SUCCESS) {
+        fprintf(stdout, "public-key decryption failed\n");
+        goto finish;
+    }
+
+    /* get the decrypted message from the output structure */
+    if (rnp_output_memory_get_buf(output, &buf, &buf_len, false) != RNP_SUCCESS) {
+        goto finish;
+    }
+    fprintf(stdout,
+            "Decrypted message (%s):\n%.*s\n",
+            usekeys ? "with key" : "with password",
+            (int) buf_len,
+            buf);
+
+    result = 0;
+finish:
+    rnp_input_destroy(keyfile);
+    rnp_input_destroy(input);
+    rnp_output_destroy(output);
+    rnp_ffi_destroy(ffi);
+    return result;
+}
+
+int
+main(int argc, char **argv)
+{
+    int res;
+    res = ffi_decrypt(true);
+    if (res) {
+        return res;
+    }
+    res = ffi_decrypt(false);
+    return res;
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/src/examples/dump.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2019, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ * 2.  Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <unistd.h> /* getopt() */
+#include <getopt.h>
+#include <rnp/rnp.h>
+#include <libgen.h> /* basename() */
+
+#define PFX "dump: "
+
+static void
+print_usage(char *program_name)
+{
+    fprintf(stderr,
+            PFX
+            "Program dumps PGP packets. \n\nUsage:\n"
+            "\t%s [-d|-h] [input.pgp]\n"
+            "\t  -d : indicates whether to print packet content. Data is represented as hex\n"
+            "\t  -m : dump mpi values\n"
+            "\t  -g : dump key fingerprints and grips\n"
+            "\t  -j : JSON output\n"
+            "\t  -h : prints help and exists\n",
+            basename(program_name));
+}
+
+static bool
+stdin_reader(void *app_ctx, void *buf, size_t len, size_t *readres)
+{
+    ssize_t res = read(STDIN_FILENO, buf, len);
+    if (res < 0) {
+        return false;
+    }
+    *readres = res;
+    return true;
+}
+
+static bool
+stdout_writer(void *app_ctx, const void *buf, size_t len)
+{
+    ssize_t wlen = write(STDOUT_FILENO, buf, len);
+    return (wlen >= 0) && (size_t) wlen == len;
+}
+
+int
+main(int argc, char *const argv[])
+{
+    char *   input_file = NULL;
+    uint32_t flags = 0;
+    uint32_t jflags = 0;
+    bool     json = false;
+
+    /* Parse command line options:
+        -i input_file [mandatory]: specifies name of the file with PGP packets
+        -d : indicates wether to dump whole packet content
+        -m : dump mpi contents
+        -g : dump key grips and fingerprints
+        -j : JSON output
+        -h : prints help and exists
+    */
+    int opt = 0;
+    while ((opt = getopt(argc, argv, "dmgjh")) != -1) {
+        switch (opt) {
+        case 'd':
+            flags |= RNP_DUMP_RAW;
+            jflags |= RNP_JSON_DUMP_RAW;
+            break;
+        case 'm':
+            flags |= RNP_DUMP_MPI;
+            jflags |= RNP_JSON_DUMP_MPI;
+            break;
+        case 'g':
+            flags |= RNP_DUMP_GRIP;
+            jflags |= RNP_JSON_DUMP_GRIP;
+            break;
+        case 'j':
+            json = true;
+            break;
+        default:
+            print_usage(argv[0]);
+            return 1;
+        }
+    }
+
+    /*  Check whether we have input file */
+    if (optind < argc) {
+        input_file = argv[optind];
+    }
+
+    rnp_input_t  input = NULL;
+    rnp_result_t ret = 0;
+    if (input_file) {
+        ret = rnp_input_from_path(&input, input_file);
+    } else {
+        ret = rnp_input_from_callback(&input, stdin_reader, NULL, NULL);
+    }
+    if (ret) {
+        fprintf(stderr, "failed to open source: error 0x%x\n", (int) ret);
+        return 1;
+    }
+
+    if (!json) {
+        rnp_output_t output = NULL;
+        ret = rnp_output_to_callback(&output, stdout_writer, NULL, NULL);
+        if (ret) {
+            fprintf(stderr, "failed to open stdout: error 0x%x\n", (int) ret);
+            rnp_input_destroy(input);
+            return 1;
+        }
+        ret = rnp_dump_packets_to_output(input, output, flags);
+        rnp_output_destroy(output);
+    } else {
+        char *json = NULL;
+        ret = rnp_dump_packets_to_json(input, jflags, &json);
+        if (!ret) {
+            fprintf(stdout, "%s\n", json);
+        }
+        rnp_buffer_destroy(json);
+    }
+    rnp_input_destroy(input);
+
+    /* Inform in case of error occured during parsing */
+    if (ret) {
+        fprintf(stderr, "Operation failed [error code: 0x%X]\n", (int) ret);
+        return 1;
+    }
+
+    return 0;
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rnp/src/examples/encrypt.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2018, [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ * 2.  Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEO