热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SIMPLICITI加密机制

一、帧结构为了支持加密,相比未加密数据帧,对帧格式进行两处更改。1、当帧被加密时,设置加密有效位。即网络层帧头第一个字F_ENCRYPT_OS_MSK置1.。2、在网络层帧头往后加


一、帧结构

为了支持加密,相比未加密数据帧,对帧格式进行两处更改。

1、当帧被加密时,设置加密有效位。即网络层帧头第一个字F_ENCRYPT_OS_MSK置1.。

2、在网络层帧头往后加3个字节。如下所示,分别为CTR、ICHK和MAC,CTR用于存储加密计数器初始值,ICHK用于存储FCS(帧校验序列),这里默认使用求和校验。MAC用于存储消息认证码。这将会使允许的有效最大应用程序有效负载减少3。

 


二、加密参数

1、初始化向量( IV )

     初始化向量是一个32位的无符号对象。 它在文件nwk_security.c中声明和定义。 用户可以根据需要进行更改。默认为0x87654321.

2、密钥(KEY)

       密钥是一个128位值,它初始化为16字节的字符数组。加密算法适用于32位无符号长对象。初始化密钥是字符数组,根据需要进行字节交换以适应不同微控制器的大小端。 必须这样做才能保证具有不同本机端表示的微控制器能有相同的加密结果,密钥初始化值为SimpliciTI's Key。

3、消息认证码(MAC)

     消息认证码是一个8位的常量。当有效负载被解密时,将MAC值与期望值进行比较。它不参与消息完整性检查,默认值为0xA5。

4、计数器(COUNTER)

       计数器是32位无符号长整形对象。对于基于连接的应用程序,每个连接的计数器的初始值都是在运行时生成的。 这些连接基本上代表用户应用程序,建立连接时,在链接会话中交换初始值。对于网络应用程序,计数器值的导出方式不同,因为网络应用程序不是基于连接的。


三、负载加密与解密过程

1、加密过程

       首先由初始化向量和计数器值和密钥进行串联,成为64位数据,通过XTEA产生8个字节的加密数据,然后将准备加密的八个字节分别于加密数据进行异或操作,结果即为加密后的数据。为保证密码块不会重复,每一次加密改变计数器值,而计数器在较长时间内不会重复,负载长度有限,则不会出现重复代码块。更改每个加密的计数器可确保每个加密操作都有一个唯一的块。由于加密中使用的密钥长度为128位,在得到的64位密码块和要发送的(下一个)64位纯文本之间进行独占的按位逻辑异或。如果剩余的纯文本小于64位,则丢弃额外的密码块。 如果纯文本仍然存在,则创建下一个密码块,增加计数值。

2、解密过程

       解密是通过加密与加密端相同的块来完成的。 然后,所得到的密码块与接收的密码流进行异或,以再现原始的纯文本。因为与相同的数进行两次异或即为本身。 由于密码流与原始纯文本的长度匹配,因此使用相同的过程来纠正非64位倍数的流。显然,这种方案取决于保持计数器同步。

 


四、XTEA算法

       在密码学中,微型加密算法(Tiny Encryption Algorithm,TEA)是一种易于描和执行的块密码,通常只需要很少的代码就可实现。其设计者是剑桥大学计算机实验室的大卫·惠勒与罗杰·尼达姆。这项技术最初于1994年提交给鲁汶的快速软件加密的研讨会上,并在该研讨会上演讲中首次发表。XTEA是TEA的升级版,增加了更多的密钥表,移位和异或操作等等,设计者是Roger Needham, David Wheeler

加密过程:

代码实现:


/******************************************************************************
* @fn xtea_encipher
*
* @brief XTEA encipher algorithm. Calling arguments removed from public
* domain code and static-scope values used instead.
*
* input parameters
*
* output parameters
*
* @return void
*/
void xtea_encipher(void)
{
uint32_t v0=sMsg[0], v1=sMsg[1];
uint16_t i;
uint32_t sum=0, delta=0x9E3779B9;
for(i=0; i {
v0 += (((v1 <<4) ^ (v1 >> 5)) + v1) ^ (sum + sKey.keyL[sum & 3]);
sum += delta;
v1 += (((v0 <<4) ^ (v0 >> 5)) + v0) ^ (sum + sKey.keyL[(sum>>11) & 3]);
}
sMsg[0]=v0;
sMsg[1]=v1;
}

五、SIMPLICI TI提供的API

      SIMPLICI TI在信息加密部分主要提供了两个主要函数,即加密数据帧,以及解密数据帧,nwk_setSecureFrame和nwk_getSecureFrame。nwk_setSecureFrame首先输入的判断计数器初始值是否为空,为空则产生一个随机数赋值给本地计数器,然后给CTR、ICHK 和MAC赋值,然后进行加密, F_ENCRYPT_OS置位,最后保存locnt到ctr。nwk_getSecureFrame则是nwk_setSecureFrame的逆过程,首先进行计数器的校验,如果匹配,进行解密,然后进行MAC和FCS的校验。

nwk_setSecureFrame:


/******************************************************************************
* @fn nwk_setSecureFrame
*
* @brief Called from NWK to secure a frame.
*
* input parameters
* @param frame - pointer to frame to secure
* @param msglen - length of message
* @param ctr - pointer to the counter used in the cipher block. This will
* be NULL if a network application is sending a frame. Since
* these are not connection-based there is no counter sync
* issue but we still need a counter value. A random value
* is used.
*
* output parameters
* @param cntStart - counter is updated during encryption.
*
* @return void
*/
void nwk_setSecureFrame(mrfiPacket_t *frame, uint8_t msglen, uint32_t *ctr)
{
uint32_t locCnt;
/* If an encrypted frame is to be sent to a non-connection based port use a
* random number as the lsb counter value. In this case only the lsb is used
* for a counter value during decryption. Not as secure but there are still
* the 32 bits in the IV.
*/
locCnt = ctr ? *ctr : MRFI_RandomByte();
/* place counter value into frame */
PUT_INTO_FRAME(MRFI_P_PAYLOAD(frame), F_SEC_CTR_OS, (uint8_t)(locCnt & 0xFF));
/* Put MAC value in */
nwk_putNumObjectIntoMsg((void *)&sMAC, (void *)(MRFI_P_PAYLOAD(frame)+F_SEC_MAC_OS), sizeof(secMAC_t));
/* Put FCS value in */
{
secFCS_t fcs = calcFCS(MRFI_P_PAYLOAD(frame)+F_SEC_MAC_OS, msglen+sizeof(secMAC_t));
nwk_putNumObjectIntoMsg((void *)&fcs, (void *)(MRFI_P_PAYLOAD(frame)+F_SEC_ICHK_OS), sizeof(secFCS_t));
}
/* Encrypt frame */
msg_encipher(MRFI_P_PAYLOAD(frame)+F_SEC_ICHK_OS, msglen+sizeof(secMAC_t)+sizeof(secFCS_t), &locCnt);
/* Set the Encryption bit */
PUT_INTO_FRAME(MRFI_P_PAYLOAD(frame), F_ENCRYPT_OS, F_ENCRYPT_OS_MSK);
/* Update the counter if it was a "real" counter. */
if (ctr)
{
*ctr = locCnt;
}
return;
}

nwk_getSecureFrame:


/******************************************************************************
* @fn nwk_getSecureFrame
*
* @brief Called from NWK to get a secure a frame and decrypt.
*
* input parameters
* @param frame - pointer to frame containing encrypted message
* @param msglen - length of message
* @param ctr - pointer to the counter used in the cipher block. This will
* be NULL if a network applicaiton is getting a frame. Since
* these are not connection-nbased there is no counter sync
* issue but we still need a counter value.
*
* output parameters
* @param cntStart - counter is updated during decryption. If decryption fails
* this value is not changed.
*
* @return Returns non-zero if frame decryption is valid, otherwise returns 0.
*/
uint8_t nwk_getSecureFrame(mrfiPacket_t *frame, uint8_t msglen, uint32_t *ctr)
{
uint8_t rc = 1;
uint8_t dOne= 0;
uint8_t cntHint = GET_FROM_FRAME(MRFI_P_PAYLOAD(frame), F_SEC_CTR_OS);
uint32_t locCnt, frameCnt;
/* Construct proposed CTR values */
/* Just like encryption, we may be talking to a non-connection based
* peer in which case the counter value is represented by the lsb byte
* conveyed in the frame.
*/
locCnt = ctr ? *ctr : cntHint;
frameCnt = (locCnt & 0xFFFFFF00) + cntHint;
do
{
/* See if counters match */
if (locCnt == frameCnt)
{
/* When the counters appear to match is the only time we actually decipher
* the message. It is the only time we can do so since out-of-sync lsb counter
* values guarantees that something is wrong somewhere. Decryption is successful
* only if the MAC and FCS values match. The message is left as-is after the
* decipher attempt. Either it appears valid or is doesn't and is discarded.
* There is no recovery attempt if the counters match but the MAC or FCS do
* not. It is considered a rogue message.
*/
msg_decipher(MRFI_P_PAYLOAD(frame)+F_SEC_ICHK_OS, msglen-1, &locCnt);
/* Get MAC and make sure it matches. A failure can occur if a replayed frame happens
* to have the correct counter sync value but was encoded with the wrong complete
* counter value. Otherwise the MAC values must match when the counter values are equal.
*/
{
secMAC_t mac;
nwk_getNumObjectFromMsg((void *)(MRFI_P_PAYLOAD(frame)+F_SEC_MAC_OS), (void *)&mac, sizeof(secMAC_t));
if (mac != sMAC)
{
rc = 0;
}
}
/* FCS check... */
{
secFCS_t fcs;
nwk_getNumObjectFromMsg((void *)(MRFI_P_PAYLOAD(frame)+F_SEC_ICHK_OS), (void *)&fcs, sizeof(secFCS_t));
if (fcs != calcFCS(MRFI_P_PAYLOAD(frame)+F_SEC_MAC_OS, msglen-1-sizeof(secMAC_t)))
{
rc = 0;
}
}
/* we're done. */
dOne= 1;
}
else
{
/* Uh oh. Counters don't match. Try and resync. We need to distinguish among
* missed frames, duplicates and rogues plus account for counter wrap.
*/
if (frameCnt > locCnt)
{
/* frameCnt is bigger. Second part of test below takes care of
* the unlikely case of a complete counter wrap (msb's all 0) in
* which case the test will incorrectly fail when the count is
* actually within the (wrapped) window. #ifdef'ed to avoid compiler
* warning in case user sets CNT_WINDOW to 0 (pointless comparison of
* unsigned value).
*/
if (((frameCnt-CTR_WINDOW) <= locCnt)
#if CTR_WINDOW > 0
|| (frameCnt #endif
)
{
/* Value within window. We probably missed something. Adjust and decipher.
* If locCnt is less because it wrapped and frameCnt didn't it means that
* it's a duplicate or late frame. In that case the following will lead to
* a decryption that fails sanity checks which is OK because the frame will
* be correctly rejected.
*/
locCnt = frameCnt;
}
else
{
/* It's either a rogue or a really old duplicate packet. In either case
* we dismiss the frame.
*/
rc = 0;
dOne= 1;
}
}
else
{
/* locCnt is bigger. The only way the frame can be valid is if the
* counter wrapped causing frameCnt to appear to be smaller. Wrap the
* counter and decrypt. If the frame isn't valid, i.e., it's late,
* a duplicate, or a rogue, the decryption will fail sanity checks and
* the frame will be correctly rejected. The following arithmetic works
* correctly without a special test for the complete counter wrap case.
*/
frameCnt += 0x100; /* wrap the hint-based counter */
if (((frameCnt-CTR_WINDOW) <= locCnt))
{
/* An lsb wrap but still within window. We probably missed something.
* Adjust (with wrap) and decrypt.
*/
locCnt = frameCnt;
}
else
{
/* rogue frame */
rc = 0;
dOne= 1;
}
}
}
} while (!done);
if (ctr && rc)
{
/* Only update the counter if the count was a "real" one and the
* decryption succeeded.
*/
*ctr = locCnt;
}
return rc;
}
#endif /* SMPL_SECURE */

 



推荐阅读
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 配置IPv4静态路由实现企业网内不同网段用户互访
    本文介绍了通过配置IPv4静态路由实现企业网内不同网段用户互访的方法。首先需要配置接口的链路层协议参数和IP地址,使相邻节点网络层可达。然后按照静态路由组网图的操作步骤,配置静态路由。这样任意两台主机之间都能够互通。 ... [详细]
author-avatar
手机用户2502861125
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有