E2E P01 & CRC计算

1、E2E的Profile(配置)

1.1 概述

E2E提供了一下五种保护机制来保护数据安全,如下:

CRC:发送端根据数据计算CRC值,接收端会重新计算并检查。

Sequence Counter: 发送端每次传输,该值都会加一,接收端会检查该值。

Alive Counter:发送端每次传输,该值都会加一,接收端会检查该值,通常跟Sequence Counter是一个东西(具体我也不知道有什么区别)。

Data ID:给每个数据或者I-PDU Group编号。

Timeout detection: 接收者接收超时,发送者响应超时。

  为了同时满足保护机制的标准化和灵活性要求,E2E 模块提供了很多个 profile,包括P01、P02、P04、P05 和 P06,P07, P11, P22,它们之间的最大区别就在于每一个所采用的保护机制是以上五个保护机制的子集。

Profile

保护机制

发送描述

最大保护数据长度

Profile01

Counter(4bit)、Data ID(16bit)、 CRC8、Timeout monitoring

Data ID由Data ID Mode决定是否发送 ,Counter和CRC需要发送

30bytes

Profile02

Counter(4bit)、Data ID List(8bit)、 CRC8

Data ID 不会发送,仅用作 CRC计算,Counter和CRC需要发送

256bytes

Profile04

Counter(16bit)、Data ID(32bit)、CRC32、Length(16bit)

Counter、Data ID、CRC、Length均会发送

4096bytes

Profile05

Counter(8bit)、Data ID(16bit) 、CRC16

Data ID 不会发送,仅用作 CRC计算,Counter和CRC需要发送

4096bytes

Profile06

Counter(8bit)、Data ID(16bit)、CRC16、Length(16bit)

Data ID 不会发送,仅用作 CRC 计算,Counter,CRC和Length需要发送

4096bytes

Profile07

Counter(32bit)、Data ID(32bit)、CRC64、Length(32bit)

Counter、Data ID、CRC、Length均会发送

未知

Profile11

Counter(4bit)、Data ID(16bit or 12bit)、CRC8

Counter、Data ID、CRC均会发送

30bytes

Profile12

Counter(4bit)、Data ID List(16*8bit)、CRC8

Data ID 不会发送,仅用作 CRC计算,Counter和CRC需要发送

未知

  • 对于CAN/CANFD/LIN通信信道,需保护的完整数据(包括应用数据、CRC和Counter)的长度不超过32字节,应通过E2E profile1进行保护

  • 对于CANFD通信信道,需保护的完整数据(包括应用数据、CRC和Counter)的长度超过32bytes,应通过E2E profile5进行保护

  • 对于ETH通信信道,需保护的完整数据(包括应用数据、CRC和Counter)的长度不超过4k bytes,应通过E2E profile4进行保护

  • 对于ETH通信信道,需保护的完整数据(包括应用数据、CRC和Counter)的长度超过4k bytes但不超过4M bytes,应通过E2E profile7进行保护

1.2 Profile1 

1.2.1 例子

下面的例子可以简单介绍E2E的工作机制,假设汽车内有两个ECU,A和B,两个节点之间通过CAN总线进行通信,A节点要将某一安全相关的数据(比如汽车车速信号,油门踏板信号等)传给B节点,这里我们假定车速信号VehSpeed = 0x1157,如果采用E2E概念对这个车速数据进行保护,那么实际上A除了要发给B上边VehicleSpeed数据之外,还要将CRC和Counter传给B,B在接受到数据之后也会计算出CRC然后将其和收到的进行比较,B会根据校验的结果进行下一步操作。

 -

那么现在的问题就是已知数据Data=0x1157,计算出CRC、Counter。

Profile1的一些属性:CRC,Counter,Timeout monitoring,Data ID

CRC:对数据进行多项式除法计算后的余数

Counter:用于计数每次增加1,A将计数值发给B,B可以依据收到的counter值确定是否接收及时。

Timeout monitoring:用来评价Counter是否丢失延时等。

DataID:一个A和B提前定好的特殊数字,一般是16bits,按照E2E_P01DataIDMode 的不同分为1A,1B,1C三种细分的配置,计算CRC时对DataID做不同处理。

在考虑上述Autosar要求后,我们要计算CRC的数据最终可写为Data = {0x09,0x000x000x57,0x11};这里我们假定DataID=0x0009,VehSpeed低8位放到数组靠前位置。

总结一下就是下面的过程

1.将counter放入Data

2.将DataID(16bits)按照一定规则放入Data

3.计算Data的CRC值

4.将counter增加1

1.2.2 profile 1 CRC的计算

profile 01的CRC计算基于 user data

关于CRC计算,CRC可以理解为多项式做除法后的余数,按照除数的不同可以分类为CRC-8,CRC-16,CRC-32等,看了一下大概好几十种。Autosar E2E profile 1 规定采用CRC-8-SAE J1850 ,对应多项式 x8+x4+x3+x2+1 ,即100011101,通常写为0x1D,注意这里不是0x11D,可能是最高位必然为1,所以省去了。

下面图片显示了二进制除法采用多项式计算0x57: CRC=0x8D的过程,实际上0x57按照不同的传输顺序分为两种Msbit-first(01010111)Lsbit-first(11101010)这里只计算Msbit-first的情况。后边添加了8个padded bits,但是观察下来猜测若要计算CRC-3要padded 3 bits?CRC-16要padded 16 bits??

取一个字符(8bit),逐位检查该字符,如果为1,字符^crc_mul;同时,如果原本crc最高位是1,那么crc^crc_mul后左移1位,否则只是左移一位

不取反  从高位开始异或  左移CRC

1.2.3 profile 1 工作机制图示

