DM协议中的安全认证

来源:互联网 发布:福禄克的网络测试仪 编辑:程序博客网 时间:2024/06/06 08:34

     DM协议使用了SyncML认证框架,并在《SyncML_DM_Security》文档中定义了扩展。
     DM协议中的终端和服务端相互之间都需要作认证。 安全认证可以采用不同的级别。如果传输层中已经内建了认证机制,那么可以不使用DM协议级的认证。如果传输层没有提供足够安全的认证机制,那么DM协议级的认证是必需的。如果在原始请求中没有包含信息凭证或信息凭证不足,Server和终端都可以认证对方。
     假设DM协议使用传输层级的认证,那么它能够提供Session级的认证,这样可以在会话开始的时候交换认证凭证(比如TLS或WTLS协议)。如果传输层不能够提供Session级的认证,每次请求都必须作认证。

认证凭证

认证凭证 主要包含以下内容:

  • Server ID(唯一标识DM Server)
  • Username
  • Password
  • Nonce 允许通过使用静态数据的Hash算法防止重复攻击(静态数据是为了克服重复攻击)

为了作终端到Server的认证,username、password和nonce都是必须的(即使没有填写它们,这三者也会被作Hash处理)。

为了作Server到终端的认证,Server ID、password和nonce都是必须的。Server必须为它所服务的每一个终端使用不同的password,这样是为了避免使用一个共享密码时,当Server与一个终端正在交互时,另一个终端进入造假。

认证

DM协议使用与SyncML协议相同的安全认证技术。也就是,终端和Server都可以互相发送认证凭证或要求对方发送认证凭证。
对于DM协议,syncml:auth-MD5认证类型是必须的。

1 DM协议中的MD-5认证

MD-5认证是在SyncHdr的Cred中提供原始的userid:password。
如下所示:
<SyncML>
<SyncHdr>
<VerDTD>1.1</VerDTD>
<VerProto>DM/1.1</VerProto>
<SessionID>1</SessionID>
<MsgID>1</MsgID>
<Target>
<LocURI>http://www.syncml.org/mgmt-server</LocURI>
</Target>
<Source>
<LocURI>IMEI:493005100592800</LocURI>
</Source>
<Cred>
<Meta>
<Type xmlns="syncml:metinf">syncml:auth-MD5</Type>
</Meta>
<Data>18EA3F……</Data>
<!-- base64 formatting of MD-5 Digest -->
</Cred>
<Meta>
<MaxMsgSize xmlns="syncml:metinf">5000</MaxMsgSize>
</Meta>
</SyncHdr>
<!—regular body information here -->
<SyncBody>
</SyncBody>
</SyncML>

2 计算MD-5摘要

Cred中提供的MD-5摘要是根据如下规则计算的:
H=MD5 Hash函数
Digest=MD5 Hash函数的输出
B64=base64编码函数
Digest=H(B64 (H(username:password) ):nonce)

这个算法允许认证方在不清楚password的情况下作认证。Password既没有作为Cred的一部分发送,也不需要认证方知道,认证方只需要保存一份计算好Hash值的username:password字串。

3 Password和nonce的使用方法

password和nonce的长度都建议至少要128位。
无论是从终端设备,还是从DM Server,要求对方认证时,nonce是必须的。
一旦认证凭证发给了对方,整个过程中nonce不变。

认证方必须考虑到认证凭证中的nonce失效的问题(可能是因为之前的通讯失败)。鉴于此,如果认证失败,认证方必须生成一个新的nonce,然后再次进行认证过程。

每个会话都要使用一个新的nonce,nonce值的序列应该是不可预料的。

