Various probably quite untidy progress on KDMs.
authorCarl Hetherington <cth@carlh.net>
Sat, 5 Jan 2013 22:02:24 +0000 (22:02 +0000)
committerCarl Hetherington <cth@carlh.net>
Sat, 5 Jan 2013 22:02:24 +0000 (22:02 +0000)
15 files changed:
run-tests.sh
src/asset.cc
src/certificates.cc
src/certificates.h
src/dcp.cc
src/dcp.h
src/mxf_asset.cc
src/mxf_asset.h
src/picture_asset.cc
src/picture_asset.h
src/sound_asset.cc
src/sound_asset.h
src/util.cc
src/util.h
test/tests.cc

index e08dc86d91e4d3ec8048c15febbb8ff6c15dbe74..671da9198bb4be44c7a67424ecba3270f3fd912a 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/bash -e
 
 #
 # Runs our test suite, which (amongst other things)
index ac8f8b8ed446dc8735cace506c59cb30ef4c5315..62fdddf6ef312918e2e3d40ba6e3f42c0dad66e5 100644 (file)
@@ -91,3 +91,4 @@ Asset::digest () const
 
        return _digest;
 }
+
index ba0ebaaeb48c9520977f90a662e097943ec27359..ac7e20f7384ab2193e68975a7d44b8fb9158e024 100644 (file)
@@ -4,6 +4,7 @@
 #include <openssl/x509.h>
 #include <openssl/ssl.h>
 #include <openssl/asn1.h>
+#include <libxml++/nodes/element.h>
 #include "certificates.h"
 #include "exceptions.h"
 
@@ -104,7 +105,6 @@ Certificate::serial () const
 
        return st;
 }
-               
 
 /** @param filename Text file of PEM-format certificates,
  *  in the order:
index a1a409ac0902fb9ccd0a7bac43fe5973f8d1229c..1c342acb227bb36d63334f93a3b45af06a23691c 100644 (file)
@@ -9,6 +9,10 @@
 
 class certificates;
 
+namespace xmlpp {
+       class Element;
+}
+
 namespace libdcp {
 
 class Certificate : public boost::noncopyable
index 2ece0eacaec75b50793a8f0c6fbc8d0aaa2045fc..a282c33ed62be5b6479bbfd08e8862127b056853 100644 (file)
@@ -471,7 +471,7 @@ CPL::write_xml (bool encrypted, CertificateChain const & certificates, string co
        }
 
        if (encrypted) {
-               DCP::sign (cpl, certificates, signer_key);
+               sign (cpl, certificates, signer_key);
        }
 
        doc.write_to_file_formatted (p.string(), "UTF-8");
@@ -480,98 +480,6 @@ CPL::write_xml (bool encrypted, CertificateChain const & certificates, string co
        _length = boost::filesystem::file_size (p.string ());
 }
 
-void
-DCP::sign (xmlpp::Element* parent, CertificateChain const & certificates, string const & signer_key)
-{
-       xmlpp::Element* signer = parent->add_child("Signer");
-
-       {
-               xmlpp::Element* data = signer->add_child("X509Data", "dsig");
-               {
-                       xmlpp::Element* serial = data->add_child("X509IssuerSerial", "dsig");
-                       serial->add_child("X509IssuerName", "dsig")->add_child_text (
-                               Certificate::name_for_xml (certificates.leaf()->issuer())
-                               );
-                       serial->add_child("X509SerialNumber", "dsig")->add_child_text (
-                               certificates.leaf()->serial()
-                               );
-               }
-               data->add_child("X509SubjectName", "dsig")->add_child_text (
-                       Certificate::name_for_xml (certificates.leaf()->subject())
-                       );
-       }
-       
-       xmlpp::Element* signature = parent->add_child("Signature", "dsig");
-       
-       {
-               xmlpp::Element* signed_info = signature->add_child ("SignedInfo", "dsig");
-               signed_info->add_child("CanonicalizationMethod", "dsig")->set_attribute ("Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315");
-               signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
-               {
-                       xmlpp::Element* reference = signed_info->add_child("Reference", "dsig");
-                       reference->set_attribute ("URI", "");
-                       {
-                               xmlpp::Element* transforms = reference->add_child("Transforms", "dsig");
-                               transforms->add_child("Transform", "dsig")->set_attribute (
-                                       "Algorithm", "http://www.w3.org/2000/09/xmldsig#enveloped-signature"
-                                       );
-                       }
-                       reference->add_child("DigestMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1");
-                       /* This will be filled in by the signing later */
-                       reference->add_child("DigestValue", "dsig");
-               }
-       }
-       
-       signature->add_child("SignatureValue", "dsig");
-       
-       xmlpp::Element* key_info = signature->add_child("KeyInfo", "dsig");
-       list<shared_ptr<Certificate> > c = certificates.leaf_to_root ();
-       for (list<shared_ptr<Certificate> >::iterator i = c.begin(); i != c.end(); ++i) {
-               xmlpp::Element* data = key_info->add_child("X509Data", "dsig");
-               
-               {
-                       xmlpp::Element* serial = data->add_child("X509IssuerSerial", "dsig");
-                       serial->add_child("X509IssuerName", "dsig")->add_child_text(
-                               Certificate::name_for_xml ((*i)->issuer())
-                               );
-                       serial->add_child("X509SerialNumber", "dsig")->add_child_text((*i)->serial());
-               }
-               
-               data->add_child("X509Certificate", "dsig")->add_child_text((*i)->certificate());
-       }
-       
-       xmlSecKeysMngrPtr keys_manager = xmlSecKeysMngrCreate();
-       if (!keys_manager) {
-               throw MiscError ("could not create keys manager");
-       }
-       if (xmlSecCryptoAppDefaultKeysMngrInit (keys_manager) < 0) {
-               throw MiscError ("could not initialise keys manager");
-       }
-       
-       xmlSecKeyPtr const key = xmlSecCryptoAppKeyLoad (signer_key.c_str(), xmlSecKeyDataFormatPem, 0, 0, 0);
-       if (key == 0) {
-               throw MiscError ("could not load signer key");
-               }
-       
-       if (xmlSecCryptoAppDefaultKeysMngrAdoptKey (keys_manager, key) < 0) {
-               xmlSecKeyDestroy (key);
-               throw MiscError ("could not use signer key");
-       }
-       
-       xmlSecDSigCtx signature_context;
-       
-       if (xmlSecDSigCtxInitialize (&signature_context, keys_manager) < 0) {
-               throw MiscError ("could not initialise XMLSEC context");
-       }
-       
-       if (xmlSecDSigCtxSign (&signature_context, signature->cobj()) < 0) {
-               throw MiscError ("could not sign CPL");
-       }
-       
-       xmlSecDSigCtxFinalize (&signature_context);
-       xmlSecKeysMngrDestroy (keys_manager);
-}
-
 void
 CPL::write_to_pkl (xmlpp::Element* p) const
 {
@@ -660,3 +568,147 @@ CPL::equals (CPL const & other, EqualityOptions opt, list<string>& notes) const
 
        return true;
 }
