通信认证

技能与DuerOS通信过程中,双方都需要对接收到的请求信息进行认证,避免接收到恶意攻击者发来的请求,保证通信内容安全。

技能认证

技能认证要求

当DuerOS发送请求给技能时,技能需要回复DuerOS的请求。此时技能需要满足以下要求。

验证签名过程

当DuerOS向技能发送请求时,技能需要对发来的请求进行验证,验证过程如下。

  1. 从http head的signaturecerturl地址里面下载权威签名证书,然后从签名证书中获取公钥。地址signaturecerturl的格式为协议+域名+url地址+文件名,其中协议域名url地址是固定不变的。如https://duer.bdstatic.com/saiya/flow/dueros-api.baidu.com.cer.txt是一个signaturecerturl地址,可以从该地址下载一个PEM-encoded X.509的权威签名证书。在获取签名证书的过程中需要验证如下几项。
    • 协议必须是https
    • 域名必须是duer.bdstatic.com,大小写严格匹配。
    • url必须以saiya/flow/开始,大小写严格匹配。
    • 端口必须是443。
    • 权威签名证书中的Subject Alternative Names(SANs)的值必须是dueros-api.baidu.com
  2. 从http head中获取signature信息,并用base64解码signature得到str1。
  3. 通过公钥和str1解密得到sign1。如果解密成功,继续验证。如果解密失败则拒绝请求。
  4. 使用sha1计算消息body的内容得到sign2,并与sign1进行比较,如果一致则继续验证,如果不一致,则拒绝请求。
  5. 比较request请求消息中的timestamp字段与系统当前的时间,如果两者差值小于180秒,则认为当前请求合法,对请求进行处理。如果两者差值大于等于180秒,则拒绝请求。

下图展示了DuerOS生成签名过程和技能验证签名的过程。验证过程中的2-4步可以使用rsa_verify函数代替。

文本卡片的示例

DuerOS认证

DuerOS认证条件

技能主动请求DuerOS时,DuerOS和技能需要满足如下条件。

  • 技能需要使用RSA方法生成公钥和私钥,并将公钥上传到DBP平台。
  • 技能需要按如下步骤生成签名,并将签名发送给DuerOS。
    • 首先,对消息的body进行base64位加密得到str1。
    • 其次,获取技能的botId和消息的时间戳timestamp。
    • 再次,将str1、botId、timestamp、debug(或online)四个字符串按顺序连接成字符串str2。技能未上线时,使用字符串debug,技能上线后使用字符串online。
    • 最后,将私钥和str2进行加密生成签名signature。
  • DuerOS需要验证技能发送的请求,当恶意攻击者篡改技能发送的请求内容,DuerOS能够识别,不被欺骗。

DuerOS验证签名过程

当DuerOS收到技能发送的请求时,需要对技能发来的请求进行验证,验证步骤如下。

  1. 从http head中获取signature,并进行base64位解密获得str1。
  2. 从DBP平台上获取技能的公钥,并将公钥与str1通过解密获得sign1,如果解密失败则拒绝请求。
  3. 将body、botId、timestamp三个字符串按顺序连接成str2,并对str2生成摘要sign2,比较sign1与sign2是否相同,如果不同则决绝请求,如果相同,则继续验证。
  4. 比较请求消息中的timestamp字段与系统当前时间,如果两者差值小于180秒,则认为请求合法,对请求进行处理。如果两者差值大于等于180秒,则拒绝请求。

下图展示了技能生成签名过程和DuerOS验证签名的过程。DuerOS验证签名过程中的2-3步可以使用rsa_verify函数代替。

文本卡片的示例

RSA方法生成公私钥

RSA方法生成的公钥和私钥是成对出现的,在DuerOS与技能通信过程中起着重要的作用。下面介绍RSA生成公钥和私钥的过程。

OpenSSL安装

首先介绍OpenSSL安装。

  • Windows安装 下载OpenSSL并安装OpenSSL,下载地址是http://slproweb.com/products/Win32OpenSSL.html,安装后配置Windows环境变量。

  • Linux用户可以使用系统自带的OpenSSL。
  • MacOS用户可以使用系统自带的OpenSSL。

RSA公钥私钥生成过程

私钥生成过程

执行下面命令生成1024位私钥rsa_private_key.pem。

genrsa -out rsa_private_key.pem 1024

生成私钥的内容如下。

----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDLAwyua/Mhu4Ik8a2iLst0yWijyyDeHsuTEM9/X/IhAtlxHJ7w
GmO5UmD0rSGv5rGDlu5n/jo8p35WLbOGTocs9RlOV5wS69rxtiO0CHHSdOi+jh1r
+9mDiPmnQQ2sOl6KFsvGwRB3UaCc6LgqDqsg89/f4IkrLLas3nPRa989RQIDAQAB
AoGALjLZde/2+lwzd7jP7LJ9dmxHNc8KAcI8TZFrxu7MqRp+5TDAMp+uxgOrMMMd
gWwcRXfZdSzzj84GABKSYiQIupg7V6rk/XgmIQAiBjWEvyzpwp71IRE9dzhkL5Qc
WF/PymajQ766vI1FhhLdU85Rc0Gly5ZawsfQGDBJ/s6AWMECQQD47D4gPA/Pnzpx
5VnMJpgLLqA7E5oOBiD0EINUZ0iYPMu/EYazUTAcLoRitUQorm16aP7IjaUvymHA
9HfDYsXpAkEA0MimPCuD3Pg8xaaSrqGXSCufOMezIOZcnFYSCIcAy0p0mBoySZON
ypvjB8ojhvCONRhQFJy35OlFuAOsl162/QJBAMNYalzTpbjTBYOycGkU9Ib5/Ua/
WEufJadDejz3nPHT7DUy5Nm+YhoLq1rnU+j1EfdZhHERL8w0b8iEUaRk1FkCQBEG
S4fchIQgOdRkINHcm1lnNTSMFC86mZKl8hJ/77CkAZ3lhPQ68/TxgTHBaeQ2+WGa
+ey0Wspvux+mLQyqzIECQQDEL+4/UFI/wKAsO41k8wibzZ8/Rm3BQTwV0i5tzxHO
9N5jIHkZa5AIVhq2qNBD+ev8gNp9MbipYUhduHrudLdS
-----END RSA PRIVATE KEY-----

公钥生成过程

执行下面的命令生成rsa_private_key.pem对应的公钥rsa_public_key.pem。

rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

生成的公钥内容如下。


----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLAwyua/Mhu4Ik8a2iLst0yWij
yyDeHsuTEM9/X/IhAtlxHJ7wGmO5UmD0rSGv5rGDlu5n/jo8p35WLbOGTocs9RlO
V5wS69rxtiO0CHHSdOi+jh1r+9mDiPmnQQ2sOl6KFsvGwRB3UaCc6LgqDqsg89/f
4IkrLLas3nPRa989RQIDAQAB
-----END PUBLIC KEY-----