4 认证过程实例

  • 首先终端向DM Server发送Package 1。这时nonce是随便填的,如下例中的"sfOMmg54tOJfhp12mwiEFg=="
    <SyncML xmlns='SYNCML:SYNCML1.1'>
    <SyncHdr>
    <VerDTD>1.1</VerDTD>
    <VerProto>DM/1.1</VerProto>
    <SessionID>4</SessionID>
    <MsgID>1</MsgID>
    <Target>
    <LocURI>http://10.5.24.32:8080/funambol/dm</LocURI>
    </Target>
    <Source>
    <LocURI>dmtest</LocURI>
    <LocName>funambol</LocName>
    </Source>
    <Cred>
    <Meta>
    <Format xmlns='syncml:metinf'>b64</Format>
    <Type xmlns='syncml:metinf'>syncml:auth-md5</Type>
    </Meta>
    <Data> sfOMmg54tOJfhp12mwiEFg== </Data>
    </Cred>
    <Meta>
    <MaxMsgSize xmlns='syncml:metinf'>5000</MaxMsgSize>
    <MaxObjSize xmlns='syncml:metinf'>25000</MaxObjSize>
    </Meta>
    </SyncHdr>
    <SyncBody>
    <Alert>
    <CmdID>1</CmdID>
    <Data>1201</Data>
    </Alert>
    <Replace>
    <CmdID>2</CmdID>
    <Item>
    <Source>
    <LocURI>./DevInfo/Lang</LocURI>
    </Source>
    <Data>en-us</Data>
    </Item>
    <Item>
    <Source>
    <LocURI>./DevInfo/DmV</LocURI>
    </Source>
    <Data>4.0</Data>
    </Item>
    <Item>
    <Source>
    <LocURI>./DevInfo/Mod</LocURI>
    </Source>
    <Data>scts devman</Data>
    </Item>
    <Item>
    <Source>
    <LocURI>./DevInfo/Man</LocURI>
    </Source>
    <Data>SyncML</Data>
    </Item>
    <Item>
    <Source>
    <LocURI>./DevInfo/DevId</LocURI>
    </Source>
    <Data>dmtest</Data>
    </Item>
    </Replace>
    <Final/>
    </SyncBody>
    </SyncML>
  • DM Server经过认证检查,发现终端的授权不合法,要求终端用新生成nonce重新认证
    <SyncML>
    <SyncHdr>
    <VerDTD>1.1</VerDTD>
    <VerProto>DM/1.1</VerProto>
    <SessionID>4</SessionID>
    <MsgID>1</MsgID>
    <Target>
    <LocURI>dmtest</LocURI>
    <LocName>funambol</LocName>
    </Target>
    <Source>
    <LocURI>http://10.5.24.32:8080/funambol/dm</LocURI>
    </Source>
    <RespURI>http://10.5.24.32:8080/funambol/dm?sid=W0JAMWE4ODg1Zi0xMjcyNTI2NzE5NTc4</RespURI>
    <Cred>
    <Meta>
    <Format xmlns='syncml:metinf'>b64</Format>
    <Type xmlns='syncml:metinf'>syncml:auth-md5</Type>
    </Meta>
    <Data>Dq77Ns5kBvpeE0/KG7lMGg==</Data>
    </Cred>
    <Meta>
    <MaxMsgSize xmlns='syncml:metinf'>5000</MaxMsgSize>
    <MaxObjSize xmlns='syncml:metinf'>25000</MaxObjSize>
    </Meta>
    </SyncHdr>
    <SyncBody>
    <Status>
    <CmdID>1</CmdID>
    <MsgRef>1</MsgRef>
    <CmdRef>0</CmdRef>
    <Cmd>SyncHdr</Cmd>
    <TargetRef>http://10.5.24.32:8080/funambol/dm</TargetRef>
    <SourceRef>dmtest</SourceRef>
    <Chal>
    <Meta>
    <Format xmlns='syncml:metinf'>b64</Format>
    <Type xmlns='syncml:metinf'>syncml:auth-md5</Type>
    <NextNonce xmlns='syncml:metinf'>gDslXkBVXH0xXipPdjl6Lg==</NextNonce>
    </Meta>
    </Chal>
    <Data>401</Data>
    </Status>
    <Status>
    <CmdID>2</CmdID>
    <MsgRef>1</MsgRef>
    <CmdRef>1</CmdRef>
    <Cmd>Alert</Cmd>
    <Data>401</Data>
    </Status>
    <Status>
    <CmdID>3</CmdID>
    <MsgRef>1</MsgRef>
    <CmdRef>2</CmdRef>
    <Cmd>Replace</Cmd>
    <Data>401</Data>
    </Status>
    <Final>
    </Final>
    </SyncBody>
    </SyncML>
  • 终端根据Server发过来的新nonce,重新生成认证凭证,再发给Server (此时还是Package 1)
    <SyncML xmlns='SYNCML:SYNCML1.1'>
    <SyncHdr>
    <VerDTD>1.1</VerDTD>
    <VerProto>DM/1.1</VerProto>
    <SessionID>4</SessionID>
    <MsgID>2</MsgID>
    <Target>
    <LocURI>http://10.5.24.32:8080/funambol/dm?sid=W0JAMWE4ODg1Zi0xMjcyNTI2NzE5NTc4</LocURI>
    </Target>
    <Source>
    <LocURI>dmtest</LocURI>
    <LocName>funambol</LocName>
    </Source>
    <Cred>
    <Meta>
    <Format xmlns='syncml:metinf'>b64</Format>
    <Type xmlns='syncml:metinf'>syncml:auth-md5</Type>
    </Meta>
    <Data>gDwKeu7afMRzKdSIyt1RGg==</Data>
    </Cred>
    <Meta>
    <MaxMsgSize xmlns='syncml:metinf'>5000</MaxMsgSize>
    <MaxObjSize xmlns='syncml:metinf'>25000</MaxObjSize>
    </Meta>
    </SyncHdr>
    <SyncBody>
    <Status>
    <CmdID>1</CmdID>
    <MsgRef>1</MsgRef>
    <CmdRef>0</CmdRef>
    <Cmd>SyncHdr</Cmd>
    <TargetRef>dmtest</TargetRef>
    <SourceRef>http://10.5.24.32:8080/funambol/dm</SourceRef>
    <Data>212</Data>
    </Status>
    <Alert>
    <CmdID>2</CmdID>
    <Data>1201</Data>
    </Alert>
    <Replace>
    <CmdID>3</CmdID>
    <Item>
    <Source>
    <LocURI>./DevInfo/Lang</LocURI>
    </Source>
    <Data>en-us</Data>
    </Item>
    <Item>
    <Source>
    <LocURI>./DevInfo/DmV</LocURI>
    </Source>
    <Data>4.0</Data>
    </Item>
    <Item>
    <Source>
    <LocURI>./DevInfo/Mod</LocURI>
    </Source>
    <Data>scts devman</Data>
    </Item>
    <Item>
    <Source>
    <LocURI>./DevInfo/Man</LocURI>
    </Source>
    <Data>SyncML</Data>
    </Item>
    <Item>
    <Source>
    <LocURI>./DevInfo/DevId</LocURI>
    </Source>
    <Data>dmtest</Data>
    </Item>
    </Replace>
    <Final/>
    </SyncBody>
    </SyncML>

