前言
做嵌入式开发的同学知道,嵌入式片上内存RAM容量一般是比较小的,而经常需要对Flash里面的大文件做哈希校验,例如一个RAM 256KB的MCU,需要对512KB的Flash文件做MD5、SHA256检验,这可怎么办,相信难道了不少工程师。再物联网领域,这类情况最常见的无非在设备升级(OTA)环节,因为OTA过程一般需要对文件的完整性、合法性(签名)进行验证,下面说下如何使用mebdtls工具处理这类情况。
好使但不太建议的方法
如果对这类流式处理不熟悉的同学,估计首先会想到一个方法:在制作原文件的时候,把大文件进行拆分成若干个小数据包,每个小数据包后面追加本段的校验结果(例如MD5)。这样,接收方就能分片进行MD5校验,以解决内存问题。的确,这个方法可以解决这个问题,但是有几个弊端:
- 需要额外的算法制作文件包,耗时
- 增加了额外的数据,占用更多带宽,丢包的风险增加(数据包越大,丢包风险越高)
- 校验、解密过程中,效率较低,相当于执行了N次算法
对大文件使用加密解密类算法,再探MD5(校验)
其实,算法设计之初,就应该考虑这个问题,设计这些算法的都是行业大咖,怎么可能没考虑到这一层面,于是,下面给出MD5分片处理的方法(其他算法同理,不一一例举)
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#include <stdio.h>
#define mbedtls_printf printf
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif
#if defined(MBEDTLS_MD5_C)
#include "mbedtls/md5.h"
#endif
#if !defined(MBEDTLS_MD5_C)
int main( void )
{
mbedtls_printf("MBEDTLS_MD5_C not defined.\n");
return( 0 );
}
#else
int main( void )
{
int i;
unsigned char digest[16];
char str1[] = "Helloworld1";
char str2[] = "Helloworld2";
mbedtls_printf("\n MD5('%s%s') = ", str1, str2);
/**
* MD5分片处理核心函数
* */
int ret;
mbedtls_md5_context ctx;
mbedtls_md5_init(&ctx);
ret = mbedtls_md5_starts_ret(&ctx);
ret = mbedtls_md5_update_ret(&ctx, (unsigned char*) str1, strlen(str1));
ret = mbedtls_md5_update_ret(&ctx, (unsigned char*) str2, strlen(str2));
ret = mbedtls_md5_finish_ret(&ctx, digest);
mbedtls_md5_free(&ctx);
/**************************************************************************/
for( i = 0; i < 16; i++ )
mbedtls_printf( "%02x", digest[i] );
mbedtls_printf( "\n\n" );
#if defined(_WIN32)
mbedtls_printf( " Press Enter to exit this program.\n" );
fflush( stdout ); getchar();
#endif
return( MBEDTLS_EXIT_SUCCESS );
exit: return (ret);
}
#endif /* MBEDTLS_MD5_C */
运行得出结果:
与实际结果进行对比: