Linux安全体系的OMA数字版权保护(DRM)的实现 - ShangShuWu1_第1页
Linux安全体系的OMA数字版权保护(DRM)的实现 - ShangShuWu1_第2页
Linux安全体系的OMA数字版权保护(DRM)的实现 - ShangShuWu1_第3页
Linux安全体系的OMA数字版权保护(DRM)的实现 - ShangShuWu1_第4页
Linux安全体系的OMA数字版权保护(DRM)的实现 - ShangShuWu1_第5页
已阅读5页,还剩91页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

\o"Linux安全体系的OMA数字版权保护(DRM)的实现"\o"用户:Njlts"\o"Special:用户贡献/Njlts"\o"Special:用户贡献/42"Linux安全体系的OMA数字版权保护(DRM)的实现\o"查看页面内容[c]"页面\o"关于页面正文的讨论[t]"讨论更多文章模板注释Wiki可信性\o"此页面的早前修订版本[h]"历史出自ShangShuWu未检查跳转到:<<str<<′\n′;}return0;}

下面程序执行的结果列出如下:Exceptionraised:Memoryallocationfailure!程序可以有多个try、throw和catch语句,与throw参数相匹配的catch语句才能运行,如果没有与匹配的catch语句,则运行缺省(2)命名空间缺省下,C++使用单一的全局变量命名空间,如果用户定义的一个全局变量名与源代码不可见的库的全局变量名发生重名冲突,程序将可能发生不可预知的错误。为了克服这个问题,C++可以采用关键字namespace指定程序的命名空间,在不同命名空间的重名全局变量相互不影响,但程序使用全局变量名时必须指定全局变量名的命名空间。指定命名空间的方法有两种,一种是在程序文件的前面指定命名空间,如:usingnamespacestd指定了本文件使用标准C++的命名空间。另一种是在全局变量名前加上命名空间,这样,不管全局变量放在哪个程序文件中都可以识别到命名空间。如:全局变量std::test,表示test是命名空间std的全局变量。定义命名空间的样例如下:namespacemyspace{ stringglobal_var="test"; }

上面的语句定义了myspace命名空间,定义了myspace命名空间的全局变量global_var。程序文件在文件头部可以如下指定命名空间:#include<iostream>#include<string>usingnamespacemyspace;

文件头部指定命名空间后,这个文件使用的所有全局变量global_var都属于myspace命名空间。如果不在文件头部用usingnamespacemyspace指定命名空间,还可以在任何文件中使用myspace::global_var表示这个全局变量属于myspace命名空间。(3)类工厂类工厂是用于创建类的实例的类,给共享库中定义的类提供对外统一的接口,这样,只要类工厂不变,实现功能的类可以变化,编译共享库,而应用程序不需要再编译就可以使用。类工厂的常用定义方法如下:classClassFactory{publicstaticProductCreateProductA(){returnnewProductA();}

publicstaticProductCreateProductB(){retunnewProductB();}}

下面以OpenIPMP软件包中的XMLFactory类工厂说明它的定义及使用方法。类工厂需要向外输出类的符号变量名,它通过库的输出符号变量定义来定义这些输出的类名,XMLFactory类工厂的输出的符号变量定义如下(在src/DRMPlugin/XMLFactory/XMLFactory.h中):#ifdefined(WIN32)#ifdefinedXMLFACTORY_EXPORTS#defineXMLFACTORY_EXPORT__declspec(dllexport)#else#defineXMLFACTORY_EXPORT__declspec(dllimport)#endif//XMLFACTORY_EXPORTS#elifdefined(LINUX)#defineXMLFACTORY_EXPORT#else#defineXMLFACTORY_EXPORT#endifXMLFactory类工厂的成员函数DecodeDocumentFromFile创建了IXMLDocument类的实例,其定义如下(在src/DRMPlugin/XMLFactory/XMLFactory.h中):namespaceDRMPlugin{classXMLFactory{public:staticXMLFACTORY_EXPORTIXMLDocument*DecodeDocumentFromFile(conststd::string&fname,DRMLogger&logger);}};}//namespaceDRMPlugin

XMLFactory类工厂的成员函数DecodeDocumentFromFile实现方法如下(在src/DRMPlugin/XMLFactory/XMLFactory.cpp中):IXMLDocument*XMLFactory::DecodeDocumentFromFile(conststd::string&fname,DRMLogger&logger){returnDecodeDocument(xml,logger);}IXMLDocument*XMLFactory::DecodeDocument(conststd::string&xml,DRMLogger&logger){try{returnnewXMLDocument(xml,logger);}catch(...){logger.UpdateLog("XMLFactory::DecodeDocument:unknownexception...");return0;}}