2、CRC-16代码实现

 2.1  直接计算法

#include <iostream>
#include <cstdint>

// 计算CRC16校验值
uint16_t calculateCRC16(const uint8_t* data, size_t length)
{
    uint16_t crc = 0xFFFF;
    
    for (size_t i = 0; i < length; ++i)
    {
        crc ^= data[i];
        
        for (int j = 0; j < 8; ++j)
        {
            if (crc & 0x0001)
            {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else
            {
                crc >>= 1;
            }
        }
    }
    
    return crc;
}

int main()
{
    // 示例数据
    uint8_t data[] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
    size_t length = sizeof(data) / sizeof(data[0]);
    
    // 计算CRC16校验值
    uint16_t crc16 = calculateCRC16(data, length);
    
    // 输出结果
    std::cout << "CRC16校验值: 0x" << std::hex << crc16 << std::endl;
    
    return 0;
}

2.2  查表法

2.2.1 表的生成算法

#define POLY 0xA001 // 生成多项式Ox8005的反序,即1000000000000101→1010000000000001,即A001
unsigned short auchCRC[256]; // CRC表
void make_crc_table(void) // 生成CRC表的函数
{
    unsigned short c;
    int i, j;
    for (i = 0; i < 256; i++)
    {
        c = i;
        for (j = 0; j < 8; j++) 
        {
            if (c & 0x1) // 如果最低位为1,则右移一位并与生成多项式异或(商1)
                c = (c >> 1) ^ POLY;
            else // 如果最低位为0,则只右移一位,无需异或(商0)
                c = c >> 1;
        }
        auchCRC[i] = c; // 将计算出的CRC校验码存入表中
    }
}

2.2.2 查表法

const UINT16 auchCRC[256] =
{
	0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440,0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040
};

//计算CRC16码,使用查表法
UINT16 CRC16(u8 *data, int len)
{
	UINT16 CRC = 0xffff;//0xff与数据异或就相当于取反,故只需要一开始把CRC初始值设置为0xffff即可
	UINT8 index;
	for (int i = 0; i < Len ; i++)
	{
		index = (CRC & 0xFF)^ data[i];//取上一字节的CRC低八位,与本字节异或
		CRC >>= 8;//取上一字节的高八位
		CRC ^= auchCRC[index];//与查表后的结果异或
	}
	return (CRC);
  • 初始值是给CRC计算一个初始值,可以是0,也可以是其他值;结果异或值是把计算结果再异或某一个值;这么做的目的是防止全0数据的CRC一直为0

  • 输入数据反转是指输入数据以字节为单位按位逆序处理;输出数据反转是指CRC计算结果整体按位逆序处理;这么做的目的我看到的一个合理解释是右移比左移更容易计算,效率高,它跟大小端无关。

 3、P01 的e2e 配置 

//========================server==================================================
"e2e" :
    {
        "e2e_enabled" : "true",
        "protected" :
        [
            {
                "service_id" : "0x1111",
                "event_id" : "0x3333",
                "profile" : "CRC8",
                "variant" : "protector",
                "crc_offset" : "0",//CRC存放的偏移位置,一般放在payload的第一个字节
                "data_id_mode" : "3",
                "data_length" : "56",//(payload 的长度-1)*8,单位bit
                "data_id" : "0xA73"
            }
        ]
    },

//=========================client===================================================
    "e2e" :
    {
        "e2e_enabled" : "true",
        "protected" :
        [
            {
                "service_id" : "0x1111",
                "event_id" : "0x3333",
                "profile" : "CRC8",
                "variant" : "checker",
                "crc_offset" : "0",
                "data_id_mode" : "3",
                "data_length" : "56",
                "data_id" : "0xA73"
            }
        ]
    },

### E2E校验与CRC校验的区别 #### 原理差异 E2E(End-to-End)校验主要用于确保数据在整个传输路径上的完整性,从发送端到接收端的过程中防止任何篡改或损坏。这种机制通常涉及更复杂的协议栈层次结构,不仅限于物理层的数据验证。 相比之下,CRC(循环冗余检验)是一种基于多项式除法的错误检测技术,专门用于发现固定长度消息中的无意改变。CRC利用模2除法进行计算,通过特定生成多项式得到一个校验序列附加在原始数据之后[^1]。 对于CRC的具体实现而言,当处理单字节输入时,会先将其与当前CRC值做异或操作,随后依据所得结果逐位执行移位及条件性的按位异或运算直至完成整个字节的操作流程[^4]。 而对于E2E保护,则可能采用多种手段组合而成,比如CRC本身加上额外的时间戳、计数器或者其他形式的身份认证措施来增强安全性[^3]。 #### 应用场景对比 CRC广泛应用于各种通信接口标准之中,如CAN总线系统里用来保障帧内信息准确性;而在文件存储领域也常见其身影以确认档案未被意外破坏。由于其实现较为简便高效,在硬件层面易于集成,因此成为众多行业默认的选择之一。 另一方面,E2E校验更多见诸于汽车电子控制单元(ECU)间的安全通讯需求场景下,特别是在涉及到关键行车功能的部分&mdash;&mdash;例如动力传动系统的指令交互过程中。这类应用往往要求更为严格的数据一致性和防攻击能力,故而倾向于选用综合防护方案而非单纯依赖某种简单的检错算法[^2]。 ```python def calculate_crc(data, polynomial=0x1D): crc = 0xFF for byte in data: crc ^= byte for _ in range(8): if crc &amp; 0x80: crc = ((crc &lt;&lt; 1) ^ polynomial) &amp; 0xFF else: crc &lt;&lt;= 1 crc &amp;= 0xFF return crc ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值