+
+shared_ptr<xmlpp::Document>
+CPL::make_kdm (CertificateChain const & certificates, string const & signer_key, shared_ptr<const Certificate> recipient_cert) const
+{
+       shared_ptr<xmlpp::Document> doc (new xmlpp::Document);
+       xmlpp::Element* root = doc->create_root_node ("DCinemaSecurityMessage");
+       root->set_namespace_declaration ("http://www.smpte-ra.org/schemas/430-3/2006/ETM", "");
+       root->set_namespace_declaration ("http://www.w3.org/2000/09/xmldsig#", "ds");
+       root->set_namespace_declaration ("http://www.w3.org/2001/04/xmlenc#", "enc");
+
+       {
+               xmlpp::Element* authenticated_public = root->add_child("AuthenticatedPublic");
+               authenticated_public->set_attribute("Id", "ID_AuthenticatedPublic");
+               xmlAddID (0, doc->cobj(), (const xmlChar *) "ID_AuthenticatedPublic", authenticated_public->get_attribute("Id")->cobj());
+               
+               authenticated_public->add_child("MessageId")->add_child_text("urn:uuid:" + make_uuid());
+               authenticated_public->add_child("MessageType")->add_child_text("http://www.smpte-ra.org/430-1/2006/KDM#kdm-key-type");
+               authenticated_public->add_child("AnnotationText")->add_child_text(Metadata::instance()->product_name);
+               authenticated_public->add_child("IssueDate")->add_child_text(Metadata::instance()->issue_date);
+
+               {
+                       xmlpp::Element* signer = authenticated_public->add_child("Signer");
+                       signer->add_child("X509IssuerName", "ds")->add_child_text (
+                               Certificate::name_for_xml (recipient_cert->issuer())
+                               );
+                       signer->add_child("X509SerialNumber", "ds")->add_child_text (
+                               recipient_cert->serial()
+                               );
+               }
+
+               {
+                       xmlpp::Element* required_extensions = authenticated_public->add_child("RequiredExtensions");
+
+                       {
+                               xmlpp::Element* kdm_required_extensions = required_extensions->add_child("KDMRequiredExtensions");
+                               kdm_required_extensions->set_namespace_declaration ("http://www.smpte-ra.org/schemas/430-1/2006/KDM");
+                               {
+                                       xmlpp::Element* recipient = kdm_required_extensions->add_child("Recipient");
+                                       {
+                                               xmlpp::Element* serial_element = recipient->add_child("X509IssuerSerial");
+                                               serial_element->add_child("X509IssuerName", "ds")->add_child_text (
+                                                       Certificate::name_for_xml (recipient_cert->issuer())
+                                                       );
+                                               serial_element->add_child("X509SerialNumber", "ds")->add_child_text (
+                                                       recipient_cert->serial()
+                                                       );
+                                       }
+
+                                       recipient->add_child("X509SubjectName")->add_child_text (Certificate::name_for_xml (recipient_cert->subject()));
+                               }
+
+                               kdm_required_extensions->add_child("CompositionPlaylistId")->add_child_text("XXX");
+                               kdm_required_extensions->add_child("ContentTitleText")->add_child_text("XXX");
+                               kdm_required_extensions->add_child("ContentAuthenticator")->add_child_text("XXX");
+                               kdm_required_extensions->add_child("ContentKeysNotValidBefore")->add_child_text("XXX");
+                               kdm_required_extensions->add_child("ContentKeysNotValidAfter")->add_child_text("XXX");
+
+                               {
+                                       xmlpp::Element* authorized_device_info = kdm_required_extensions->add_child("AuthorizedDeviceInfo");
+                                       authorized_device_info->add_child("DeviceListIdentifier")->add_child_text("urn:uuid:" + make_uuid());
+                                       authorized_device_info->add_child("DeviceListDescription")->add_child_text(recipient_cert->subject());
+                                       {
+                                               xmlpp::Element* device_list = authorized_device_info->add_child("DeviceList");
+                                               device_list->add_child("CertificateThumbprint")->add_child_text("XXX");
+                                       }
+                               }
+
+                               {
+                                       xmlpp::Element* key_id_list = kdm_required_extensions->add_child("KeyIdList");
+                                       list<shared_ptr<const Asset> > a = assets();
+                                       for (list<shared_ptr<const Asset> >::iterator i = a.begin(); i != a.end(); ++i) {
+                                               /* XXX: non-MXF assets? */
+                                               shared_ptr<const MXFAsset> mxf = boost::dynamic_pointer_cast<const MXFAsset> (*i);
+                                               if (mxf) {
+                                                       mxf->add_typed_key_id (key_id_list);
+                                               }
+                                       }
+                               }
+
+                               {
+                                       xmlpp::Element* forensic_mark_flag_list = kdm_required_extensions->add_child("ForensicMarkFlagList");
+                                       forensic_mark_flag_list->add_child("ForensicMarkFlag")->add_child_text ( 
+                                               "http://www.smpte-ra.org/430-1/2006/KDM#mrkflg-picture-disable"
+                                               );
+                                       forensic_mark_flag_list->add_child("ForensicMarkFlag")->add_child_text ( 
+                                               "http://www.smpte-ra.org/430-1/2006/KDM#mrkflg-audio-disable"
+                                               );
+                               }
+                       }
+               }
+                                        
+               authenticated_public->add_child("NonCriticalExtensions");
+       }
+
+       {
+               xmlpp::Element* authenticated_private = root->add_child("AuthenticatedPrivate");
+               authenticated_private->set_attribute ("Id", "ID_AuthenticatedPrivate");
+               xmlAddID (0, doc->cobj(), (const xmlChar *) "ID_AuthenticatedPrivate", authenticated_private->get_attribute("Id")->cobj());
+               {
+                       xmlpp::Element* encrypted_key = authenticated_private->add_child ("EncryptedKey", "enc");
+                       {
+                               xmlpp::Element* encryption_method = encrypted_key->add_child ("EncryptionMethod", "enc");
+                               encryption_method->set_attribute ("Algorithm", "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p");
+                               encryption_method->add_child("DigestMethod", "ds")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1");
+                       }
+
+                       xmlpp::Element* cipher_data = authenticated_private->add_child ("CipherData", "enc");
+                       cipher_data->add_child("CipherValue", "enc")->add_child_text("XXX");
+               }
+       }
+       
+       /* XXX: x2 one for each mxf? */
+
+       {
+               xmlpp::Element* signature = root->add_child("Signature", "ds");
+               
+               {
+                       xmlpp::Element* signed_info = signature->add_child("SignedInfo", "ds");
+                       signed_info->add_child("CanonicalizationMethod", "ds")->set_attribute(
+                               "Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"
+                               );
+                       signed_info->add_child("SignatureMethod", "ds")->set_attribute(
+                               "Algorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
+                               );
+                       {
+                               xmlpp::Element* reference = signed_info->add_child("Reference", "ds");
+                               reference->set_attribute("URI", "#ID_AuthenticatedPublic");
+                               reference->add_child("DigestMethod", "ds")->set_attribute("Algorithm", "http://www.w3.org/2001/04/xmlenc#sha256");
+                               reference->add_child("DigestValue", "ds");
+                       }
+                       
+                       {                               
+                               xmlpp::Element* reference = signed_info->add_child("Reference", "ds");
+                               reference->set_attribute("URI", "#ID_AuthenticatedPrivate");
+                               reference->add_child("DigestMethod", "ds")->set_attribute("Algorithm", "http://www.w3.org/2001/04/xmlenc#sha256");
+                               reference->add_child("DigestValue", "ds");
+                       }
+               }
+               
+               add_signature_value (signature, certificates, signer_key, "ds");
+       }
+
+       return doc;
+}
index 0ee4a8fc8bd23856461f6b3c80f5c296e984abac..96b28090a84c8cea3d9c6d8725c20b9ab37e81aa 100644 (file)
--- a/src/dcp.h
+++ b/src/dcp.h
@@ -32,6 +32,7 @@
 #include "certificates.h"
 
 namespace xmlpp {
+       class Document;
        class Element;
 }
 