XMLFactory类工厂及具体的功能实现类都在目录src/DRMPlugin/XMLFactory下,经编译生成库libXMLFactory.la。这里使用了静态库,改变了类工厂的功能实现类,需要编译静态库和应用程序。但类工厂抽象出接口,每个类工厂完成一种类型的工作,这种抽象使程序结构清晰。类工厂在应用程序中的使用方法与一般的类一样,XMLFactory类工厂在主函数main中的调用方法如下(在src\DRMPlugin\OMADRM\Test\OMADRMTest\Test.cpp中):intmain(intargc,char*argv[]){//Encodetest.DRMPlugin::IXMLDocument*encagentxml=XMLFactory::DecodeDocumentFromFile("OMADRMEncoderInfo.xml",logger);if(encagentxml==0){std::cout<<"Encodetestfailed!"<<std::endl;return-1;}if(encagentxml->GetRootElement()->AddChildElement("License")==0){deleteencagentxml;std::cout<<"Encodetestfailed!"<<std::endl;return-1;}}(4)类模板模板是实现代码可重用性的一种方法,它将类型定义为参数,模板实现的方法对参数指定的类型都适用。类模板将模板的参数类型定义为类,例如:类模板类模板的定义列出如下:template<typenameT>class类模板SPtr{public: SPtr<T>(T*p=0){ pointer=p;if(pointer!=0)pointer->UpCount(); }}3.3多线程类工厂ThreadSyncFactory(1)线程互斥锁的类多线程共享数据时会使用线程互斥锁。为了使用方便,OpenIPMP提供了互斥锁的基类IMutex,将C库的线程互斥锁操作封装为PThreadsMutex类,基类IMutex抽象了互斥锁的行为,提供了互斥锁操作的纯虚函数,类PThreadsMutex从基类IMutex继承,重载了基类的函数,用C库的线程互斥锁的操作函数实现这些重载函数。基类IMutex的实现列出如下(在src\DRMPlugin\include\IThreadSync.h中):classThreadSyncException{//用于线程和同步对象的错误,由语句throw使用};

classIMutex{public:virtual~IMutex(){}virtualboolLock(unsignedinttimeout)=0;//等待获得互斥锁,直到timeout超时,获得互斥锁,返回truevirtualboolLock()=0;//无限期等待,直到获得互斥锁,获得互斥锁,返回truevirtualboolRelease()=0;//释放互斥锁,释放成功返回true};

类PThreadsMutex从类IMutex继承,重装了类IMutex中的虚函数。类PThreadsMutex的实现列出如下(在src\DRMPlugin\ThreadSyncFactory\PThreadsThreadSync.h中):/*!线程使用的互斥锁*/classPThreadsMutex:publicIMutex{public:/*!构造函数*/PThreadsMutex(DRMLogger&logger);//创建互斥锁,若失败,给出ThreadSyncException信号

/*!析构函数*/virtual~PThreadsMutex();virtualboolLock(unsignedinttimeout);virtualboolLock();virtualboolRelease();

private:DRMLogger&mutexLogger;pthread_mutex_tid;//线程互斥锁};

PThreadsMutex::PThreadsMutex(DRMLogger&logger):id(),mutexLogger(logger){ pthread_mutexattr_tattr; pthread_mutexattr_init(&attr);//用默认的属性来初始化attr if(pthread_mutex_init(&id,&attr)!=0){//初始化互斥锁idmutexLogger.UpdateLog("PThreadsMutex::ctor:cannotinitialize...");//记录log信息throwThreadSyncException(); }}

PThreadsMutex::~PThreadsMutex(){if(pthread_mutex_destroy(&id)<0){//销毁互斥锁idmutexLogger.UpdateLog("PThreadsMutex::dtor:cannotdestroymutex...");throwThreadSyncException();}}

boolPThreadsMutex::Lock(unsignedinttimeout){returnLock();}

boolPThreadsMutex::Lock(){if(pthread_mutex_lock(&id)<0){//加线程锁mutexLogger.UpdateLog("PThreadsMutex::Lock:cannotlock...");returnfalse;}returntrue;}

boolPThreadsMutex::Release(){if(pthread_mutex_unlock(&id)<0){//释放线程锁mutexLogger.UpdateLog("PThreadsMutex::Release:cannotrelease...");returnfalse;}returntrue;}(2)线程同步机制的类标准C库提供了多线程之间同步机制的实现函数,OpenIPMP为了使用方便,用类IEvent和其子类PThreadsEvent封装了这些函数。基类IEvent定义了用虚函数定义了同步机制所需要的操作函数,子类PThreadsEvent重载基类的函数,利用C库的函数实现线程的同步功能。类IEvent和其子类PThreadsEvent的实现分别列出如下:cclassIEvent{public:virtual~IEvent(){}

/*!等待事件通知,等待直到超时*/virtualboolWait(unsignedinttimeout)=0;/*!无限期地等待事件通知*/virtualboolWait()=0;/*!设置等待条件*/virtualboolSet()=0;/*!取消等待条件*/virtualboolUnset()=0;};

staticboolWaitForEvents(conststd::vector<IEvent*>&events){for(unsignedinti=0;i<events.size();i++){if(events[i]->Wait()==false){returnfalse;}}returntrue;}

classPThreadsEvent:publicIEvent{public:PThreadsEvent(DRMLogger&logger);//构造函数

virtual~PThreadsEvent();//析构函数virtualboolWait(unsignedinttimeout);virtualboolWait();virtualboolSet();virtualboolUnset();

private:DRMLogger&eventLogger;pthread_mutex_tmtex;pthread_cond_tcond;//线程等待的条件boolsignaled;//signaled表示条件满足,不用再等待};

PThreadsEvent::PThreadsEvent(DRMLogger&logger):mtex(),cond(),signaled(false),eventLogger(logger){pthread_mutexattr_tattr;pthread_mutexattr_init(&attr);//初始化线程互斥锁属性值为缺省值if(pthread_mutex_init(&mtex,&attr)!=0){//初始化线程互斥锁mtexeventLogger.UpdateLog("PThreadsEvent::ctor:cannotinitialize...");throwThreadSyncException();}pthread_condattr_tcattr;pthread_condattr_init(&cattr);//初始化一个条件变量属性对象cattrif(pthread_cond_init(&cond,&cattr)!=0){//初始化一个条件变量condeventLogger.UpdateLog("PThreadsEvent::ctor:cannotinitialize...");throwThreadSyncException();//发出异常消息ThreadSyncException()}}

PThreadsEvent::~PThreadsEvent(){//析构函数,销毁mtex和condif(pthread_mutex_destroy(&mtex)<0){eventLogger.UpdateLog("PThreadsEvent::ctor:cannotdestroymutex...");throwThreadSyncException();}if(pthread_cond_destroy(&cond)<0){eventLogger.UpdateLog("PThreadsEvent::ctor:cannotdestroyconditionvariable...");throwThreadSyncException();}}/*线程等待条件cond满足,直到超时*/boolPThreadsEvent::Wait(unsignedinttimeout){//timeout为ms单位if(pthread_mutex_lock(&mtex)<0){eventLogger.UpdateLog("PThreadsEvent::Wait:cannotlockmutex...");returnfalse;}if(signaled==true){//signaled表示条件满足,不用再等待return(pthread_mutex_unlock(&mtex)>=0);}structtimevalnow;structtimezonezone;structtimespectout;gettimeofday(&now,&zone);//得到当前的时间和本地的时区tout.tv_sec=now.tv_sec+(timeout/1000);tout.tv_nsec=(now.tv_usec+(timeout%1000)*1000)*1000;//转换成ns单位if(pthread_cond_timedwait(&cond,&mtex,&tout)!=0){//条件等待直到超时//eventLogger.UpdateLog("PThreadsEvent::Wait:waitfailed...");pthread_mutex_unlock(&mtex);returnfalse;}if(pthread_mutex_unlock(&mtex)<0){eventLogger.UpdateLog("PThreadsEvent::Wait:cannotunlockmutex...");returnfalse;}returntrue;}

boolPThreadsEvent::Wait(){if(pthread_mutex_lock(&mtex)<0){eventLogger.UpdateLog("PThreadsEvent::Wait:cannotlockmutex...");returnfalse;}if(signaled==true){//signaled表示条件满足,不用再等待return(pthread_mutex_unlock(&mtex)>=0);}if(pthread_cond_wait(&cond,&mtex)!=0){//线程睡眠直到特定条件cond发生//eventLogger.UpdateLog("PThreadsEvent::Wait:waitfailed...");pthread_mutex_unlock(&mtex);returnfalse;}if(pthread_mutex_unlock(&mtex)<0){eventLogger.UpdateLog("PThreadsEvent::Wait:cannotunlockmutex...");returnfalse;}returntrue;}

/*线程等待条件满足,设置signaled为true,并唤醒睡眠的线程*/boolPThreadsEvent::Set(){if(pthread_mutex_lock(&mtex)<0){eventLogger.UpdateLog("PThreadsEvent::Set:cannotlockmutex...");returnfalse;}signaled=true;//signaled表示条件满足,不用再等待if(pthread_mutex_unlock(&mtex)<0){eventLogger.UpdateLog("PThreadsEvent::Set:cannotunlockmutex...");returnfalse;}if(pthread_cond_broadcast(&cond)!=0){//条件cond满足,唤醒所有挂起的线程eventLogger.UpdateLog("PThreadsEvent::Set:broadcastfailed...");returnfalse;}returntrue;}

/*设置signaled为false,表示线程等待条件不满足,需要等待线程等待条件的满足*/boolPThreadsEvent::Unset(){if(pthread_mutex_lock(&mtex)<0){eventLogger.UpdateLog("PThreadsEvent::Unset:cannotlockmutex...");returnfalse;}signaled=false;//signaled为true时,表示条件满足,不用再等待if(pthread_mutex_unlock(&mtex)<0){eventLogger.UpdateLog("PThreadsEvent::Unset:cannotunlockmutex...");returnfalse;}returntrue;}(3)线程类OpenIPMP将标准C库中线程的创建与运行封装成类PThreadsThread,方便了程序使用创建线程。类PThreadsThread及它所继承的基类IThread列出如下:classIThread{public:virtual~IThread(){}};

classPThreadsThread:publicIThread{public:/*构造函数PThreadsThread创建线程,没有安全属性,使用缺省的堆栈属性,并立即启动线程。其参数start是线程启动的功能函数,参数par线程功能函数的参数,参数logger是用于读写log信息的类对象*/PThreadsThread(void(*start)(void*),void*par,DRMLogger&logger);virtual~PThreadsThread();

private:pthread_thandle;};

构造函数PThreadsThread创建线程,运行功能函数,其列出如下:PThreadsThread::PThreadsThread(void(*start)(void*),void*par,DRMLogger&logger):handle(){pthread_attr_ttype;if(pthread_attr_init(&type)!=0){//初始化线程属性为缺省值logger.UpdateLog("PThreadsThread::ctor:cannotinitialize...");throwThreadSyncException();}PThreadParams*pars=newPThreadParams();pars->start=start;pars->par=par;//创建线程,线程运行功能函数,运行完后,线程退出if(pthread_create(&handle,&type,PThreadRun,pars)!=0){logger.UpdateLog("PThreadsThread::ctor:cannotcreatethread...");deletepars;//销毁对象throwThreadSyncException();}}

PThreadsThread::~PThreadsThread(){//析构函数}

结构PThreadParams封闭了线程运行函数的参数,通过它可将函数PThreadRun的参数解析为一个函数和参数,其列出如下:structPThreadParams{void(*start)(void*);void*par;};

函数PThreadRun是线程运行函数,它执行具体的功能函数,执行完后,退出线程。这里使用线程运行函数嵌套执行具体的功能函数,是为了将线程处理与功能函数完全分开,功能函数不必考虑线程的处理。函数PThreadRun列出如下:staticvoid*PThreadRun(void*par){PThreadParams*str=(PThreadParams*)par;void(*tstart)(void*)=str->start;void*tpar=str->par;tstart(tpar);//运行线线程功能函数deletestr;pthread_exit(0);//功能函数运行完后退出线程return0;}线程类工厂ThreadSyncFactoryWindow和Linux平台上线程实现调用的函数是不一样的,线程类工厂ThreadSyncFactory屏蔽了这种实现的差异性,向外提供了统一的接口。互斥锁、事件及线程都抽象出了基类,然后分别用从基类继承的子类实现标准C库线程的功能,线程类工厂ThreadSyncFactory向外公开的接口函数返回类型都是基类的类型,这样,屏蔽了类的具体实现方法,统一了接口。类工厂还把它所包含的类的异常信息捕捉下来,统一在类工厂中由catch语句进行处理,这样,具体的类不必关心如何处理log信息。因此,类工厂的主要作用是向外提供统一的接口,管理具体的类实现,抽象具体的类共有的特性。具体的类完成着指定的功能。改变具体的类后,只要类工厂不变,调用类工厂的应用程序就不用改变。这较好地实现了程序的分层。类工厂ThreadSyncFactory的定义列出如下(在src\DRMPlugin\ThreadSyncFactory\ThreadSyncFactory.h中):classThreadSyncFactory{public:/*!创建线程互斥锁类对象,创建成功,返回类对象,创建失败,返回0。创建的类对象是Imutex的子类对象,返回的是基类的类型,这屏蔽了子类的差异性,统一了接口*/staticTHREADSYNCFACTORY_EXPORTIMutex*GetMutex(DRMLogger&logger);

/*!创建全局的互斥锁类对象*/staticTHREADSYNCFACTORY_EXPORTIMutex*GetGlobalMutex();

/*!创建线程的事件对象*/staticTHREADSYNCFACTORY_EXPORTIEvent*GetEvent(DRMLogger&logger);

/*!创建线程对象*/staticTHREADSYNCFACTORY_EXPORTIThread*GetThread(void(*start)(void*),void*par,DRMLogger&logger);};

类工厂ThreadSyncFactory的实现列出如下(在src\DRMPlugin\ThreadSyncFactory\ThreadSyncFactory.cpp中):IMutex*ThreadSyncFactory::GetMutex(DRMLogger&logger){try{returnnewPThreadsMutex(logger);}catch(ThreadSyncException){return0;}catch(...){//捕捉所有语句throw给出的异常信息logger.UpdateLog("ThreadSyncFactory::GetMutex:unknownexception...");return0;}}

IMutex*ThreadSyncFactory::GetGlobalMutex(){try{returnnewPThreadsGlobalMutex();}catch(ThreadSyncException){return0;}catch(...){return0;}}

IEvent*ThreadSyncFactory::GetEvent(DRMLogger&logger){try{returnnewPThreadsEvent(logger);//创建线程事件对象}catch(ThreadSyncException){return0;}catch(...){//捕捉所有语句throw给出的异常信息logger.UpdateLog("ThreadSyncFactory::GetEvent:unknownexception...");return0;}}

IThread*ThreadSyncFactory::GetThread(void(*start)(void*),void*par,DRMLogger&logger){try{returnnewPThreadsThread(start,par,logger);//创建线程}catch(ThreadSyncException){return0;}catch(...){//捕捉所有语句throw给出的异常信息logger.UpdateLog("ThreadSyncFactory::GetThread:unknownexception...");return0;}}

4用类工厂封装PKI4.1XML类工厂XMLFactoryOMADRM在使用ROAP(RightObjectAcquisitionProtocol)申请权利对象以及使用OCSP(OnlineCertificateStatusProtocol)进行证书状态验证时,协议消息使用XML(ExtensibleMarkupLanguage)格式进行描述。XML的功能是描述内容的数据形式和结构,被广泛用于与网页浏览器相关的协议的数据传输和交互。DOM(DocumentObjectModel,文档对象模型)是W3C组织制定的规范,用于标准HTML和XML文档的编程接口,是详细描述HTML/XML文件对象规则的API,将网页和脚本或编程语言连接了起来。它定义了HTML或XML档的逻辑结构以及访问操作这些文档的方法。它将文档的逻辑结构定义由节点组成的树形结构,程序通过遍历树的节点,可以增、删、改节点及内容。DOM规范只定义了操作HTML/XML文档的接口,而没有指定实现这些接口的方法。Xerces-C库是ApacheSoftwareFoundation提供的C++函数库,是XML分析器,提供了读写XML文档的API函数。它符合于XML1.1规范和DOMLevel2CoreSpecification规范。OpenIPMP使用类工厂XMLFactory分别定义了基类IXMLAttribute、IXMLElement和IXMLDocument抽象出XML文档的元素属性、元素和XML文档的操作函数,使用了分别从这些基类继承的子类XMLAttribute、XMLElement和XMLDocument,封装了Xerces-C库中的类DOMParser、DOM_Document、DOM_Node、DOM_Element和DOM_Attr,完成对XML文档的具体读写操作。类工厂XMLFactory提供了对类XMLAttribute、XMLElement和XMLDocument的管理及向外的统一接口。xercesc库源代码可从/xerces-c/download.cgi下载,其API函数使用方法请参考xercesc库源代码所带的文档说明。下面仅列出XMLFactory类的实现和XMLDocument的构造函数。类工厂XMLFactory的定义列出如下(在src\DRMPlugin\XMLFactory\XMLFactory.h中):classXMLFactory{public:/*!用给定名字的根节点创建一个新的XML文档。参数name为根节点名,也是文档的名字,参数logger为记录log信息的类对象。创建成功返回新的XML文档,创建失败返回0*/staticXMLFACTORY_EXPORTIXMLDocument*CreateDocument(conststd::string&name,DRMLogger&logger);/*!从一个编码的XML字符串创建新XML文档。参数xml为编码的XML字符串*/staticXMLFACTORY_EXPORTIXMLDocument*DecodeDocument(conststd::string&xml,DRMLogger&logger);/*!从一个文件创建新XML文档*/staticXMLFACTORY_EXPORTIXMLDocument*DecodeDocumentFromFile(conststd::string&fname,DRMLogger&logger);};类工厂XMLFactory的实现列出如下(在src\DRMPlugin\XMLFactory\XMLFactory.cpp中):IXMLDocument*XMLFactory::CreateDocument(conststd::string&name,DRMLogger&logger){try{returnnewXMLDocument("<"+name+"></"+name+">",logger);}catch(...){logger.UpdateLog("XMLFactory::CreateDocument:unknownexception...");return0;}}

IXMLDocument*XMLFactory::DecodeDocument(conststd::string&xml,DRMLogger&logger){try{returnnewXMLDocument(xml,logger);}catch(...){logger.UpdateLog("XMLFactory::DecodeDocument:unknownexception...");return0;}}IXMLDocument*XMLFactory::DecodeDocumentFromFile(conststd::string&fname,DRMLogger&logger){FILE*fp=fopen(fname.data(),"rb");//打开文件if(fp==NULL){logger.UpdateLog("XMLFactory::DecodeDocumentFromFile:cannotopen"+fname+"...");return0;}structstattstat;stat(fname.data(),&tstat);char*xmlText=(char*)malloc(tstat.st_size+1);fread(xmlText,tstat.st_size,1,fp);//读取文件到缓存xmlText xmlText[tstat.st_size]='\0';fclose(fp);std::stringxml=xmlText;free(xmlText);returnDecodeDocument(xml,logger);//由xmlText字符串构建XML文档对象}类XMLDocument定义如下(在src\DRMPlugin\XMLFactory\XMLDocument.h中):classXMLDocument:publicIXMLDocument{public:/*!构造函数,参数xml为编码的XML字符串*/XMLDocument(conststd::string&xml,DRMLogger&logger);virtual~XMLDocument();

/*!得到根元素*/virtualIXMLElement*GetRootElement();

/*!编译成字符串*/virtualstd::stringEncode();

private:IXMLElement*root;DOMParser*parser;//xercesc库的类,是XML文档分析器,封装了各种解析函数DOM_Documentdoc;//xercesc库的类,代表了XML文档DRMLogger&docLogger;};类XMLDocument构造函数通过参数xml字符串构建DOM_Document对象,解析出节点树,得到根节点root,这样,通过遍历节点树,可对DOM_Document对象进行读写操作。其列出如下:XMLDocument::XMLDocument(conststd::string&xml,DRMLogger&logger):root(0),parser(0),doc(),docLogger(logger){try{MemBufInputSourcebyteInput((constXMLByte*const)xml.data(),(constunsignedint)xml.size(),(char*const)"xmldocument");parser=newDOMParser();parser->parse(byteInput);doc=parser->getDocument();DOM_Elementelem=doc.getDocumentElement();root=newXMLElement(elem,docLogger);//根节点元素}catch(...){docLogger.UpdateLog("XMLDocument::ctor:xerceserror...");if(parser!=0)deleteparser;throwXMLException();}}4.2公钥加密工厂PublicCryptoFactory类工厂PublicCryptoFactory是管理PKI公钥加密的各种算法的管理器,它屏蔽了算法的实现细节,对应用程序提供了统一的接口。例如:对于Hash算法,OpenIPMP在src\DRMPlugin\include\IPublicCrypto.h文件中定义了基类IHasher,其他具体的Hash算法对应的类从它继承,如:SHA1OpenSSLHasher。不管具体的Hash算法类如何实现,类工厂PublicCryptoFactory的函数可以返回IHasher类型指针指向具体的Hash算法类对象。类工厂PublicCryptoFactory提供了Hash算法、签名、证书验证等与公钥相关的算法类,其定义列出如下(在src\DRMPlugin\PublicCryptoFactory\PublicCryptoFactory.h中):classPublicCryptoFactory{public:/*!创建MD5Hash算法的类对象*/staticPUBLICCRYPTOFACTORY_EXPORTIHasher*GetMD5Hasher(DRMLogger&logger);/*!创建SHA1Hash算法的类对象*/staticPUBLICCRYPTOFACTORY_EXPORTIHasher*GetSHA1Hasher(DRMLogger&logger);/*!创建类对象,用于从密钥数据中分析公钥解密器,参数data为输入的数据,datalen为数据长度*/staticPUBLICCRYPTOFACTORY_EXPORTIPublicDecryptor*ParsePublicDecryptorFromKeyData(ByteT*data,unsignedintdatalen,DRMLogger&logger);/*!创建类对象,用于从密钥数据中分析公钥签名*/staticPUBLICCRYPTOFACTORY_EXPORTIPublicSigner*ParsePublicSignerFromKeyData(ByteT*data,unsignedintdatalen,DRMLogger&logger);/*!创建类对象,用于从密钥数据中分析公钥解密器和签名*/staticPUBLICCRYPTOFACTORY_EXPORTIPublicDecryptorSigner*ParsePublicDecryptorSignerFromKeyData(ByteT*data,unsignedintdatalen,DRMLogger&logger);/*!创建类对象,从密钥文件中分析公钥解密器,参数fname为文件路径名*/staticPUBLICCRYPTOFACTORY_EXPORTIPublicDecryptor*ParsePublicDecryptorFromKeyFile(conststd::string&fname,DRMLogger&logger);/*!创建类对象,用于从密钥文件中分析签名*/staticPUBLICCRYPTOFACTORY_EXPORTIPublicSigner*ParsePublicSignerFromKeyFile(conststd::string&fname,DRMLogger&logger);/*!创建类对象,用于从密钥文件中分析公钥解密器和签名*/staticPUBLICCRYPTOFACTORY_EXPORTIPublicDecryptorSigner*ParsePublicDecryptorSignerFromKeyFile(conststd::string&fname,DRMLogger&logger);/*!创建类对象,用于证书验证*/staticPUBLICCRYPTOFACTORY_EXPORTICertVerifier*GetCertificateVerifier(DRMLogger&logger);/*!创建类对象,用于从证书数据中分析公钥加密器证书*/staticPUBLICCRYPTOFACTORY_EXPORTIPublicEncryptorCertificate*ParsePublicEncryptorCertificateFromData(ByteT*data,unsignedintdatalen,DRMLogger&logger);/*!创建类对象,用于从证书文件中分析公钥加密器证书*/staticPUBLICCRYPTOFACTORY_EXPORTIPublicEncryptorCertificate*ParsePublicEncryptorCertificateFromFile(conststd::string&fname,DRMLogger&logger);/*!创建类对象,用于从证书数据中分析公钥验证器证书*/staticPUBLICCRYPTOFACTORY_EXPORTIPublicVerifierCertificate*ParsePublicVerifierCertificateFromData(ByteT*data,unsignedintdatalen,DRMLogger&logger);/*!创建类对象,用于从证书文件中分析公钥验证器证书*/staticPUBLICCRYPTOFACTORY_EXPORTIPublicVerifierCertificate*ParsePublicVerifierCertificateFromFile(conststd::string&fname,DRMLogger&logger);/*!创建类对象,用于从证书数据中分析公钥加密器和验证器证书*/staticPUBLICCRYPTOFACTORY_EXPORTIPublicEncryptorVerifierCertificate*ParsePublicEncryptorVerifierCertificateFromData(ByteT*data,unsignedintdatalen,DRMLogger&logger);/*!创建类对象,用于从证书文件中分析公钥加密器和验证器证书*/staticPUBLICCRYPTOFACTORY_EXPORTIPublicEncryptorVerifierCertificate*ParsePublicEncryptorVerifierCertificateFromFile(conststd::string&fname,DRMLogger&logger);};OpenIPMP采用openssl库作为它的密码算法库,OpenIPMP用类封装了各种公钥算法,它们封装方法类似,下面仅列出MD5hash算法的类封装实现。类工厂PublicCryptoFactory的函数GetMD5Hasher创建一个hash算法类实例返回。该类实例的hash计算函数Hashe调用openssl的摘要计算接口函数。函数GetMD5Hasher列出如下(在src\DRMPlugin\PublicCryptoFactory\PublicCryptoFactory.cpp中):IHasher*PublicCryptoFactory::GetMD5Hasher(DRMLogger&logger){returnnewMD5OpenSSLHasher();}类MD5OpenSSLHasher封装了hash算法,用于计算数据序列的摘要,其定义列出如下(在src\DRMPlugin\PublicCryptoFactory\OpenSSLPublicCrypto.h中):classMD5OpenSSLHasher:publicIHasher{public:virtual~MD5OpenSSLHasher(){}

/*计算摘要,参数data为需要hash计算的字节序列,hash为计算结果的字节序列*/virtualboolHash(constByteSeq&data,ByteSeq&hash);};MD5hash算法函数Hash调用openssl库的EVP加密算法接口函数EVP_Digest来实现摘要计算,计算的结果封装成类ByteSeq实例,通过函数Hash的参数hash返回。函数Hash列出如下(在src\DRMPlugin\PublicCryptoFactory\OpenSSLPublicCrypto.cpp中):boolMD5OpenSSLHasher::Hash(constByteSeq&data,ByteSeq&hash){/*ByteT定义为unsignedchar类型*/ByteT*hhash=(ByteT*)malloc(EVP_md5()->md_size);if(hhash==NULL){returnfalse;}intret=1;unsignedinthashlen=0;/*调用openssl库的接口函数EVP_Digest计算摘要*//*(void*)data.GetFirst()得到字节数组的第一个字节地址,即得到字节串的起始地址*/ret=EVP_Digest((void*)data.GetFirst(),(unsignedint)data.GetLength(),hhash,&hashlen,EVP_md5(),/*ENGINE*impl*/0);if(ret!=1){free(hhash);returnfalse;}hash=ByteSeq(hhash,hashlen);//创建字节序列类ByteSeq实例free(hhash);

returntrue;}4.3Base64类工厂Base64FactoryBase64类工厂Base64Factory封装了Base64编码和解码算法,OpenIPMP自己实现了Base64的编码/解码算法。类工厂Base64Factory定义列出如下(在src\DRMPlugin\Base64Factory\Base64Factory.h中):classBase64Factory{public:/*Base64编码算法,参数data为输入的字节流,参数b64为编码后的字节流*/staticboolEncode(constByteSeq&data,Base64StringT&b64);

/*Base64解码算法,参数b64为输入的Base64字节流,参数data为输出的解码字节流*/staticboolDecode(constBase64StringT&b64,ByteSeq&data);};4.4密码算法类工厂CipherFactory密码算法类工厂CipherFactory管理随机器产生器和各种对称密码算法,封装了Crypto++库的密码算法函数。其列出如下(在src\DRMPlugin\CipherFactory\CipherFactory.h中):classCipherFactory{public:/*产生用于密码短语的随机数,存放随机数的缓冲区由这个函数分配*/staticboolRndGenerate(UInt32Tpassphrase,ByteT**k,UInt32Tklen);

/*产生随机数,存放随机数的缓冲区由这个函数分配*/staticboolRndGenerate(ByteT**k,UInt32Tklen);

/*得到新创建的blowfish加密器对象*/staticBlowfishEncryptor*GetBlowfishEncryptor(ByteT*k,UInt32TkSize,DRMLogger&logger);

/*得到新创建的AES128CBC加密器对象*/staticAES128CBCEncryptor*GetAES128CBCEncryptor(ByteT*k,UInt32TkSize,ByteT*iv,DRMLogger&logger);

/*得到新创建的AES128CTR加密器对象*/staticAES128CTREncryptor*GetAES128CTREncryptor(ByteT*k,UInt32TkSize,ByteT*iv,DRMLogger&logger);

/*得到新创建的AES128ICM加密器对象*/staticAES128ICMEncryptor*GetAES128ICMEncryptor(ByteT*k,UInt32TkSize,DRMLogger&logger);

/*得到新创建的blowfish解密器对象*/staticBlowfishDecryptor*GetBlowfishDecryptor(ByteT*k,UInt32TkSize,DRMLogger&logger);

/*得到新创建的AES128CBC解密器对象*/staticAES128CBCDecryptor*GetAES128CBCDecryptor(ByteT*k,UInt32TkSize,DRMLogger&logger);

/*得到新创建的AES128CTR解密器对象*/staticAES128CTRDecryptor*GetAES128CTRDecryptor(ByteT*k,UInt32TkSize,DRMLogger&logger);

/*得到新创建的AES128ICM解密器对象*/staticAES128ICMDecryptor*GetAES128ICMDecryptor(ByteT*k,UInt32TkSize,DRMLogger&logger);};密码算法类工厂CipherFactory的密码算法函数封装了Crypto++库的函数,下面仅说明AES算法的实现。Crypto++是一个用标准C++编写的密码类库开放源代码软件,实现了各种公钥算法、对称加密算法、数字签名算法、信息摘要算法以及其相关的其它密码算法等。AES对称密码算法包括ECB、CBC、CFB、OFB和CTR几种工作模式,AES对称密码算法采用标准的Rijndael算法,CBC模式AES加密算法用类CPPAES128CBCEncryptor进行封装。类CPPAES128CBCEncryptor使用了Crypto++库的Rijndael算法加密类CBC_Mode<CryptoPP::Rijndael>::Encryption实现加密算法,其列出如下(在src\DRMPlugin\CipherFactory\BlockCipher.h中):classCPPAES128CBCEncryptor:publicAES128CBCEncryptor{public:/*构造函数,参数k为密钥,参数kSize为密钥大小,参数i为初始化向量,参数logger为消息日志,如果失败,会抛出异常CipherException*/CPPAES128CBCEncryptor(ByteT*k,UInt32TkSize,ByteT*i,DRMLogger&logger);

virtual~CPPAES128CBCEncryptor();

/*加密字符串,参数in为输入的字符串,参数inSize为输入字符串大小,参数out为加密后输出的字符串,参数outLen为加密字符串的大小,加密成功时,函数返回true,否则返回false*/ virtualboolEncrypt(ByteT*in,UInt32TinSize,ByteT**out,UInt32T*outLen);

/*得到用于下一个包加密的初始化向量IV。参数par为输出的初始化向量,参数parLen为初始化向量长度*/ virtualboolNextIV(ByteT**par,UInt32T*parLen);

private: ByteT*key;//密钥UInt32TkeySize;//密钥大小 ByteT*iv;//IV向量//CBC模式,标准AES的Rijndael算法,CryptoPP为命名空间CryptoPP::CBC_Mode<CryptoPP::Rijndael>::Encryptionenc; /*这里用std::string,因为不能确信需要多大缓冲区用于填充*/ std::stringencData;/*流过滤器StreamTransformationFilter对工作模式CBC进行包装,需要时流过滤器将缓冲区数据阻塞*/ CryptoPP::StreamTransformationFilterfilter;};构造函数CPPAES128CBCEncryptor创建CBC模式Rijndael算法加密对象enc,创建流过滤器对象,设置加密数据输出变量encData,设置密钥和IV向量。其列出如下(src\DRMPlugin\CipherFactory\BlockCipher.cpp):CPPAES128CBCEncryptor::CPPAES128CBCEncryptor(ByteT*k,UInt32TkSize,ByteT*i,DRMLogger&logger):key(k),keySize(kSize),iv(i),enc(),encData(),filter(enc,newCryptoPP::StringSink(encData),//将encData将加密数据输出#ifdefined(WIN32)CryptoPP::StreamTransformationFilter::BlockPaddingScheme::PKCS_PADDING){#elifdefined(LINUX)CryptoPP::StreamTransformationFilter::PKCS_PADDING){#elseCryptoPP::StreamTransformationFilter::PKCS_PADDING){#endif

if(kSize!=16){if(key!=0)free(key);key=0;if(iv!=0)free(iv);iv=0;logger.UpdateLog("CPPAES128CBCEncryptor::ctor:wrongkeysize.");throwCipherException();} enc.SetKeyWithIV((unsignedchar*)key,keySize,(unsignedchar*)iv);//设置密钥和IV向量}函数Encrypt对字符串进行加密计算,并返回加密的字符串。其列出如下:boolCPPAES128CBCEncryptor::Encrypt(ByteT*in,UInt32TinSize,ByteT**out,UInt32T*outLen){ encData=""; filter.Put((unsignedchar*)in,inSize);//对输入进行处理,然后调用加密对象对字符串进行加密 filter.MessageEnd();//输入的结束性标志 enc.Resynchronize((unsignedchar*)iv); enc.GetNextIV((unsignedchar*)iv);//得到下一个IV,用于计算下一个包 enc.SetKeyWithIV((unsignedchar*)key,keySize,(unsignedchar*)iv);//设置密钥的IV

*out=(ByteT*)malloc(encData.size());if(*out==NULL){returnfalse;}memcpy(*out,encData.c_str(),encData.size());//拷贝加密的字符串*outLen=encData.size();returntrue;}5ROAP消息处理5.1权利对象RO的类描述OMADRM的域RO可以被分开发送,权利发布者对请求的ROAP回应消息含有权利描述,域的权利描述样例列出如下:<roap:protectedROxmlns:roap="urn:oma:bac:dldrm:roap-1.0"//xmlns:roap表示定义的命名空间roapxmlns:ds="/2000/09/xmldsig#"//表示ds所在命名空间为文件xmldsigxmlns:xenc="/2001/04/xmlenc#"xmlns:o-ex="/1.1/ODRL-EX"xmlns:o-dd="/1.1/ODRL-DD"xmlns:xsi="/2001/XMLSchema-instance"><rightso-ex:id="REL1"><o-ex:context><o-dd:version>2.0</o-dd:version>//类ODDVersion<o-dd:uid>RightsObjectID</o-dd:uid>//类RightsODDUID</o-ex:context><o-ex:agreement><o-ex:asset><o-ex:context><o

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论