summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2020-10-13 11:23:55 +0200
committerJustus Winter <justus@sequoia-pgp.org>2020-10-13 11:48:49 +0200
commit88b48afbc4ea4dcd343f3e17a2e43d130bc2628f (patch)
treef44dfaec2df55bb6643ca2682db3fd0222d3a2ac
parent87db0d161c89d944219b2516317ee2155814c2c6 (diff)
openpgp-ffi: New example.
-rw-r--r--openpgp-ffi/examples/Makefile1
-rw-r--r--openpgp-ffi/examples/sign.c106
2 files changed, 107 insertions, 0 deletions
diff --git a/openpgp-ffi/examples/Makefile b/openpgp-ffi/examples/Makefile
index 6742a9a5..fa3c9a4c 100644
--- a/openpgp-ffi/examples/Makefile
+++ b/openpgp-ffi/examples/Makefile
@@ -10,6 +10,7 @@ EXAMPLE_TARGET_DIR ?= $(CARGO_TARGET_DIR)/debug/c-examples/openpgp-ffi
EXAMPLES = \
example reader parser encrypt-for armor \
+ sign \
decrypt-with \
generate-key \
type-safety-demo use-after-free-demo immutable-reference-demo \
diff --git a/openpgp-ffi/examples/sign.c b/openpgp-ffi/examples/sign.c
new file mode 100644
index 00000000..288d9865
--- /dev/null
+++ b/openpgp-ffi/examples/sign.c
@@ -0,0 +1,106 @@
+/* This example demonstrates how to use the low-level interface to
+ create a signed message. */
+
+#define _GNU_SOURCE
+/* Roughly glibc compatible error reporting. */
+#define error(S, E, F, ...) do { \
+ fprintf (stderr, (F), __VA_ARGS__); \
+ int s = (S), e = (E); \
+ if (e) { fprintf (stderr, ": %s", strerror (e)); } \
+ fprintf (stderr, "\n"); \
+ fflush (stderr); \
+ if (s) { exit (s); } \
+ } while (0)
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sequoia/openpgp.h>
+
+int
+main (int argc, char **argv)
+{
+ pgp_error_t err;
+ pgp_cert_t cert;
+ pgp_writer_t sink;
+ pgp_writer_t armor_writer;
+ pgp_writer_stack_t writer = NULL;
+ pgp_policy_t policy = pgp_standard_policy ();
+
+ if (argc != 2)
+ error (1, 0, "Usage: %s <keyfile> <plain >cipher", argv[0]);
+
+ cert = pgp_cert_from_file (&err, argv[1]);
+ if (cert == NULL)
+ error (1, 0, "pgp_cert_from_file: %s", pgp_error_to_string (err));
+
+ /* Iterate over the cert and get the signing key. */
+ pgp_signer_t signer;
+ {
+ pgp_cert_valid_key_iter_t iter;
+ pgp_valid_key_amalgamation_t ka;
+ pgp_key_t key;
+ pgp_key_pair_t signing_keypair;
+
+ iter = pgp_cert_valid_key_iter (cert, policy, 0);
+ pgp_cert_valid_key_iter_alive (iter);
+ pgp_cert_valid_key_iter_revoked (iter, false);
+ pgp_cert_valid_key_iter_for_signing (iter);
+ pgp_cert_valid_key_iter_unencrypted_secret (iter);
+ ka = pgp_cert_valid_key_iter_next(iter, NULL, NULL);
+ if (ka == NULL)
+ error (1, 0, "%s has no signing-capable (sub)key", argv[1]);
+ key = pgp_valid_key_amalgamation_key (ka);
+ assert (pgp_key_has_unencrypted_secret (key));
+ signing_keypair =
+ pgp_key_into_key_pair (NULL, pgp_key_clone (key));
+ assert (signing_keypair);
+ signer = pgp_key_pair_as_signer (/* consumes */ signing_keypair);
+ pgp_key_free (key);
+ pgp_valid_key_amalgamation_free (ka);
+ pgp_cert_valid_key_iter_free (iter);
+ }
+
+ sink = pgp_writer_from_fd (STDOUT_FILENO);
+ armor_writer = pgp_armor_writer_new (&err, sink, PGP_ARMOR_KIND_MESSAGE,
+ NULL, 0);
+
+ writer = pgp_writer_stack_message (armor_writer);
+ writer = pgp_signer_new (&err, writer, /* consumes */ &signer, 1, 0);
+ if (writer == NULL)
+ error (1, 0, "pgp_signer_new: %s", pgp_error_to_string (err));
+
+ writer = pgp_literal_writer_new (&err, writer);
+ if (writer == NULL)
+ error (1, 0, "pgp_literal_writer_new: %s", pgp_error_to_string (err));
+
+ size_t nread;
+ uint8_t buf[4096];
+ while ((nread = fread (buf, 1, sizeof buf, stdin)))
+ {
+ uint8_t *b = buf;
+ while (nread)
+ {
+ ssize_t written;
+ written = pgp_writer_stack_write (&err, writer, b, nread);
+ if (written < 0)
+ error (1, 0, "pgp_writer_stack_write: %s", pgp_error_to_string (err));
+
+ b += written;
+ nread -= written;
+ }
+ }
+
+ if (pgp_writer_stack_finalize (&err, writer))
+ error (1, 0, "pgp_writer_stack_write: %s", pgp_error_to_string (err));
+
+ if (pgp_armor_writer_finalize (&err, armor_writer))
+ error (1, 0, "pgp_armor_writer_finalize: %s", pgp_error_to_string (err));
+ pgp_writer_free (sink);
+ pgp_cert_free (cert);
+ pgp_policy_free (policy);
+ return 0;
+}