ET199(http://www.jansh.com.cn/product/detail.php?cid=13)采用安全强度最高的智能卡芯片,硬件不能被复制,多重安全级别,并且集成了16位CPU,8KRAM,64K存储空间等模块。运行在ET199内部的程序是使用C51语言进行开发的,本方案示例主要用到MD5计算的内部系统函数,通过内部MD5计算对程序添加校验。方案的测试过程需要首先在ET199加密锁中预先设置公私钥文件和一个可执行文件,详见ET199内部文件配置。

方案原理说明:

本方案示例,通过调用内部系统函数,将源程序除去最后16个字节二进制文件做MD5散列运算,将运算的结果保存到二进制文件的最后16个字节中,每次程序运行时,程序通过加密锁内部MD5计算对自身做MD5运算校验,如果程序被修改了,那么运算之后的结果一定与之前的的校验结果不相同,则说明程序被改动过,如果运算之后的结果与之前保存的结果相同,那么说明源程序没有被修改过。

方案示例:

本说明文档中仅列举核心代码或函数,详细的代码设计,请参看方案源代码。所有操作均在插有ET199加密锁的状态下完成,并且加密锁属性都是出厂默认设置。本方案示例将需要重复使用的枚举ET199、打开ET199等函数封装到一个函数:

DWORD  CMD5FileCheckDlg::OpenDog(ET_CONTEXT* pETC)

{

DWORD dwRet;

DWORD dwCount;

ET_CONTEXT *pContext;

//===============================

//枚举ET199并返回数量

dwCount = 0;

dwRet   = ETEnum(NULL,&dwCount);

if(dwRet != ET_E_INSUFFICIENT_BUFFER && dwRet != ET_S_SUCCESS)     return dwRet;

//根据数量分配内存用于存储CONTEXT结构数组

pContext = new ET_CONTEXT[dwCount];

//清0缓冲区

memset(pContext,0,sizeof(ET_CONTEXT)*dwCount);

//使用分配的缓冲区重新进行枚举

dwRet=ETEnum(pContext,&dwCount);

if(dwRet != ET_S_SUCCESS) return dwRet;

if(dwCount == 0) return ET_E_KEY_REMOVED;

//打开ET199

dwRet = ETOpen(&pContext[0]);

if(dwRet != ET_S_SUCCESS) return dwRet;

* pETC = pContext[0];

return ET_S_SUCCESS;

}

将执行过程封装到函数:

DWORD CMD5FileCheckDlg::ExecuteDog(ET_CONTEXT* pETC, LPCSTR lpszFileID, BYTE* pInbuf, int len_In, BYTE* pOutbuf, int* len_Out)

{

DWORD          leng;

DWORD          dwRet;

BYTE           tmpbuf[256];

// =================

//检查加密锁句柄

if(pETC->hLock == INVALID_HANDLE_VALUE)  return -1;

//

memset(tmpbuf, 0, sizeof(tmpbuf));

//执行芯片中的1000可执行文件

dwRet = ETExecute(pETC, lpszFileID, pInbuf, len_In, pOutbuf, *len_Out, &leng);

if(dwRet != ET_S_SUCCESS) return dwRet;

//tmpbuf[0]是芯片中代码执行的返回值

if(tmpbuf[0] != 0) //ET_SUCCESS

{

return tmpbuf[0];

}

//返回数据

*len_Out = leng;

return 0;

}

以上两个函数的封装,仅是为了方便起见。

一、运行MD5FileMake.exe,该程序实现对某一程序添加MD5校验

图1

选择需要添加检验的源程序MD5FileCheck.exe,单击“MD5固化文件”,会在相应目录下产生一个校验文件ChangeLess.exe。

//校验MD5

BOOL CMD5FileCheckDlg::MakeFileMD5(char* pFilePath)

{

HANDLE  handle;

long    file_len;

BYTE*   pbuf;

DWORD   bytesread;

//==================

//打开文件

handle=CreateFile(pFilePath,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

if(handle == INVALID_HANDLE_VALUE)

{

return FALSE;

}

file_len = GetFileSize(handle, 0);

pbuf = (BYTE*)malloc(file_len);

ReadFile(handle, pbuf, file_len, &bytesread, 0);

CloseHandle(handle);

GetTrueMD5(pbuf, file_len-16, pbuf+file_len-16);

handle=CreateFile("ChangeLess.exe", GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);

if(handle == INVALID_HANDLE_VALUE)

{

free(pbuf);

//

return FALSE;

}

WriteFile(handle, pbuf, file_len, &bytesread, 0);

CloseHandle(handle);

free(pbuf);

return TRUE;

}

二、二进制文件的比较

源程序二进制文件和检验程序二进制文件的比较如下图所示,其中图1是源程序MD5FileCheck.exe最后16个字节的二进制,图3是检验文件ChangeLess.exe的最后16字节的二进制。

图2

图3

三、运行添加校验的程序ChangeLess.exe

图4

该程序实现对自身的检验,单击“校验文件MD5值”如果源程序没有被修改过,运行检验程序时会提示“文件完整性检验OK”。

图5

如果源程序被修改过,运行校验文件是则会提示“文件完整新检验ERR”。

图6

//校验MD5

BOOL CMD5FileCheckDlg::CheckFileMD5(char*  pFilePath)

{

HANDLE  handle;

long    file_len;

BYTE*   pbuf;

DWORD   bytesread;

BYTE    TrueMD5[16];

BYTE    FileMD5[16];

//==================

//打开文件

handle=CreateFile(pFilePath,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

if(handle == INVALID_HANDLE_VALUE)

{

return FALSE;

}

file_len = GetFileSize(handle, 0);

pbuf = (BYTE*)malloc(file_len);

ReadFile(handle, pbuf, file_len, &bytesread, 0);

CloseHandle(handle);

memset(TrueMD5, 0, sizeof(TrueMD5));

GetMD5(pbuf, file_len-16, TrueMD5);

memcpy(FileMD5, pbuf+file_len-16, 16);

free(pbuf);

if(memcmp(FileMD5, TrueMD5, 16) == 0) return TRUE;

else  return FALSE;

}

//MD5计算

void  CMD5FileCheckDlg::GetMD5(BYTE* pbuf, long len,  BYTE* pOutMD5)

{

int            leng;

DWORD          dwRet;

ET_CONTEXT     etc;

BYTE           tmpbuf[1+128];

BYTE           md5[16];

// =================

//打开加密锁

if(OpenDog(&etc) != ET_S_SUCCESS)

{

AfxMessageBox("打开加密锁失败!");

return;

}

//校验PIN码

if(ETVerifyPin(&etc, ET_DEFAULT_USER_PIN, ET_USER_PIN_LEN, ET_USER_PIN) != ET_S_SUCCESS)

{

AfxMessageBox("加密锁校验用户PIN码失败!");

return;

}

//文件128字节块xor

XorBlock128(pbuf, len,  tmpbuf+1);

//执行芯片中的1000可执行文件,功能号:MD5运算

tmpbuf[0] = Func_MD5;

leng  = sizeof(tmpbuf);

dwRet = ExecuteDog(&etc, "1000", tmpbuf, sizeof(tmpbuf), tmpbuf, &leng);

if(dwRet == 0 && tmpbuf[0] == 0)

{

//返回数据

memcpy(md5, tmpbuf+1, 16);

}

else

{

AfxMessageBox("执行加密锁内算法失败!");

//关闭加密锁

ETClose(&etc);

return;

}

memcpy(pOutMD5, md5, 16);

//关闭加密锁

ETClose(&etc);

return;

}

方案特点:

本加密方案的设计,首先通过对一个文件添加MD5校验,然后每次运行程序师通过该文件自身做一次MD5的校验,如果程序有一点的“风吹草动”,那么校验值一定同之前存储的校验值是不一样的,从而可以判断文件是否被修改过,以此可以有效验证源程序是否被破解者恶意篡改。

ET199加密方案——文件MD5校验相关推荐

  1. java 文件md5校验_Java 获取 文件md5校验码

    讯雷下载的核心思想是校验文件的md5值,两个文件若md5相同则为同一文件. 当得到用户下载某个文件的请求后它根据数据库中保留的文件md5比对出拥有此文件的url, 将用户请求挂接到此url上并仿造一个 ...

  2. Python实现文件md5校验

    Linux下校验文件MD5值,最简单的方法就是执行md5sum命令 md5sum filename 原本打算用subprocess调用系统命令来获取md5值, [python] view plainc ...

  3. Linux中文件MD5校验

    md5sum命令用于生成文件的md5数字摘要,并可以验证文件内容是否发生了改变,间接地还可以检验两个文件内容是否完全相同.因为md5sum是读取文件内容来计算校验码的,因此只能验证文件内容,而无法验证 ...

  4. Linux文件MD5校验

    1.进入操作系统Linux中的/root目录,找到test.txt文件,并使用md5sum工具来计算出该文件的md5值,并将计算该文件md5的命令的字符串作为flag进行提交: Flag:md5sum ...

  5. 生成文件md5校验码可满足大于2G情况

    对于文件生成md5校验码,在实际开发中用处很大,有利于比较服务器上是否已经存在该文件,哪怕文件名不一致也无所谓. 由于存在超大文件,经过从网上查找,得到两种方法,一种是利用MappedByteBuff ...

  6. Linux查看文件MD5校验码命令,讲解Linux中校验文件的MD5码与SHA1码的命令使用

    md5sum 用法:md5sum [选项]... [文件]... 显示或检查 MD5(128-bit) 校验和. 若没有文件选项,或者文件处为"-",则从标准输入读取. -b, - ...

  7. python读取大文件md5校验性能优化比较

    with open(filename, "rb") as f: f.read() 读取整个文件,通常将文件内容放到一个字符串变量中: f.readline() 次读取一行内容: f ...

  8. MD5校验(checksum)

    MD5校验(checksum)是通过对接收的传输数据执行散列运算来检查数据的正确性. 简介 一个散列函数,比如 MD5,是一个将任意长度的数据字符串转化成短的固定长度的值的单向操作.任意两个字符串不应 ...

  9. android MD5校验码的生成与算法实现

    android MD5校验码的生成与算法实现 在Java中,java.security.MessageDigest (rt.jar中)已经定义了 MD5 的计算,所以我们只需要简单地调用即可得到 MD ...

最新文章

  1. 走向ASP.NET架构设计-第六章-服务层设计(中篇)
  2. HTML表中的自动换行
  3. rock-paper-scissors
  4. Dataset之Rotten Tomatoes:Rotten Tomatoes影评数据集简介、下载、使用方法之详细攻略
  5. POJ 1789248512583026
  6. freetextbox java_FreeTextBox3.2.2下载及使用详解(图)
  7. linux错误代码0x8008005,利用Windows10自带Linux学习(附带:0x8007019e错误解决方法)...
  8. Unity客户端开发优化要点
  9. 随想录(工作后的一点思考)
  10. 请求之前~HttpHandler实现媒体文件和图像文件的盗链
  11. Corel Painter 2022 for Mac(初学者可驾驭的绘画软件)
  12. 64位window 7安装2TB以上大容量硬盘
  13. 数学建模学习(41):单因素方差分析
  14. C++ 函数模板 实例化和具体化
  15. html导出excel换行,ASP.NET 导出到Excel时保留换行的代码
  16. javaFX实现登录界面并跳转
  17. 怎么调整图片的尺寸大小?
  18. C# 判断本机是否安装Excel及多版本安装?获取Excel进程信息和打开Excel应用软件
  19. 一个http请求的详细过程
  20. 学习大数据有推荐的么

热门文章

  1. type-c接口显示器方案
  2. 从u盘引导进入linux6,使用U盘启动安装U盘内linux6.1
  3. make XXX_defconfig 分析
  4. 2019腾讯游戏客户端面试
  5. word模板填充数据
  6. 汉字Collection
  7. C++函数模板和模板函数的区别
  8. 计算机管理home,电脑home键是什么意思
  9. 古龙冰洞超级计算机指令,龙族幻想古龙冰洞异闻攻略 古龙冰洞指令介绍
  10. 台式电脑显示屏显示html,台式机电脑屏幕突然出现彩色条纹原因及解决方法