AES加密原理和AOE工程实践

在AI业务的开发的过程中,我们常常需要对模型文件进行加密。
我们从以下几个方面来说一说AES的加密原理以及AOE里的工程实践。

  • 常见的加密算法
  • AOE对模型加密需求的思考
  • AES的加密原理
  • AOE工程实践-AES和AOE的结合

常见的加密算法

常见的加密算法,主要分为两种:
对称加密,采用单密钥的加密方法,同一个密钥可以同时用来加密和解密。常用的对称加密算法有DES,3DES,AES等。
非对称加密,需要两个密钥来进行加密和解密,这两个密钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。常用的非对称加密算法有RSA,Elgamal,ECC等。

用个比喻来理解一下这2种不同的加密方式:
对称加密:假设有一个密码箱,A设置了一个密码锁好箱子,B知道这个密码以后,输入这个密码就可以打开箱子,这个密码就是秘钥,A和B使用相同的密码。
非对称加密:有一把锁和一把唯一的钥匙,A用锁把箱子锁好,B只有用这把钥匙才能打开这个箱子。这把锁就可以理解为公钥,是公开的。这把钥匙可以理解为私钥,是不公开的,是不在网络里传输的,只有私钥的拥有者才能打开这个箱子。

简单比较一下他们的差异:

功能特性 对称加密 非对称加密
密钥特征 加密方和解密方使用同一个密钥 加密方和解密方使用不同的密钥
加密效率 效率高,速度快 速度慢
密钥安全性 传输过程中容易泄漏 安全性高

在实际的应用中,一般都是对称加密和非对称加密算法相结合,这样既可以保证加密的速度,也可以保证秘钥传输的安全性。以AES和RSA结合为例,有一种通用的做法,在向服务器发送一段数据信息的时候,先用AES算法对数据进行加密,再使用服务器的RSA公钥对AES的密钥进行加密后,最后数据和加密后的AES KEY上传到服务器。这样只有知道了服务器RSA私钥,才能解开得到正确的AES KEY,最终用AES KEY才能解开这段密文。

对模型加密需求的思考

深度学习中,模型训练是最关键和最有挑战性的。不仅需要有丰富的经验定义出合适的模型,还需要有大量的数据集,经常需要3-4天才能训练出一个模型。出于对知识产权的保护或者商业保护,我们常常需要对训练出来的模型文件进行加密。思考一下我们对模型加密的需求:速度要快,安全性要高,不依赖服务器的情况下本地也能加密解密。另外还需要有一个摘要算法来校验,保证模型的完整性。我们初步考虑使用AES算法,摘要算法使用MD5。下面我们来看看AES算法是如何工作的。

AES的加密原理

AES,Advanced Encryption Standard,是对称加解密算法的最经典算法之一,标准的AES加密位宽是每个块128bit,密钥分为128bit,192bit,256bit,这就是通常说的AES-128,AES-192,AES-256。我们从几个方面来具体了解一下AES加密。

  • AES加密过程
  • AES解密过程
  • AES加密模式和Padding
  • AOE加密组件为何选择AES加密算法

AES加密过程

AES算法主要有四种操作处理,分别是轮密钥加层(Add Round Key)、字节代换层(SubBytes)、行位移层(Shift Rows)、列混淆层(Mix Columns)。AES加密的过程,并不是明文和密钥简单运算一下。以AES128为例,它要执行10轮加密。实际的执行过程是这样的:

  • 第0轮,把原始数据和原始密钥进行异或;
  • 第1-9轮,执行SubBytes,ShiftRows,MixColumns,AddRoundKey的完整流程;
  • 第10轮,执行SubBytes,ShiftRows,不执行MixColumns;
static void Cipher(state_t* state, const uint8_t* RoundKey)
{uint8_t round = 0;// Add the First round key AddRoundKey(0, state, RoundKey); // There will be Nr rounds.for (round = 1; round < Nr; ++round){SubBytes(state);ShiftRows(state);MixColumns(state);AddRoundKey(round, state, RoundKey);}// The last round is given below.SubBytes(state);ShiftRows(state);AddRoundKey(Nr, state, RoundKey);
}

SubBytes

SubBytes,字节混淆。AES处理的最小单位是8位无符号整数,正好可以对应伽罗瓦域GF(28)上的一个元素,混淆的方法是先计算每一个字节在GF(28)的乘法逆元,目的是提供非线性变换。再对结果做一次仿射变换,目的是改变掉伽罗瓦域的结构。

因为GF(28)中的每一个元素,都可以用多项式来表示:a7x7 + a6x^6 + a5x^5 + … + a1x + a0,其中a7-a0,只能从GF(2)中取值。所以对某个字节计算逆元,可以转换成求多项式的逆元。以0xac为例,写成二进制是10101100,写成多项式就是x^7 + x^5 + x^3 + x^2,计算逆元就变成计算这个多项式的逆元。得到多项式逆元以后,我们可以把它转换成16进制的值。仿射变换简单理解,就是通过某个计算,得到一个新的值。具体的计算方法,我们就不多介绍了。实际中,可以用查表法来完成这一步骤。

因为这些步骤得到的每个字节的值是固定对,所以我们可以计算出GF(2^8)中每个元素对应的值,最后我们可以得到了一张16*16的查找表,叫做Substitution-box,简称sbox或者s盒。对于每个输入的字节,例如输入字节的十六进制形式位0xAB,则在表格的纵坐标中定位A,再在纵坐标中定位B,最后使用s(a,b)的值来替换这个字节的值。通过这个步骤,我们的输入数据D1-D16,变成了S1-S16。

ShiftRows

将16个S盒变换后的字节,从上往下、从左到右地写成了一个矩阵。第一行保持不动,第二行向左移动1格,第三行向左移动2格,第四行向左滑移动3格,如图所示:

MixColumns

用下面这个矩阵和ShiftRows之后的结果相乘。列混淆操作混淆了输入矩阵的每一列,使输入的每个字节都会影响到4个输出字节。这部分包含了矩阵乘法,伽罗瓦域内加法和乘法的相关知识。总的来说,ShiftRows和MixColumns两步骤为这个密码系统提供了扩散性。

左边矩阵中的01,02,03对应的多项式分别是1,x,x+1。假设右边矩阵输入全部是0x11,对应的多项式是x4+1。使用GF(28)中的加法和乘法,计算过程如下:

C(i) = (01 + 01 + 02 + 03) * 11
=(1 + 1 + x + x + 1) * (x^4 + 1)
= 1 * (x^4+1)
= x^4 + 1

乘法结果有两种情况:

  • 最高次幂没有超过x^7,这时的结果就是相乘之后的结果。
  • 如果超过了x^8,我们就要把这个多项式对P(x)取模,其中P(x) = x^8 + x^ 4 + x^3 + x + 1。

AddRoundKey

在上面的几个步骤中,我们是对输入对数据进行混淆。AddRoundKey每执行一次叫做一轮加密,这一步会执行多次。简单来说就是把密钥和混淆后的结果进行xor运算,但在每一轮使用的密钥都是根据上一轮的密钥变换而来的。
轮密钥是如何生成的?以AES-128为例,密钥一共16个字节,我们把它们4字节分成一组,计作W0-W3。在每一轮中,通过函数g变换和固定的公式,可以得到这一轮的密钥。一共生成44个W(i),每4个为一组一共生成11个密钥k0-k10,其中k0是原始密钥。轮数依赖于密钥长度,16字节密钥对应10轮,24字节密钥对应12轮,32字节对应14轮。具体的计算过程我们就不再描述了,看起来简单,实际上背后有大量的数学知识和研究作为支撑。

AES解密过程

对于解密,就是把加密的过程反过来,如下面的参考代码,其中的InvShiftRows,InvSubBytes,InvMixColumns分别是对应算法的逆运算。

static void InvCipher(state_t* state, const uint8_t* RoundKey)
{uint8_t round = 0;// Add the First round key AddRoundKey(Nr, state, RoundKey); // There will be Nr rounds.for (round = (Nr - 1); round > 0; --round){InvShiftRows(state);InvSubBytes(state);AddRoundKey(round, state, RoundKey);InvMixColumns(state);}// The last round is given below.InvShiftRows(state);InvSubBytes(state);AddRoundKey(0, state, RoundKey);
}

平常工作中,我们是不推荐自己手写这类成熟专业的加密算法的,很容易写出漏洞或者错误,最终造成严重的安全问题。

加密模式和Padding

AES只能对固定长度的数据进行加密,对于不定长的数据,我们需要把它切分成若干定长的数据,再进行加密解密,这就是我们常说的分组加密。分组加密有ECB,CBC,CFB,OFB这几种加密模式,我们介绍一下ECB模式和CBC模式,以及Padding的对加密解密的影响。

ECB模式
ECB模式又称电子密码本模式(Electronic codebook):ECB是最简单的块密码加密模式,加密前根据加密块大小(如AES为128位)分成若干块,之后将每块使用相同的密钥单独加密,解密同理。具体见下图:

(图片来自维基百科)

ECB模式由于每块数据的加密是独立的,所以可以分块进行并行加密或者解密。它的缺点是相同的明文块会被加密成相同的密文块,所以这种方法在某些条件下安全性相对不是很高。

CBC模式
CBC模式又称密码分组链接(Cipher-block chaining):CBC模式对于每个待加密的密码块在加密前会先与前一个密码块的密文异或然后再用加密器加密,第一个明文块与一个叫初始化向量IV的数据块异或。具体见下图:

完成加密或解密后会更新初始化向量IV,CBC模式安全性更高,但由于对每个数据块的加密依赖前一个数据块的加密,所以加密是无法并行的。

用一张图来比较看一下ECB和CBC加密的效果,可以发现使用CBC模式分散性和安全性更好。

Padding
在AES加密与解密的过程中,如果需要加密的数据不是16的倍数的时候,需要对原来的数据做填充操作。填充的方式有pkcs7padding/zeropadding/NoPadding等。
我们看看不同的填充方式是如何进行填充的,例设一开始的数据是FF FF FF FF FF FF FF FF FF
PKCS7填充:FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07
Zeros填充:FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00
NoPadding:不填充,需要自己保证数据是16的倍数。

显然,不同的padding对加密与解密是有影响的,所以在加密和解密的时候需要保证padding的方式是一致的。

AOE加密组件为何选择AES加密算法

理论上大部分的算法都是可以破解的,只是有可能需要很长时间的计算才能破解。AES加密算法在目前的计算能力下,直接破解几乎是不可能的。从我们保护模型的目的来看,使用AES-128就可以满足我们的需求。另外,在AES算法被标准化后,很多硬件芯片和软件工具都实现了对AES的支持,使用AES算法来加密解密,性能也非常高。综合考虑了性能和安全性,我们使用了AES-128/CBC算法来做加密,并在这个基础上结合MD5摘要算法,对文件的完整性做校验。

AOE工程实践-AES和AOE的结合

我们从以下几个方面来看看AOE的加密组件是如何实现的:

  • AOE的加密文件结构
  • AOE的加密过程
  • AOE的解密过程
  • AOE加密组件的使用

AOE的加密文件结构
我们设计了一个新的文件结构,加密后的文件结构如下:

1byte 4bytes 16bytes nbytes
Version Code File Length File MD5 加密后的模型文件数据

我们在加密后的模型数据前,增加了一个head,head一共21个byte:

  • Version Code, 1byte,表示模型的加密方法索引,从1开始依次递增。
    如果模型加密的版本号 > sdk能支持解密的版本号,则解密失败,需要更新sdk。
  • File Length,4bytes,表示模型文件的原始长度。
  • File MD5,16bytes,表示模型文件的原始MD5,解密出的模型文件MD5需要和这个MD5一致。
  • 加密后的模型文件数据,nbytes,根据不同的加密算法,得到的数据长度也是不一样的。

AOE第一版的加密算法(Version Code为1),加密和解密都可以在本地完成,不需要和服务器进行交互,对应的加密解密过程如下:

AOE的加密过程
1,采用AES-128/CBC/No Padding对模型加密。
2,给文件加上21字节的文件头,Version Code + File Length + File MD5。
3,使用文件MD5和加密后的模型做简单的Swap操作,把MD5的16个byte,分别和模型加密后的前16k数据的第一个字节进行交换。

使用AES方式加密,我们面临一个问题,密钥很容易泄漏。为了解决这个问题,首先我们选择了CBC模式,其次我们对加密后对文件做了一下混淆。这样即使别人知道了我们的AES KEY,如果不知道我们加密组件里的混淆方式,因为是CBC模式加密,所以他也是无法解开我们加密后的文件的。

AOE的解密过程
解密的过程和加密的过程是相反的,具体的算法如下:
1,读取加密文件的前21个字节,得到Version Code,文件长度。
2,读取加密数据的前16k数据的第一个字节,和head里的MD5字段进行swap,经过这一步以后,可以得到文件的MD5和原始的加密后的数据。
3,采用AES-128/CBC/No Padding对模型解密,得到解密文件以后使用文件MD5来检验文件的完整性。

AOE加密组件的使用
AOE加密组件,提供了C版本和JNI封装,JAVA版本和Python版本,在端上我们更推荐使用C版本,在服务器后台我们推荐使用JAVA版本或者Python版本来做一些批量的工作。我们提供了解密到内存和文件两种方式,我们更推荐直接解密到内存里,这样不会生成临时文件,安全性更高。

思考和总结

密码学对大部分人来说是非常专业的,需要大量的数学知识,加密和破解也一直是矛和盾的关系。目前AOE SDK站在成熟算法的肩膀上,结合了AES算法对模型进行了加密,后续我们还会扩展一些新的加密算法,给大家参考和使用。欢迎大家来使用和提建议。

https://github.com/didi/aoe
(AoE (AI on Edge,终端智能,边缘计算) 是一个终端侧AI集成运行时环境 (IRE),帮助开发者提升效率)

添加小助手微信进入AOE开源交流群

