Implementing a custom keys store.

Home Download News Documentation FAQ Tutorial API reference Examples XML Digital Signature Online Verifier XML Encryption XML Canonicalization Reporting Bugs Mailing list Related
XML Security Library Reference Manual
<<< Previous Page | Home | Up | Next Page >>>
# Implementing a custom keys store. In many cases, a default built-in list based keys store is not good enough. For example, XML Security Library (and the built-in default keys store) have no synchronization and you'll need to implement a custom keys store if you want to add or remove keys while other threads use the store. Example 4. Creating a custom keys manager.
    /**
     * create_files_keys_mngr:
     *
     * Creates a files based keys manager: we assume that key name is
     * the key file name,
     *
     * Returns pointer to newly created keys manager or NULL if an error occurs.
     */
    xmlSecKeysMngrPtr
    create_files_keys_mngr(void) {
        xmlSecKeyStorePtr keysStore;
        xmlSecKeysMngrPtr mngr;

        /* create files based keys store */
        keysStore = xmlSecKeyStoreCreate(files_keys_store_get_klass());
        if(keysStore == NULL) {
    	fprintf(stderr, "Error: failed to create keys store.\n");
    	return(NULL);
        }

        /* create keys manager */
        mngr = xmlSecKeysMngrCreate();
        if(mngr == NULL) {
    	fprintf(stderr, "Error: failed to create keys manager.\n");
    	xmlSecKeyStoreDestroy(keysStore);
    	return(NULL);
        }

        /* add store to keys manager, from now on keys manager destroys the store if needed */
        if(xmlSecKeysMngrAdoptKeysStore(mngr, keysStore) < 0) {
    	fprintf(stderr, "Error: failed to add keys store to keys manager.\n");
    	xmlSecKeyStoreDestroy(keysStore);
    	xmlSecKeysMngrDestroy(mngr);
    	return(NULL);
        }

        /* initialize crypto library specific data in keys manager */
        if(xmlSecCryptoKeysMngrInit(mngr) < 0) {
    	fprintf(stderr, "Error: failed to initialize crypto data in keys manager.\n");
    	xmlSecKeysMngrDestroy(mngr);
    	return(NULL);
        }

        /* set the get key callback */
        mngr->getKey = xmlSecKeysMngrGetKey;
        return(mngr);
    }

    /****************************************************************************
     *
     * Files Keys Store: we assume that key's name (content of the
     * <dsig:KeyName/> element is a name of the file with a key.
     * Attention: this probably not a good solution for high traffic systems.
     *
     ***************************************************************************/
    static xmlSecKeyPtr		files_keys_store_find_key	(xmlSecKeyStorePtr store,
    								 const xmlChar* name,
    								 xmlSecKeyInfoCtxPtr keyInfoCtx);
    static xmlSecKeyStoreKlass files_keys_store_klass = {
        sizeof(xmlSecKeyStoreKlass),
        sizeof(xmlSecKeyStore),
        BAD_CAST "files-based-keys-store",	/* const xmlChar* name; */
        NULL,				/* xmlSecKeyStoreInitializeMethod initialize; */
        NULL,				/* xmlSecKeyStoreFinalizeMethod finalize; */
        files_keys_store_find_key,		/* xmlSecKeyStoreFindKeyMethod findKey; */

        /* reserved for the future */
        NULL,				/* void* reserved0; */
        NULL,				/* void* reserved1; */
    };

    /**
     * files_keys_store_get_klass:
     *
     * The files based keys store klass: we assume that key name is the
     * key file name,
     *
     * Returns files based keys store klass.
     */
    xmlSecKeyStoreId
    files_keys_store_get_klass(void) {
        return(&files_keys_store_klass);
    }

    /**
     * files_keys_store_find_key:
     * @store:		the pointer to default keys store.
     * @name:		the desired key name.
     * @keyInfoCtx:		the pointer to <dsig:KeyInfo/> node processing context.
     *
     * Lookups key in the @store.
     *
     * Returns pointer to key or NULL if key not found or an error occurs.
     */
    static xmlSecKeyPtr
    files_keys_store_find_key(xmlSecKeyStorePtr store, const xmlChar* name, xmlSecKeyInfoCtxPtr keyInfoCtx) {
        xmlSecKeyPtr key;
        const xmlChar* p;

        assert(store);
        assert(keyInfoCtx);

        /* it's possible to do not have the key name or desired key type
         * but we could do nothing in this case */
        if((name == NULL) || (keyInfoCtx->keyReq.keyId == xmlSecKeyDataIdUnknown)){
    	return(NULL);
        }

        /* we don't want to open files in a folder other than "current";
         * to prevent it limit the characters in the key name to alpha/digit,
         * '.', '-' or '_'.
         */
        for(p = name; (*p) != '\0'; ++p) {
    	if(!isalnum((*p)) && ((*p) != '.') && ((*p) != '-') && ((*p) != '_')) {
    	    return(NULL);
    	}
        }

        if((keyInfoCtx->keyReq.keyId == xmlSecKeyDataDsaId) || (keyInfoCtx->keyReq.keyId == xmlSecKeyDataRsaId)) {
    	/* load key from a pem file, if key is not found then it's an error (is it?) */
    	key = xmlSecCryptoAppKeyLoad(name, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
    	if(key == NULL) {
        	    fprintf(stderr,"Error: failed to load pem key from \"%s\"\n", name);
    	    return(NULL);
    	}
        } else {
    	/* otherwise it's a binary key, if key is not found then it's an error (is it?) */
    	key = xmlSecKeyReadBinaryFile(keyInfoCtx->keyReq.keyId, name);
    	if(key == NULL) {
        	    fprintf(stderr,"Error: failed to load key from binary file \"%s\"\n", name);
    	    return(NULL);
    	}
        }

        /* set key name */
        if(xmlSecKeySetName(key, name) < 0) {
            fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", name);
            xmlSecKeyDestroy(key);
            return(NULL);
        }

        return(key);
    }
Full program listing
<<< Previous Page | Home | Up | Next Page >>>
Using keys manager for verification/decryption. | Using X509 Certificates.
Aleksey Sanin