## Using keys manager for signatures/encryption.

Instead of specifiying signature or encryption key in the corresponding context object (`signKey` member of xmlSecDSigCtx structure or `encKey` member of xmlSecEncCtx structure), the application can use keys manager to select the signature or encryption key. This is especialy useful when you are encrypting or signing something with a session key which is by itself should be encrypted. The key for the session key encryption in the <EncryptedKey/> node could be selected using <dsig:KeyName/> node in the template.

Example 17. Encrypting file using a session key and a permanent key from keys manager.

    /**
     * load_rsa_keys:
     * @key_file:		the key filename.
     *
     * Creates default keys manager and load RSA key from #key_file in it.
     * The caller is responsible for destroing returned keys manager using
     * @xmlSecKeysMngrDestroy.
     *
     * Returns the pointer to newly created keys manager or NULL if an error
     * occurs.
     */
    xmlSecKeysMngrPtr
    load_rsa_keys(char* key_file) {
        xmlSecKeysMngrPtr mngr;
        xmlSecKeyPtr key;

        assert(key_file);

        /* create and initialize keys manager, we use a default list based
         * keys manager, implement your own xmlSecKeysStore klass if you need
         * something more sophisticated
         */
        mngr = xmlSecKeysMngrCreate();
        if(mngr == NULL) {
    	fprintf(stderr, "Error: failed to create keys manager.\n");
    	return(NULL);
        }
        if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
    	fprintf(stderr, "Error: failed to initialize keys manager.\n");
    	xmlSecKeysMngrDestroy(mngr);
    	return(NULL);
        }

        /* load private RSA key */
        key = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
        if(key == NULL) {
            fprintf(stderr,"Error: failed to load rsa key from file \"%s\"\n", key_file);
            xmlSecKeysMngrDestroy(mngr);
            return(NULL);
        }

        /* set key name to the file name, this is just an example! */
        if(xmlSecKeySetName(key, BAD_CAST key_file) < 0) {
            fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
            xmlSecKeyDestroy(key);
    	xmlSecKeysMngrDestroy(mngr);
    	return(NULL);
        }

        /* add key to keys manager, from now on keys manager is responsible
         * for destroying key
         */
        if(xmlSecCryptoAppDefaultKeysMngrAdoptKey(mngr, key) < 0) {
            fprintf(stderr,"Error: failed to add key from \"%s\" to keys manager\n", key_file);
            xmlSecKeyDestroy(key);
            xmlSecKeysMngrDestroy(mngr);
            return(NULL);
        }

        return(mngr);
    }

    /**
     * encrypt_file:
     * @mngr:		the pointer to keys manager.
     * @xml_file:		the encryption template file name.
     * @key_name:		the RSA key name.
     *
     * Encrypts #xml_file using a dynamicaly created template, a session DES key
     * and an RSA key from keys manager.
     *
     * Returns 0 on success or a negative value if an error occurs.
     */
    int
    encrypt_file(xmlSecKeysMngrPtr mngr, const char* xml_file, const char* key_name) {
        xmlDocPtr doc = NULL;
        xmlNodePtr encDataNode = NULL;
        xmlNodePtr keyInfoNode = NULL;
        xmlNodePtr encKeyNode = NULL;
        xmlNodePtr keyInfoNode2 = NULL;
        xmlSecEncCtxPtr encCtx = NULL;
        int res = -1;

        assert(mngr);
        assert(xml_file);
        assert(key_name);

        /* load template */
        doc = xmlParseFile(xml_file);
        if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
    	fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file);
    	goto done;
        }

        /* create encryption template to encrypt XML file and replace
         * its content with encryption result */
        encDataNode = xmlSecTmplEncDataCreate(doc, xmlSecTransformDes3CbcId,
    				NULL, xmlSecTypeEncElement, NULL, NULL);
        if(encDataNode == NULL) {
    	fprintf(stderr, "Error: failed to create encryption template\n");
    	goto done;
        }

        /* we want to put encrypted data in the <enc:CipherValue/> node */
        if(xmlSecTmplEncDataEnsureCipherValue(encDataNode) == NULL) {
    	fprintf(stderr, "Error: failed to add CipherValue node\n");
    	goto done;
        }

        /* add <dsig:KeyInfo/> */
        keyInfoNode = xmlSecTmplEncDataEnsureKeyInfo(encDataNode, NULL);
        if(keyInfoNode == NULL) {
    	fprintf(stderr, "Error: failed to add key info\n");
    	goto done;
        }

        /* add <enc:EncryptedKey/> to store the encrypted session key */
        encKeyNode = xmlSecTmplKeyInfoAddEncryptedKey(keyInfoNode,
    				    xmlSecTransformRsaOaepId,
    				    NULL, NULL, NULL);
        if(encKeyNode == NULL) {
    	fprintf(stderr, "Error: failed to add key info\n");
    	goto done;
        }

        /* we want to put encrypted key in the <enc:CipherValue/> node */
        if(xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == NULL) {
    	fprintf(stderr, "Error: failed to add CipherValue node\n");
    	goto done;
        }

        /* add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to <enc:EncryptedKey/> */
        keyInfoNode2 = xmlSecTmplEncDataEnsureKeyInfo(encKeyNode, NULL);
        if(keyInfoNode2 == NULL) {
    	fprintf(stderr, "Error: failed to add key info\n");
    	goto done;
        }

        /* set key name so we can lookup key when needed */
        if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode2, key_name) == NULL) {
    	fprintf(stderr, "Error: failed to add key name\n");
    	goto done;
        }

        /* create encryption context */
        encCtx = xmlSecEncCtxCreate(mngr);
        if(encCtx == NULL) {
            fprintf(stderr,"Error: failed to create encryption context\n");
    	goto done;
        }

        /* generate a Triple DES key */
        encCtx->encKey = xmlSecKeyGenerate(xmlSecKeyDataDesId, 192, xmlSecKeyDataTypeSession);
        if(encCtx->encKey == NULL) {
            fprintf(stderr,"Error: failed to generate session des key\n");
    	goto done;
        }

        /* encrypt the data */
        if(xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, xmlDocGetRootElement(doc)) < 0) {
            fprintf(stderr,"Error: encryption failed\n");
    	goto done;
        }

        /* we template is inserted in the doc */
        encDataNode = NULL;

        /* print encrypted data with document to stdout */
        xmlDocDump(stdout, doc);

        /* success */
        res = 0;

    done:

        /* cleanup */
        if(encCtx != NULL) {
    	xmlSecEncCtxDestroy(encCtx);
        }

        if(encDataNode != NULL) {
    	xmlFreeNode(encDataNode);
        }

        if(doc != NULL) {
    	xmlFreeDoc(doc);
        }
        return(res);
    }

Full program listing