domainkey.h

来自「MiniSip Client with DomainKeys Authentic」· C头文件 代码 · 共 307 行

H
307
字号
#ifndef DOMAINKEY_H_#define DOMAINKEY_H_#include <libmcrypto/config.h>#include <openssl/pem.h>#include <openssl/evp.h>#include <libmutil/Exception.h>#include <time.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <netinet/in.h>#include <arpa/nameser.h>#include <resolv.h>#include <libmcrypto/OpenSSLUtil.h>#include <iostream>#include <fstream>#include <string>#include <list>#include <stddef.h>#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <dirent.h>/** * This class represents a DomainKey (RSA Public Key). * According to the standard (RFC XXXX) the public keys are stored as a txt-record on a dns server. Once the key is fetched, it will be cached locally. * The implementation of this class referes to the openssl library. For querying the dns server, libresolv is used, too. */class LIBMCRYPTO_API DomainKey{	public:		/**		 * The constructor creates a new domain key.		 * In this case, the local cache is checked for the corresponding key. If the key does not exist, the dns server is queried for the key.		 * @param sipuri A String representing the SIP-URI of the desired domain key. i.e. foo@bar.com		 */		DomainKey(std::string sipuri);					/**		 * Destructor for the domain key.		 */		~DomainKey();				/**		 * This method verifies the signature of a data block.		 * The verification process is implemented with the openssl functions.		 * @param data byte_t array with the data		 * @param dataLength The length of the data		 * @param signature byte_t array with the signature		 * @param signatureLength The length of the signatur		 * @return boolean value which indicates if the verification is ok or not		 */		bool verify(byte_t* data, unsigned int dataLength, byte_t* signature, unsigned int signatureLength);		/**		 * Static method to delete a specific cache entry in the cache folder		 * @param sipuri A String representing the SIP-URI of the domainkey to be deleted.		 */		static void deleteCacheEntry(std::string sipuri);				/**		 * This static method deletes all cached domainkeys in the cache directory.		 */		static void deleteCacheEntries();		/**		 * All cache entries will be listed by their SIP-URI 		 * @return List of strings representing the SIP-URIs of the cached domainkeys.		 */		static std::list<std::string> listCacheEntries();		/**		 * Path to the cache directory		 */		static const std::string CACHE_DIR;			private:		/**		 * openssl public key.		 */		EVP_PKEY* publicKey;		/**		 * This method checks if the desired domainkey is already chached.		 * The filename is derived from the SIP-URI: foo@bar.com --> foo._domainkey.bar.com --> foo._domainkey.bar.com.pem		 * @param filename Filename (whole path)		 * @return boolean value if the cache entry exists		 */		bool checkPublicKeyFile(std::string filename);		/**		 * Loads the cached domainkey (public key) from a local file.		 * The filename is derived from the SIP-URI: foo@bar.com --> foo._domainkey.bar.com --> foo._domainkey.bar.com.pem 		 * @param filename Filename (whole path)		 * @return boolean value if loading was successful		 */		bool loadPublicKeyFromFile(std::string filename);		/**		 * Saves the public key into the local cache.		 * The filename is derived from the SIP-URI: foo@bar.com --> foo._domainkey.bar.com --> foo._domainkey.bar.com.pem		 * @param filename Filename (whole path)		 */		void savePublicKeyFile(std::string filename);		/**		 * This method queries the corresponding dns-server to get the public key.		 * For querying the dns-server res_query() from libresolv is used.		 * The answer of the dns-server has the following format according to RFC 1035:		 * 		 *     +---------------------+		 *     |        Header       |		 *     +---------------------+		 *     |       Question      | the question for the name server		 *     +---------------------+		 *     |        Answer       | RRs answering the question		 *     +---------------------+		 *     |      Authority      | RRs pointing toward an authority		 *     +---------------------+		 *     |      Additional     | RRs holding additional information		 *     +---------------------+		 * 		 * The header contains the following fields:		 * 		 *                                     1  1  1  1  1  1		 *       0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |                      ID                       |		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |                    QDCOUNT                    |		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |                    ANCOUNT                    |		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |                    NSCOUNT                    |		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |                    ARCOUNT                    |		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 * 		 * 		 * Question section format:		 * 		 *                                     1  1  1  1  1  1		 *       0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |                                               |		 *     /                     QNAME                     /		 *     /                                               /		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |                     QTYPE                     |		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |                     QCLASS                    |		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 * 		 * where:		 * 		 * QNAME           a domain name represented as a sequence of labels, where		 *                 each label consists of a length octet followed by that		 *                 number of octets.  The domain name terminates with the		 *                 zero length octet for the null label of the root.  Note		 *                 that this field may be an odd number of octets; no		 *                 padding is used.		 * 		 * QTYPE           a two octet code which specifies the type of the query.		 *                 The values for this field include all codes valid for a		 *                 TYPE field, together with some more general codes which		 *                 can match more than one type of RR.		 * 		 * QCLASS          a two octet code that specifies the class of the query.		 *                 For example, the QCLASS field is IN for the Internet.		 * 		 * 		 * Resource record format:		 * 		 *                                     1  1  1  1  1  1		 *       0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |                                               |		 *     /                                               /		 *     /                      NAME                     /		 *     |                                               |		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |                      TYPE                     |		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |                     CLASS                     |		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |                      TTL                      |		 *     |                                               |		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 *     |                   RDLENGTH                    |		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|		 *     /                     RDATA                     /		 *     /                                               /		 *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+		 * 		 * where:		 * 		 * NAME            a domain name to which this resource record pertains.		 * 		 * TYPE            two octets containing one of the RR type codes.  This		 *                 field specifies the meaning of the data in the RDATA		 *                 field.		 * 		 * CLASS           two octets which specify the class of the data in the		 *                 RDATA field.		 * 		 * TTL             a 32 bit unsigned integer that specifies the time		 *                 interval (in seconds) that the resource record may be		 *                 cached before it should be discarded.  Zero values are		 *                 interpreted to mean that the RR can only be used for the		 *                 transaction in progress, and should not be cached.		 * 		 * RDLENGTH        an unsigned 16 bit integer that specifies the length in		 *                 octets of the RDATA field.		 * 		 * RDATA           a variable length string of octets that describes the		 *                 resource.  The format of this information varies		 *                 according to the TYPE and CLASS of the resource record.		 *                 For example, the if the TYPE is A and the CLASS is IN,		 *                 the RDATA field is a 4 octet ARPA Internet address.		 * 		 * 		 * @param sipuri A String representing the SIP-URI 		 */		void fetchPublicKey(std::string sipuri);		/**		 * Converts the SIP-URI to the DNS-URL.		 * The DNS-URL is derived from the SIP-URI: foo@bar.com --> foo._domainkey.bar.com 		 * @param sipuri A String representing the SIP-URI 		 * @return String representing the DNS-URL		 */		static std::string getDNSURL(std::string sipuri);				/**		 * Converts the DNS-URL back to the SIP-URI		 * The SIP-URI is derived from the DNS-URL: foo._domainkey.bar.com --> foo@bar.com		 * @param dnsurl A String representing the DNS-URL		 * @return String representing the SIP-URI		 */ 		static std::string getSipURI(std::string dnsurl);				/**		 * This method extracts the qname of the question section of the dns answer.		 * 		 *                                   1  1  1  1  1  1	     *     0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5	     *   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+	     *   |                                               |	     *   /                     QNAME                     /	     *   /                                               /	     *   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+	     *   |                     QTYPE                     |	     *   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+	     *   |                     QCLASS                    |	     *   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+	     *   	     *   where:	     *   	     *   QNAME           a domain name represented as a sequence of labels, where	     *                   each label consists of a length octet followed by that	     *                   number of octets.  The domain name terminates with the	     *                   zero length octet for the null label of the root.  Note	     *                   that this field may be an odd number of octets; no	     *                   padding is used.	     * 		 * @param answer char array representing the dns answer		 * @param index index of the beginning of qname		 * @param qname_string Is a string in which the qname is stored		 * @return The length of the qname (bytes used in the answer)		 */		int extractLabel(unsigned char * answer, int index, std::string& qname_string);				/**		 * Extracts the public key from the answer txt record.		 * The public key is being extracted from the txt record. This extracted string is going the be formated as follows:		 * - "-----BEGIN PUBLIC KEY-----\n" is inserted before the key		 * - "\n-----END PUBLIC KEY-----" is inserted after the key		 * - after every 64 byte a new line is inserted		 * 		 * @param answer_txt String representing the txt record.		 * @return public key in openssl format		 */		EVP_PKEY* extractPublicKey(std::string answer_txt);		/**		 * This method checks if the cache directory exists for storing the files.		 * If the directory does not exist, it will be created		 */		void checkCacheDirectory();};class LIBMCRYPTO_API DomainKeyException : public Exception{	public:		/**		 * DomainKey exception representing an exception withing the domain key.		 * @param desc Description of the exception		 */		DomainKeyException( const char *desc):Exception(desc){};};#endif /*DOMAINKEY_H_*/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?