diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-10-09 10:43:22 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-10-09 10:43:22 +0100 |
| commit | 48e87acf77fb35f2c1a5cdad29f07ec0e4a26f3a (patch) | |
| tree | 99f929830620ea331490edc14cf02b9f0c88368e /src | |
| parent | 259113a96dc9dfbef0b26ff2e142ee673abcd53d (diff) | |
Avoid use of pipes in openssl hackery.
Diffstat (limited to 'src')
| -rw-r--r-- | src/signer_chain.cc | 104 | ||||
| -rw-r--r-- | src/signer_chain.h | 8 | ||||
| -rw-r--r-- | src/util.cc | 4 |
3 files changed, 77 insertions, 39 deletions
diff --git a/src/signer_chain.cc b/src/signer_chain.cc index 1fa8090d..879f31f4 100644 --- a/src/signer_chain.cc +++ b/src/signer_chain.cc @@ -21,8 +21,13 @@ #include <sstream> #include <boost/filesystem.hpp> #include <boost/algorithm/string.hpp> +#include <openssl/sha.h> +#include <openssl/bio.h> +#include <openssl/evp.h> +#include "KM_util.h" #include "signer_chain.h" #include "exceptions.h" +#include "util.h" using std::string; using std::ofstream; @@ -44,8 +49,68 @@ static void command (char const * c) } } +/** Extract a public key from a private key and create a SHA1 digest of it. + * @param key Private key + * @return SHA1 digest of corresponding public key, with escaped / characters. + */ + +static string +public_key_digest (boost::filesystem::path private_key) +{ + boost::filesystem::path public_name = private_key.string() + ".public"; + + /* Create the public key from the private key */ + stringstream s; + s << "openssl rsa -outform PEM -pubout -in " << private_key.string() << " > " << public_name.string (); + command (s.str().c_str ()); + + /* Read in the public key from the file */ + + string pub; + ifstream f (public_name.string().c_str ()); + + bool read = false; + while (1) { + string line; + getline (f, line); + if (line.length() >= 10 && line.substr(0, 10) == "-----BEGIN") { + read = true; + } else if (line.length() >= 8 && line.substr(0, 8) == "-----END") { + break; + } else if (read) { + pub += line; + } + } + + /* Decode the base64 of the public key */ + + unsigned char buffer[512]; + int const N = libdcp::base64_decode (pub, buffer, 1024); + + /* Hash it with SHA1 (without the first 24 bytes, for reasons that are not entirely clear) */ + + SHA_CTX context; + if (!SHA1_Init (&context)) { + throw libdcp::MiscError ("could not init SHA1 context"); + } + + if (!SHA1_Update (&context, buffer + 24, N - 24)) { + throw libdcp::MiscError ("could not update SHA1 digest"); + } + + unsigned char digest[SHA_DIGEST_LENGTH]; + if (!SHA1_Final (digest, &context)) { + throw libdcp::MiscError ("could not finish SHA1 digest"); + } + + char digest_base64[64]; + string dig = Kumu::base64encode (digest, SHA_DIGEST_LENGTH, digest_base64, 64); + boost::replace_all (dig, "/", "\\\\/"); + return dig; +} + void -libdcp::make_signer_chain (boost::filesystem::path directory) +libdcp::make_signer_chain (boost::filesystem::path directory, boost::filesystem::path openssl) { boost::filesystem::path const cwd = boost::filesystem::current_path (); @@ -68,18 +133,7 @@ libdcp::make_signer_chain (boost::filesystem::path directory) << "CN = Entity and dnQualifier\n"; } - command ("openssl rsa -outform PEM -pubout -in ca.key | openssl base64 -d | dd bs=1 skip=24 2>/dev/null | openssl sha1 -binary | openssl base64 > ca_dnq"); - - string ca_dnq; - - { - ifstream f ("ca_dnq"); - getline (f, ca_dnq); - /* XXX: is this right? */ - boost::replace_all (ca_dnq, "/", "\\\\/"); - } - - string const ca_subject = "/O=example.org/OU=example.org/CN=.smpte-430-2.ROOT.NOT_FOR_PRODUCTION/dnQualifier=" + ca_dnq; + string const ca_subject = "/O=example.org/OU=example.org/CN=.smpte-430-2.ROOT.NOT_FOR_PRODUCTION/dnQualifier=" + public_key_digest ("ca.key"); { stringstream c; @@ -104,18 +158,8 @@ libdcp::make_signer_chain (boost::filesystem::path directory) << "OU = Organization unit\n" << "CN = Entity and dnQualifier\n"; } - - command ("openssl rsa -outform PEM -pubout -in intermediate.key | openssl base64 -d | dd bs=1 skip=24 2>/dev/null | openssl sha1 -binary | openssl base64 > inter_dnq"); - - string inter_dnq; - - { - ifstream f ("inter_dnq"); - getline (f, inter_dnq); - boost::replace_all (inter_dnq, "/", "\\\\/"); - } - string const inter_subject = "/O=example.org/OU=example.org/CN=.smpte-430-2.INTERMEDIATE.NOT_FOR_PRODUCTION/dnQualifier=" + inter_dnq; + string const inter_subject = "/O=example.org/OU=example.org/CN=.smpte-430-2.INTERMEDIATE.NOT_FOR_PRODUCTION/dnQualifier=" + public_key_digest ("intermediate.key"); { stringstream s; @@ -144,17 +188,7 @@ libdcp::make_signer_chain (boost::filesystem::path directory) << "CN = Entity and dnQualifier\n"; } - command ("openssl rsa -outform PEM -pubout -in leaf.key | openssl base64 -d | dd bs=1 skip=24 2>/dev/null | openssl sha1 -binary | openssl base64 > leaf_dnq"); - - string leaf_dnq; - - { - ifstream f ("leaf_dnq"); - getline (f, leaf_dnq); - boost::replace_all (leaf_dnq, "/", "\\\\/"); - } - - string const leaf_subject = "/O=example.org/OU=example.org/CN=CS.smpte-430-2.LEAF.NOT_FOR_PRODUCTION/dnQualifier=" + leaf_dnq; + string const leaf_subject = "/O=example.org/OU=example.org/CN=CS.smpte-430-2.LEAF.NOT_FOR_PRODUCTION/dnQualifier=" + public_key_digest ("leaf.key"); { stringstream s; diff --git a/src/signer_chain.h b/src/signer_chain.h index ea67f7e1..50f56ed9 100644 --- a/src/signer_chain.h +++ b/src/signer_chain.h @@ -20,7 +20,11 @@ #include <boost/filesystem.hpp> namespace libdcp { - -void make_signer_chain (boost::filesystem::path); + +/** Create a chain of certificates for signing things. + * @param directory Directory to write files to. + * @param openssl Name of openssl binary (if it is on the path) or full path. + */ +void make_signer_chain (boost::filesystem::path directory, boost::filesystem::path openssl); } diff --git a/src/util.cc b/src/util.cc index 11052df6..ea014bc7 100644 --- a/src/util.cc +++ b/src/util.cc @@ -111,11 +111,11 @@ libdcp::make_digest (string filename, boost::function<void (float)>* progress) } } - byte_t byte_buffer[20]; + byte_t byte_buffer[SHA_DIGEST_LENGTH]; SHA1_Final (byte_buffer, &sha); char digest[64]; - return Kumu::base64encode (byte_buffer, 20, digest, 64); + return Kumu::base64encode (byte_buffer, SHA_DIGEST_LENGTH, digest, 64); } /** Convert a content kind to a string which can be used in a |