AES加密原理和AOE工程实践相关推荐

  1. AOE工程实践-银行卡OCR里的图像处理

    AOE工程实践-银行卡OCR里的图像处理 作者:杨科 近期我们开发了一个银行卡 OCR 项目.需求是用手机对着银行卡拍摄以后,通过推理,可以识别出卡片上的卡号. 工程开发过程中,我们发现手机拍摄以后的 ...

  2. AOE 工程实践-银行卡 OCR 里的图像处理

    [公众号回复 "1024",免费领取程序员赚钱实操经验] 上次分享了滴滴开源的 AOE 开源项目,很多人都没看明白,这个 AOE 到底是干什么呢?应该怎么用?所以,今天给大家带来一 ...

  3. MD5加密原理和Java实现

    MD5加密算法为现在应用最广泛的哈希算法之一,该算法广泛应用于互联网网站的用户文件加密,能够将用户密码加密为128位的长整数.数据库并不明文存储用户密码,而是在用户登录时将输入密码字符串进行MD5加密 ...

  4. DES/3DES/AES加密及区别

    DES 1977年1月,美国政府颁布:采纳IBM公司设计的方案作为非机密数据的正式数据加密标准(DES Data Encryption Standard) . 目前在国内,随着三金工程尤其是金卡工程的 ...

  5. 什么标准规定了aes加密_高级加密标准(AES)分析

    原标题:高级加密标准(AES)分析 0×00 前言 在密码学中,block(分组)密码的工作模式被广泛使用,使用同一个分组密码密钥对很多称之为块的数据加密,在优于很多诸如RSA.ECC密码的性能的情况 ...

  6. SM4分组加密算法原理和c语言实现

    一.前言 在之前的文章中介绍了<SM3国密杂凑值算法的原理和c语言实现>,这篇文章主要是用c语言撸一个SM4分组加密算法. 随着信息安全的普及以及等级保护等安全政策落地,国密算法越来越频繁 ...

  7. 从入门到深入:移动平台模型裁剪与优化的技术探索与工程实践

    可以看到,通过机器学习技术,软件或服务的功能和体验得到了质的提升.比如,我们甚至可以通过启发式引擎智能地预测并调节云计算分布式系统的节点压力,以此改善服务的弹性和稳定性,这是多么美妙. 而对移动平台来 ...

  8. 计算机网络原理和OSI模型与TCP模型

    计算机网络原理和OSI模型与TCP模型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.计算机网络的概述 1.计算机网络的定义 计算机网络是一组自治计算机的互连的集合 2.计算机 ...

  9. RAS RC4 AES 加密 MD5

    RAS RC4 AES 加密 MD5 这两者唯一的相同点是设计者中都包含了MIT的Ron Revist教授. RSA是公钥密码算法,优点:不用事先通过秘密信道传递密钥,可以用于数字签名.缺点:速度慢 ...

最新文章

  1. java如何恢复成eclipse项目,清理一下垃圾,Eclipse里面的项目全部不见了,怎么恢复...
  2. eclipse 环境下 FreeMarker 编辑器插件
  3. MySQL Packet for query is too large
  4. python零基础入门教程学习要多久-廖雪峰python教程要学多久-零基础学Python需要多久...
  5. 对比tensorflow查看打印输出张量Tensor的两种方法(急切执行tf.enable_eager_execution()和tf.Session.run())
  6. 开源的.NET运行剖析器nprof简单使用指引
  7. CSS核心技术详解-核心概念
  8. 小学学校计算机教室使用计划,小学电脑室工作计划
  9. php-7.1.0,PHP 7.4.0 Alpha 1 v7.4.0 官方最新版
  10. python读取txt文件每一行存为列表,从txt文件中读取一定数量的行,并以python方式转换为list...
  11. 12家无人驾驶公司新进展:驾照怕白考了!
  12. Linux生成随机数字和字符串
  13. rtsp,rtp,gb28181直接转化为html5播放(二)
  14. listview与adapter用法
  15. vmware10中开启Intel VT-x
  16. How to build UDK2015?
  17. VMware 11.0 简体中文版|附永久密钥
  18. python snownlp了解_python中snownlp情感分析简易的demo分享
  19. “代码雨”纯HTML源码实现及效果
  20. python求15 17 23 65 97的因数_pythonlearning

热门文章

  1. STM32开发笔记111:移植W5500驱动程序
  2. Creo9.0 特征的成组
  3. 二、18【设计模式】之迭代器模式
  4. Facebook的激励标语
  5. Leetcode编程C++之1106. 解析布尔表达式
  6. 满满干货!英语六级的高分之路
  7. python列表可变吗_Python 可变和不可变类型
  8. iOS UILabel设置居上对齐,居中对齐,居下对齐
  9. java mongodb gridfs_MongoDB学习笔记之GridFS使用介绍
  10. canva旋转图片 js_js 使用canvas 旋转 图片