@@ -89,6 +90,8 @@ public:
        void write_xml (bool, CertificateChain const &, std::string const &) const;
        void write_to_assetmap (std::ostream& s) const;
        void write_to_pkl (xmlpp::Element* p) const;
+
+       boost::shared_ptr<xmlpp::Document> make_kdm (CertificateChain const &, std::string const &, boost::shared_ptr<const Certificate>) const;
        
 private:
        std::string _directory;
@@ -159,17 +162,23 @@ public:
                _certificates = c;
        }
 
+       CertificateChain certificates () const {
+               return _certificates;
+       }
+
        void set_signer_key (std::string const & s) {
                _signer_key = s;
        }
 
+       std::string signer_key () const {
+               return _signer_key;
+       }
+
        /** Emitted with a parameter between 0 and 1 to indicate progress
         *  for long jobs.
         */
        boost::signals2::signal<void (float)> Progress;
 
-       static void sign (xmlpp::Element* parent, CertificateChain const & certificates, std::string const & signer_key);
-
 private:
 
        /** Write the PKL file.
index d229331bf5fc96750f1eae8b11b53c1c9f9032b7..6ba42d754f5ed7a15edd7ebbddf4bd03edd53175 100644 (file)
@@ -24,6 +24,7 @@
 #include <iostream>
 #include <fstream>
 #include <boost/filesystem.hpp>
+#include <libxml++/nodes/element.h>
 #include "AS_DCP.h"
 #include "KM_prng.h"
 #include "KM_util.h"
@@ -128,3 +129,11 @@ MXFAsset::length () const
 {
        return _length;
 }
+
+void
+MXFAsset::add_typed_key_id (xmlpp::Element* parent) const
+{
+       xmlpp::Element* typed_key_id = parent->add_child("TypedKeyId");
+       typed_key_id->add_child("KeyType")->add_child_text(key_type ());
+       typed_key_id->add_child("KeyId")->add_child_text("urn:uuid:" + _key_id);
+}
index e45ab2d7525077063d1ac357ee13e4a50555ac96..f68edc61f8d4a639a1131da12231b511c1cc2b3a 100644 (file)
@@ -51,8 +51,11 @@ public:
        virtual bool equals (boost::shared_ptr<const Asset> other, EqualityOptions opt, std::list<std::string>& notes) const;
        
        int length () const;
+       void add_typed_key_id (xmlpp::Element *) const;
 
 protected:
+       virtual std::string key_type () const = 0;
+       
        /** Fill in a ADSCP::WriteInfo struct.
         *  @param w struct to fill in.
         */