终端通过像上面那样第二次发送Package 1后,获得Server的认证。

终端通过使用Server产生的nonce计算认证凭证的过程如下:¶

假设Server返回的nonce为“gDslXkBVXH0xXipPdjl6Lg==”。
1) 对nonce进行B64解码
byte[] clientNonce = new BASE64Decoder().decodeBuffer("gDslXkBVXH0xXipPdjl6Lg==");

2) 根据公式 B64 (H(username:password)) 计算username:password的编码
StringBuffer userpwd=new StringBuffer();
userpwd.append(username).append(':').append(password);
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] userDigestBytes =new BASE64Encoder().encode(md.digest(userpwd.toString().getBytes())).getBytes();

3) 建立一个缓冲区buf,长度等于userDigestBytes.length + 1 + clientNonce.length
byte[] buf = new byte[userDigestBytes.length + 1 + clientNonce.length];

4) 先将userDigestBytes中的内容复制到buf中,再将clientNonce中的内容复制到后面
System.arraycopy(userDigestBytes, 0, buf, 0, userDigestBytes.length);
buf[userDigestBytes.length] = (byte)':';
System.arraycopy(clientNonce, 0, buf, userDigestBytes.length+1, clientNonce.length);

5) 对缓冲区进行MD编码
byte[] digest = MD5.digest(buf);

6) 再进行B64编码
String serverDigestNonceB64 = new String(Base64.encode(digest));

最后得到的serverDigestNonceB64就是新的认证凭证。