本文共 2986 字,大约阅读时间需要 9 分钟。
OTA升级包的加解密:从零开始
最近接手一个项目,需要在产品上新增一个OTA升级功能。一开始我以为就是从服务器下载一个程序到本地执行,弹出提示框重启就搞定了。没想到这个过程还涉及很多细节,比如加解密、解压缩、文件校验等等。为了把这些功能加上去,我花了不少时间,现在把这段时间的收获记录下来,也算是对这段工作做了一个总结。
因为涉及的内容太多,所以打算分几篇博文一一叙述。今天就先从文件加解密说起。
OTA升级包的加解密在OTA升级过程中,为了保护产品不受恶意攻击,我们需要对升级包进行加密和解密操作。当我们从服务器下载升级包时,需要先解密,确保文件没有被窃取或植入恶意代码。
那么如何实现加解密操作呢?自己写算法虽然可以,但安全性可能不高。于是想找一个开源库来直接使用。经过搜索,找到了openssl这个库,里面正好有我们需要的加解密功能。
openssl库的编译在使用openssl库的加解密功能之前,首先需要编译库文件。进入指定目录后,依次执行以下命令:
./config./make all
编译完成后,会在目录下生成几个重要的文件,其中libcrypto.a和libssl.a是我们需要的库文件。
openssl头文件说明编译完成后,我们需要编写测试代码来验证加解密的可用性。我们选择使用aes加密算法,头文件位于crypto/aes/目录下。
AES加密文件测试代码编写Makefile文件,用于编译测试代码。编写步骤如下:
touch otaPack.c编写Makefile文件:CC=ccCFLAGS=-O -I../crypto/aes -I../includeOTAPACK_OBJS = otaPack.o ../libcrypto.a ../libssl.a
call:otaPack: $(OTAPACK_OBJS)$(CC) $(CFLAGS) -o $@ $(OTAPACK_OBJS)clean:/bin/rm -f *.o otaPack
编写文件加密和解密函数:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <aes.h>
int main(int argc, char *argv[]) {if (argc < 5) {printf("参数错误!!!\r\n");exit(-1);}char file_in[64];char file_out[64];int mode = -1;char passwd[16+1];if (argv[1] == '-') {if (argv[1][1] == 'd') {mode = AES_DECRYPT;} else if (argv[1][1] == 'e') {mode = AES_ENCRYPT;}}strcpy(file_in, argv[2]);strcpy(file_out, argv[3]);strcpy(passwd, argv[4]);
printf("mode : %d. \r\n", mode);printf("file_in: %s. \r\n", file_in);printf("file_out: %s. \r\n", file_out);printf("passwd: %s. \r\n", passwd);if (mode == AES_DECRYPT) { _decrypt_file(file_in, file_out, passwd);} else if (mode == AES_ENCRYPT) { _encrypt_file(file_in, file_out, passwd);}return 0; }
void _encrypt_file(char *file_in, char *file_out, char *passwd) {FILE *fp_in = fopen(file_in, "r+");FILE *fp_out = fopen(file_out, "w+");unsigned char iv[AES_BLOCK_SIZE];int position = 0;int bytes_read, bytes_write;AES_KEY aes_key;AES_set_encrypt_key(passwd, 128, &aes_key);while (1) {memset(iv, 0, AES_BLOCK_SIZE);bytes_read = fread(indate, 1, AES_BLOCK_SIZE, fp_in);if (bytes_read < AES_BLOCK_SIZE) break;AES_cfb128_encrypt(indate, outdate, bytes_read, &aes_key, iv, &position, AES_ENCRYPT);bytes_write = fwrite(outdate, 1, bytes_read, fp_out);}fclose(fp_in);fclose(fp_out);}
void _decrypt_file(char *file_in, char *file_out, char *passwd) {FILE *fp_in = fopen(file_in, "r+");FILE *fp_out = fopen(file_out, "w+");unsigned char iv[AES_BLOCK_SIZE];int position = 0;int bytes_read, bytes_write;AES_KEY aes_key;AES_set_encrypt_key(passwd, 128, &aes_key);while (1) {memset(iv, 0, AES_BLOCK_SIZE);bytes_read = fread(outdate, 1, AES_BLOCK_SIZE, fp_in);if (bytes_read < AES_BLOCK_SIZE) break;AES_cfb128_encrypt(outdate, decryptdate, bytes_read, &aes_key, iv, &position, AES_DECRYPT);bytes_write = fwrite(decryptdate, 1, bytes_read, fp_out);}fclose(fp_in);fclose(fp_out);}
编译并测试代码:make all
测试文件:touch test.zip test./otaPack -e test.zip encrypt.zip 123456./otaPack -d encrypt.zip decrypt.zip 123456
测试结果表明,解密后的文件无法正常解压。这是因为密码长度不够,aes算法需要16个字符。重新设置16位密码进行测试,发现能够正常解压。
总结:通过这段时间的学习和测试,成功实现了OTA升级包的加解密功能。接下来需要将解密代码移植到开发板上,具体实现会有更多细节需要处理。
转载地址:http://fjnq.baihongyu.com/