index 295afc153335c8e319072f0dddb6b3e61cc57084..f783bb3972added3c5aa02f9e7a2d594de9728ec 100644 (file)
@@ -391,3 +391,9 @@ StereoPictureAsset::get_frame (int n) const
 {
        return shared_ptr<const StereoPictureFrame> (new StereoPictureFrame (path().string(), n + _entry_point));
 }
+
+string
+PictureAsset::key_type () const
+{
+       return "MDIK";
+}
index 15764dab6961c2324e7c799d111a029803716562..96bf5659db44d9ae784e2d70d39043393c1d9e3d 100644 (file)
@@ -64,6 +64,9 @@ protected:
        int _width;
        /** picture height in pixels */
        int _height;
+
+private:
+       std::string key_type () const;
 };
 
 /** A 2D (monoscopic) picture asset */
index b71d218f8a0308d9f60a08c3d2c6357d98df2be3..77267cbd33701037598114361b44e1db97691c5c 100644 (file)
@@ -285,3 +285,9 @@ SoundAsset::get_frame (int n) const
 {
        return shared_ptr<const SoundFrame> (new SoundFrame (path().string(), n + _entry_point));
 }
+
+string
+SoundAsset::key_type () const
+{
+       return "MDAK";
+}
index 0a6c8f4e1ebad38b3dd50b57af42b2e38ddea136..6711560660bfd9d56be0e3883caefcc0366b21a7 100644 (file)
@@ -104,6 +104,8 @@ public:
        }
 
 private:
+       std::string key_type () const;
+       
        void construct (boost::function<std::string (Channel)> get_path);
        std::string path_from_channel (Channel channel, std::vector<std::string> const & files);
 
index 323fb1e46070df84345f98b9d833fa66a3b4f264..ea6f6c0d95c847cd0b9767c0a1ed310b34b43b65 100644 (file)
@@ -27,6 +27,8 @@
 #include <iomanip>
 #include <boost/filesystem.hpp>
 #include <openssl/sha.h>
+#include <libxml++/nodes/element.h>
+#include <libxml++/document.h>
 #include <xmlsec/xmldsig.h>
 #include <xmlsec/dl.h>
 #include <xmlsec/app.h>
 #include "types.h"
 #include "argb_frame.h"
 #include "lut.h"
+#include "certificates.h"
 
 using std::string;
 using std::cout;
 using std::stringstream;
 using std::min;
 using std::max;
+using std::list;
 using boost::shared_ptr;
 using namespace libdcp;
 
@@ -293,3 +297,109 @@ libdcp::init ()
                throw MiscError ("could not initialise xmlsec-crypto");
        }
 }
+
+void
+libdcp::add_signature_value (xmlpp::Element* parent, CertificateChain const & certificates, string const & signer_key, string const & ns)
+{
+       parent->add_child("SignatureValue", ns);
+       
+       xmlpp::Element* key_info = parent->add_child("KeyInfo", ns);
+       list<shared_ptr<Certificate> > c = certificates.leaf_to_root ();
+       for (list<shared_ptr<Certificate> >::iterator i = c.begin(); i != c.end(); ++i) {
+               xmlpp::Element* data = key_info->add_child("X509Data", ns);
+               
+               {
+                       xmlpp::Element* serial = data->add_child("X509IssuerSerial", ns);
+                       serial->add_child("X509IssuerName", ns)->add_child_text(
+                               Certificate::name_for_xml ((*i)->issuer())
+                               );
+                       serial->add_child("X509SerialNumber", ns)->add_child_text((*i)->serial());
+               }
+               
+               data->add_child("X509Certificate", ns)->add_child_text((*i)->certificate());
+       }
+
+       xmlSecKeysMngrPtr keys_manager = xmlSecKeysMngrCreate();
+       if (!keys_manager) {
+               throw MiscError ("could not create keys manager");
+       }
+       if (xmlSecCryptoAppDefaultKeysMngrInit (keys_manager) < 0) {
+               throw MiscError ("could not initialise keys manager");
+       }
+       
+       xmlSecKeyPtr const key = xmlSecCryptoAppKeyLoad (signer_key.c_str(), xmlSecKeyDataFormatPem, 0, 0, 0);
+       if (key == 0) {
+               throw MiscError ("could not load signer key");
+               }
+       
+       if (xmlSecCryptoAppDefaultKeysMngrAdoptKey (keys_manager, key) < 0) {
+               xmlSecKeyDestroy (key);
+               throw MiscError ("could not use signer key");
+       }
+       
+       xmlSecDSigCtx signature_context;
+       
+       if (xmlSecDSigCtxInitialize (&signature_context, keys_manager) < 0) {
+               throw MiscError ("could not initialise XMLSEC context");
+       }
+       
+       if (xmlSecDSigCtxSign (&signature_context, parent->cobj()) < 0) {
+               throw MiscError ("could not sign");
+       }
+       
+       xmlSecDSigCtxFinalize (&signature_context);
+       xmlSecKeysMngrDestroy (keys_manager);
+}
+
+
+void
+libdcp::add_signer (xmlpp::Element* parent, CertificateChain const & certificates, string const & ns)
+{
+       xmlpp::Element* signer = parent->add_child("Signer");
+
+       {
+               xmlpp::Element* data = signer->add_child("X509Data", ns);
+               
+               {
+                       xmlpp::Element* serial_element = data->add_child("X509IssuerSerial", ns);
+                       serial_element->add_child("X509IssuerName", ns)->add_child_text (
+                               Certificate::name_for_xml (certificates.leaf()->issuer())
+                               );
+                       serial_element->add_child("X509SerialNumber", ns)->add_child_text (
+                               certificates.leaf()->serial()
+                               );
+               }
+               
+               data->add_child("X509SubjectName", ns)->add_child_text (Certificate::name_for_xml (certificates.leaf()->subject()));
+       }
+}
+
+void
+libdcp::sign (xmlpp::Element* parent, CertificateChain const & certificates, string const & signer_key)
+{
+       add_signer (parent, certificates, "dsig");
+
+       xmlpp::Element* signature = parent->add_child("Signature", "dsig");
+       
+       {
+               xmlpp::Element* signed_info = signature->add_child ("SignedInfo", "dsig");
+               signed_info->add_child("CanonicalizationMethod", "dsig")->set_attribute ("Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315");
+               signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
+               {
+                       xmlpp::Element* reference = signed_info->add_child("Reference", "dsig");
+                       reference->set_attribute ("URI", "");
+                       {
+                               xmlpp::Element* transforms = reference->add_child("Transforms", "dsig");
+                               transforms->add_child("Transform", "dsig")->set_attribute (
+                                       "Algorithm", "http://www.w3.org/2000/09/xmldsig#enveloped-signature"
+                                       );
+                       }
+                       reference->add_child("DigestMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1");
+                       /* This will be filled in by the signing later */
+                       reference->add_child("DigestValue", "dsig");
+               }
+       }
+       
+       add_signature_value (signature, certificates, signer_key, "dsig");
+}
+
index 6426eb8dc768b5dc6838da7638bf2910cf7eccfb..3b60e0c7359ac0c245047d66c80d6df3072138ae 100644 (file)
 #include <openjpeg.h>
 #include "types.h"
 
