What's new in José v8?

Part 1: Streaming and Detachment

June 29, 2017
fedora fedora-security

Wait! What’s José?

José is a general purpose cryptography toolkit which uses the data formats standardized by the JOSE IETF Working Group. By analogy, José is to JOSE what GPG is to OpenPGP and OpenSSL is to X.509.

José provides both a C-language library and a command line interface and is licensed under the Apache Software License version 2.0. José v8+ is available on Fedora 26+ (dnf install jose), Red Hat Enterpirse Linux 7.4+ (yum install jose) and macOS/Homebrew (brew install jose).

Streaming and Detached Mode

José v8 features support for a streaming interface. In previous releases, José would require you to load the entire plaintext, ciphertext or signature payload into memory in order to perform the cryptographic operation. This is now no longer the case.

This can be combined with detached mode signatures (JWS) and encryption (JWE) to reduce the size of the JSON output. In detached mode, the signature payload is not included in the JWS and the ciphertext is not included in the JWE.

Command Line Interface

Performing encryption on the command line is similar to previous versions, but now provides substantially improved memory usage. For example, to sign a large filesystem image you can do this:

$ jose jws sig -I fedora.img -k fedora.jwk -O /dev/null -o fedora.jws

Let’s walk through the arguments here. The -I option specifies the binary input to sign. The -k option indicates what key we want to use for signing. The -O option detaches the payload from the JWS and writes it to the specified file (in our case, /dev/null). Finally, the -o option specifies where to store our signature.

To verify this signature, we just invoke the verification command:

$ jose jws ver -I fedora.img -i fedora.jws -k fedora.jwk \
    || echo "Validation failed!"

Encryption is similar to signing, but the detached ciphertext is not disposable. Hence, we save it to a file: fedora.ct. Otherwise, the options have the same meaning as signing.

$ jose jwe enc -I fedora.img -k fedora.jwk -O fedora.ct -o fedora.jwe

Likewise, decryption requires the invocation of the decryption command:

$ jose jwe dec -I fedora.ct -i fedora.jwe -k fedora.jwk -O fedora.img \
    || echo "Authentication failed!"

Like always, José will infer secure algorithms from the key that is used. But with our new streaming support, we can actually perform these operations without OOMing your system.

C API

Streaming can be performed using the new C APIs. For example, to sign some binary data we would set up the operation like this (error handling excluded for brevity):

jose_io_auto_t *b64 = NULL;
jose_io_auto_t *sig = NULL;
json_auto_t *jws = NULL;

jws = json_object();
sig = jose_jws_sig_io(NULL, jws, NULL, jwk);
b64 = jose_b64_enc_io(sig);

while (!feof(payload_input_file)) {
    uint8_t buf[32] = {};
    size_t r;

    r = fread(buf, 1, sizeof(buf), payload_input_file);
    b64->feed(b64, buf, r);
}

/* The signature is added to the JWS here. */
b64->done(b64);
json_dumpf(jws, jws_output_file, 0);

Decryption is a similar process, with two exceptions. First, so long as our input and output are binary data, we don’t need URL-Safe Base64 codecs. Second, the IO stream for encryption provides ciphertext output that we need to handle. Here is a simple example (again, error handling excluded):

jose_io_auto_t *enc = NULL;
jose_io_auto_t *out = NULL;
json_auto_t *jwe = NULL;

jwe = json_object();
out = jose_io_file(NULL, ciphertext_output_file);
enc = jose_jwe_enc_io(NULL, jwe, NULL, jwk, out);

while (!feof(plaintext_input_file)) {
    uint8_t buf[32] = {};
    size_t r;

    r = fread(buf, 1, sizeof(buf), plaintext_input_file);
    enc->feed(enc, buf, r);
}

/* The tag is added to the JWE here. */
enc->done(enc);
json_dumpf(jwe, jwe_output_file, 0);

A few notes are necessary about both signing and encryption.

First, note that because we used the *_auto_t variants in our declarations, all resources will be cleaned up automatically at the end of the scope.

Second, if you don’t want streaming and just want simple APIs for signing and encryption of small data, we provide these. See the extensive documentation in the José headers.

comments powered by Disqus