国产精品人人做人人爽-婷婷丁香在线-亚洲精品久久午夜麻豆-无码AV中文一区二区三区-精品亚洲成?人在线观看青青-亚洲日韩av中文无码专区-亚洲AV无码久久一区二区三区-日本欧美中文字幕人在线-日韩久久AV-久久精品国产亚洲不AV麻豆

I Love mcu
歡迎光臨我愛單片機博客!

基于STC15W104單片機模擬加密芯片的源代碼

#include <STC15W104.h> ?// STC15F104W單片機頭文件
#include <intrins.h> ? ? // 包含_nop_()等 intrinsic 函數(shù)
/**
?* 基于STC15W104的加密芯片模擬
?* 利用STC15W104內(nèi)置EEPROM存儲密鑰和加密數(shù)據(jù)
?* 功能特性:
?* 1. 數(shù)據(jù)加密存儲
?* 2. 密鑰管理
?* 3. 數(shù)據(jù)完整性校驗
?* 4. 斷電數(shù)據(jù)保持
?*/
// EEPROM地址定義
#define EEPROM_KEY_ADDR 0x00 ?// 密鑰存儲地址,占用8字節(jié)
#define EEPROM_DATA_ADDR 0x10 ?// 數(shù)據(jù)存儲起始地址
#define EEPROM_SIZE 128 ?// STC15F104W內(nèi)置EEPROM大?。?28字節(jié))
// 密鑰長度
#define KEY_LENGTH 8 ?// 密鑰長度為8字節(jié)
/**
?* 延時函數(shù)
?* @param ms 延時毫秒數(shù)
?* @note 該延時函數(shù)適用于12MHz晶振的STC15W104
?*/
void Delay_ms(unsigned int ms)
{
? ? unsigned int i, j;
? ? for (i = 0; i < ms; i++)
? ? ? ? for (j = 0; j < 120; j++); ?// 循環(huán)120次約為1ms
}
/**
?* 寫EEPROM
?* @param addr EEPROM地址
?* @param dat 要寫入的數(shù)據(jù)
?* @note STC15W104的EEPROM操作需要使用IAP指令
?* @note 每次寫入后需要延時5ms以確保數(shù)據(jù)寫入完成
?*/
void EEPROM_Write(unsigned char addr, unsigned char dat)
{
? ? IAP_CONTR = 0x80; ?// 使能IAP操作,設(shè)置等待時間為0
? ? IAP_CMD = 0x02; ? ?// 設(shè)置為寫命令
? ? IAP_ADDRH = addr >> 8; ?// 設(shè)置地址高8位
? ? IAP_ADDRL = addr; ? ? ? // 設(shè)置地址低8位
? ? IAP_DATA = dat; ? ? ? ? // 設(shè)置要寫入的數(shù)據(jù)
? ? IAP_TRIG = 0x5A; ? // 觸發(fā)IAP操作,第一個觸發(fā)字節(jié)
? ? IAP_TRIG = 0xA5; ? // 觸發(fā)IAP操作,第二個觸發(fā)字節(jié)
? ? _nop_(); ? ? ? ? ? // 空操作,確保操作完成
? ? IAP_CONTR = 0x00; ?// 禁用IAP操作,關(guān)閉IAP功能
}
/**
?* 讀EEPROM
?* @param addr EEPROM地址
?* @return 讀取的數(shù)據(jù)
?* @note STC15F104W的EEPROM操作需要使用IAP指令
?*/
unsigned char EEPROM_Read(unsigned char addr)
{
? ? unsigned char dat;
? ? IAP_CONTR = 0x80; ?// 使能IAP操作,設(shè)置等待時間為0
? ? IAP_CMD = 0x01; ? ?// 設(shè)置為讀命令
? ? IAP_ADDRH = addr >> 8; ?// 設(shè)置地址高8位
? ? IAP_ADDRL = addr; ? ? ? // 設(shè)置地址低8位
? ? IAP_TRIG = 0x5A; ? // 觸發(fā)IAP操作,第一個觸發(fā)字節(jié)
? ? IAP_TRIG = 0xA5; ? // 觸發(fā)IAP操作,第二個觸發(fā)字節(jié)
? ? _nop_(); ? ? ? ? ? // 空操作,確保操作完成
? ? dat = IAP_DATA; ? ?// 讀取數(shù)據(jù)
? ? IAP_CONTR = 0x00; ?// 禁用IAP操作,關(guān)閉IAP功能
? ? return dat;
}
/**
?* 簡單的異或加密算法
?* @param data 要加密的數(shù)據(jù)
?* @param len 數(shù)據(jù)長度
?* @param key 密鑰
?* @param key_len 密鑰長度
?* @note 異或加密是一種對稱加密算法,相同的密鑰可以用于加密和解密
?* @note 當(dāng)密鑰長度小于數(shù)據(jù)長度時,會循環(huán)使用密鑰
?*/
void encrypt_data(unsigned char *data, unsigned char len, unsigned char *key, unsigned char key_len)
{
? ? unsigned char i;
? ? for (i = 0; i < len; i++)
? ? {
? ? ? ? data[i] ^= key[i % key_len]; ?// 異或加密,使用循環(huán)密鑰
? ? }
}
/**
?* 簡單的異或解密算法
?* @param data 要解密的數(shù)據(jù)
?* @param len 數(shù)據(jù)長度
?* @param key 密鑰
?* @param key_len 密鑰長度
?* @note 由于異或運算的特性,加密和解密使用相同的算法
?*/
void decrypt_data(unsigned char *data, unsigned char len, unsigned char *key, unsigned char key_len)
{
? ? // 異或加密和解密使用相同的算法
? ? // 因為 A ^ B ^ B = A,所以再次異或相同的密鑰即可解密
? ? encrypt_data(data, len, key, key_len);
}
/**
?* 計算CRC校驗值
?* @param data 數(shù)據(jù)
?* @param len 數(shù)據(jù)長度
?* @return CRC校驗值
?* @note 使用CRC-8算法,多項式為0x31 (x^8 + x^5 + x^4 + 1)
?* @note CRC校驗用于檢測數(shù)據(jù)傳輸或存儲過程中的錯誤
?*/
unsigned char calculate_crc(unsigned char *data, unsigned char len)
{
? ? unsigned char crc = 0x00; ?// 初始CRC值
? ? unsigned char i, j;
? ? for (i = 0; i < len; i++)
? ? {
? ? ? ? crc ^= data[i]; ?// 與當(dāng)前數(shù)據(jù)字節(jié)異或
? ? ? ? for (j = 0; j < 8; j++) ?// 處理每個比特位
? ? ? ? {
? ? ? ? ? ? if (crc & 0x80) ?// 如果最高位為1
? ? ? ? ? ? ? ? crc = (crc << 1) ^ 0x31; ?// 左移并與多項式異或
? ? ? ? ? ? else
? ? ? ? ? ? ? ? crc <<= 1; ?// 左移
? ? ? ? }
? ? }
? ? return crc; ?// 返回計算得到的CRC值
}
/**
?* 從EEPROM讀取密鑰
?* @param key 密鑰緩沖區(qū)
?* @note 從EEPROM的密鑰存儲區(qū)域讀取8字節(jié)密鑰
?*/
void read_key(unsigned char *key)
{
? ? unsigned char i;
? ? for (i = 0; i < KEY_LENGTH; i++)
? ? {
? ? ? ? key[i] = EEPROM_Read(EEPROM_KEY_ADDR + i); ?// 依次讀取8字節(jié)密鑰
? ? }
}
/**
?* 向EEPROM寫入密鑰
?* @param key 密鑰
?* @note 向EEPROM的密鑰存儲區(qū)域?qū)懭?字節(jié)密鑰
?* @note 每次寫入后需要延時5ms以確保數(shù)據(jù)寫入完成
?*/
void write_key(unsigned char *key)
{
? ? unsigned char i;
? ? for (i = 0; i < KEY_LENGTH; i++)
? ? {
? ? ? ? EEPROM_Write(EEPROM_KEY_ADDR + i, key[i]); ?// 依次寫入8字節(jié)密鑰
? ? ? ? Delay_ms(5); ?// EEPROM寫入需要延時
? ? }
}
/**
?* 驗證密鑰
?* @param key 要驗證的密鑰
?* @return 驗證結(jié)果,0成功,1失敗
?* @note 比較輸入密鑰與存儲在EEPROM中的密鑰是否一致
?*/
unsigned char verify_key(unsigned char *key)
{
? ? unsigned char stored_key[KEY_LENGTH];
? ? unsigned char i;
? ? read_key(stored_key); ?// 讀取存儲的密鑰
? ? for (i = 0; i < KEY_LENGTH; i++)
? ? {
? ? ? ? if (key[i] != stored_key[i]) ?// 逐字節(jié)比較
? ? ? ? ? ? return 1; ?// 驗證失敗
? ? }
? ? return 0; ?// 驗證成功
}
/**
?* 更改密鑰
?* @param old_key 舊密鑰
?* @param new_key 新密鑰
?* @return 操作結(jié)果,0成功,1失敗
?* @note 只有提供正確的舊密鑰才能更改密鑰
?*/
unsigned char change_key(unsigned char *old_key, unsigned char *new_key)
{
? ? // 驗證舊密鑰
? ? if (verify_key(old_key))
? ? ? ? return 1; ?// 舊密鑰驗證失敗
? ? // 寫入新密鑰
? ? write_key(new_key);
? ? return 0; ?// 密鑰更改成功
}
/**
?* 寫入數(shù)據(jù)到加密芯片
?* @param addr 數(shù)據(jù)地址(相對于數(shù)據(jù)存儲區(qū)起始地址)
?* @param data 數(shù)據(jù)
?* @param len 數(shù)據(jù)長度
?* @return 操作結(jié)果,0成功,1失敗
?* @note 數(shù)據(jù)會先加密再存儲,并在數(shù)據(jù)末尾添加CRC校驗值
?*/
unsigned char write_data(unsigned char addr, unsigned char *data, unsigned char len)
{
? ? unsigned char key[KEY_LENGTH];
? ? unsigned char i;
? ? unsigned char crc;
? ? // 檢查地址和長度是否合法
? ? // 預(yù)留1字節(jié)用于存儲CRC校驗值
? ? if (addr + len + 1 > (EEPROM_SIZE – EEPROM_DATA_ADDR))
? ? ? ? return 1; ?// 地址或長度超出范圍
? ? // 讀取密鑰
? ? read_key(key);
? ? // 加密數(shù)據(jù)
? ? encrypt_data(data, len, key, KEY_LENGTH);
? ? // 計算CRC校驗值
? ? crc = calculate_crc(data, len);
? ? // 寫入加密后的數(shù)據(jù)
? ? for (i = 0; i < len; i++)
? ? {
? ? ? ? EEPROM_Write(EEPROM_DATA_ADDR + addr + i, data[i]);
? ? ? ? Delay_ms(5); ?// 延時確保寫入完成
? ? }
? ? // 寫入CRC校驗值
? ? EEPROM_Write(EEPROM_DATA_ADDR + addr + len, crc);
? ? Delay_ms(5); ?// 延時確保寫入完成
? ? return 0; ?// 寫入成功
}
/**
?* 從加密芯片讀取數(shù)據(jù)
?* @param addr 數(shù)據(jù)地址(相對于數(shù)據(jù)存儲區(qū)起始地址)
?* @param data 數(shù)據(jù)緩沖區(qū)
?* @param len 數(shù)據(jù)長度
?* @return 操作結(jié)果,0成功,1失敗,2 CRC校驗錯誤
?* @note 讀取數(shù)據(jù)后會先驗證CRC,然后解密
?*/
unsigned char read_data(unsigned char addr, unsigned char *data, unsigned char len)
{
? ? unsigned char key[KEY_LENGTH];
? ? unsigned char i;
? ? unsigned char stored_crc, calculated_crc;
? ? // 檢查地址和長度是否合法
? ? if (addr + len + 1 > (EEPROM_SIZE – EEPROM_DATA_ADDR))
? ? ? ? return 1; ?// 地址或長度超出范圍
? ? // 讀取密鑰
? ? read_key(key);
? ? // 讀取加密數(shù)據(jù)
? ? for (i = 0; i < len; i++)
? ? {
? ? ? ? data[i] = EEPROM_Read(EEPROM_DATA_ADDR + addr + i);
? ? }
? ? // 讀取存儲的CRC校驗值
? ? stored_crc = EEPROM_Read(EEPROM_DATA_ADDR + addr + len);
? ? // 計算讀取數(shù)據(jù)的CRC校驗值
? ? calculated_crc = calculate_crc(data, len);
? ? // 驗證CRC校驗值
? ? if (stored_crc != calculated_crc)
? ? ? ? return 2; ?// CRC校驗錯誤
? ? // 解密數(shù)據(jù)
? ? decrypt_data(data, len, key, KEY_LENGTH);
? ? return 0; ?// 讀取成功
}
/**
?* 加密芯片初始化
?* 首次使用時設(shè)置默認(rèn)密鑰
?* @note 檢查密鑰存儲區(qū)域是否為空白(全0xFF),如果是則設(shè)置默認(rèn)密鑰
?*/
void crypto_chip_init(void)
{
? ? unsigned char default_key[KEY_LENGTH] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};
? ? unsigned char i;
? ? unsigned char blank_check = 0xFF;
? ? // 檢查密鑰是否已設(shè)置
? ? for (i = 0; i < KEY_LENGTH; i++)
? ? {
? ? ? ? blank_check &= EEPROM_Read(EEPROM_KEY_ADDR + i);
? ? }
? ? // 如果密鑰未設(shè)置(EEPROM為全0xFF),設(shè)置默認(rèn)密鑰
? ? if (blank_check == 0xFF)
? ? {
? ? ? ? write_key(default_key);
? ? }
}
/**
?* 主函數(shù)
?* @note 測試加密芯片的基本功能
?*/
void main(void)
{
? ? unsigned char test_data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; ?// 測試數(shù)據(jù)
? ? unsigned char read_data_buf[8]; ?// 存儲讀取的數(shù)據(jù)
? ? unsigned char i; ?// 循環(huán)變量
? ? unsigned char result; ?// 操作結(jié)果
? ? // 初始化加密芯片
? ? crypto_chip_init();
? ? // 測試寫入數(shù)據(jù)
? ? result = write_data(0x00, test_data, 8);
? ? if (result == 0)
? ? {
? ? ? ? // 寫入成功,測試讀取數(shù)據(jù)
? ? ? ? result = read_data(0x00, read_data_buf, 8);
? ? ? ? if (result == 0)
? ? ? ? {
? ? ? ? ? ? // 讀取成功,驗證讀取的數(shù)據(jù)是否與寫入的數(shù)據(jù)一致
? ? ? ? ? ? for (i = 0; i < 8; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if (test_data[i] != read_data_buf[i])
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? // 數(shù)據(jù)不一致,處理錯誤
? ? ? ? ? ? ? ? ? ? // 實際應(yīng)用中可以添加錯誤處理代碼
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? else if (result == 1)
? ? ? ? {
? ? ? ? ? ? // 地址或長度錯誤
? ? ? ? }
? ? ? ? else if (result == 2)
? ? ? ? {
? ? ? ? ? ? // CRC校驗錯誤
? ? ? ? }
? ? }
? ? while (1); ?// 程序循環(huán)
}
贊(3) 打賞
分享到

我愛單片機博客

單片機開發(fā)、學(xué)習(xí)、交流與分享博客!

關(guān)于我們聯(lián)系我們

登錄

找回密碼

注冊