+namespace xmlpp {
+       class Element;
+}
+
 namespace libdcp {
 
-class ARGBFrame;       
+class ARGBFrame;
+class CertificateChain;
        
 /** Create a UUID.
  *  @return UUID.
@@ -55,4 +60,8 @@ extern boost::shared_ptr<ARGBFrame> xyz_to_rgb (opj_image_t* xyz_frame);
 
 extern void init ();
 
+extern void sign (xmlpp::Element* parent, CertificateChain const & certificates, std::string const & signer_key);
+extern void add_signature_value (xmlpp::Element* parent, CertificateChain const & certificates, std::string const & signer_key, std::string const & ns);
+extern void add_signer (xmlpp::Element* parent, CertificateChain const & certificates, std::string const & ns);
+       
 }
index 3d0e4254584e0f0ad6e6ee3a19eccfd60d376846..7c3144a1445952334ebbd8aff069e3d32776a112 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <cmath>
 #include <boost/filesystem.hpp>
+#include <libxml++/libxml++.h>
 #include "KM_prng.h"
 #include "dcp.h"
 #include "util.h"
@@ -632,6 +633,8 @@ BOOST_AUTO_TEST_CASE (encryption)
        d.add_cpl (cpl);
 
        d.write_xml ();
+
+       cpl->make_kdm(d.certificates(), d.signer_key(), d.certificates().leaf())->write_to_file_formatted ("build/test/bar.kdm.xml", "UTF-8");
 }
 
 BOOST_AUTO_TEST_CASE (certificates)