常用加密及其相关的概念、简介(对称、AES、非对称、RSA、散列、HASH、消息认证码、HMAC、签名、CA、数字证书、base64、填充)
PS:要转载请注明出处,本人版权所有。
PS: 这个只是基于《我自己》的理解,
如果和你的原则及想法相冲突,请谅解,勿喷。
环境说明
无
前言
在之前,一直是通过生活、工作零零碎碎接触过加密及加密算法相关的信息,但是也只是听说过,并不知道这些算法用处和区别。
最近由于工作安排,需要将Fernet算法实现一版C++的加解密定制程序,由于Fernet组合了许多的基础加密算法,因此在这个地方,对一些常用的基础加密算法做一个总结。
加密是什么?
介绍:把“原始数据”通过某种算法+秘钥变换后,得到了“加密数据”的这个过程叫做加密。从这里也可以看到,对于加密来说,其核心要素就是:加密算法+秘钥。
意义:对于“加密数据”来说,未授权的用户,不能够直接知道“原始数据”的内容。
下面介绍一些常见的加密类别和加密相关配套的其他内容。
对称加密
对称加密是指使用 一个相同秘钥 就能对消息进行加密和解密的加密方法。
对称加密的特点就是使用 一个相同秘钥。
我们常见的对称加密有:XOR、AES等。下面我们来简单分析一下AES加密。
AES加密
高级加密标准(Advanced Encryption Standard,AES),是一种区块加密标准。从它的定义来看,其特点是区块加密,一般来说,我们常见的有AES128和AES256。
例如我们可以用如下的openssl提供的方法进行AES的加解密:
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
//注意这里只是一种cbc加密方法,aes还有很多其他加密方法
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
其实我们从上面的描述来看,就知道AES一般以16字节或者32字节为一组(我们将其定义为区块大小),进行加密。这里就会引申出一个问题,如果我们的数据(最后一组消息)不够一个区块大小,我们应该怎么办?这里提供的常见方案就是做填充。
非对称加密(公钥加密算法)
我们知道,加密一般是用于消息传递,那么如果是对称加密的情况下,要传递的两个事务:加密消息+秘钥。对于对称加密来说,如果我们的秘钥泄露了,就基本上等于明文传递了。因此,有了非对称加密。其实后面很多的加密方法就在平衡 加密消息+秘钥 两个事情。
非对称加密就是有两个秘钥(私钥,公钥),实现1对多的双向通信。其中我们常见的加密方式是:RSA,ECC等。下面,我们尝试简单介绍RSA。
RSA 加密算法
简介(来自于Wikipedia):RSA加密算法是一种非对称加密算法。RSA是由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)在1977年一起提出的。当时他们三人都在麻省理工学院工作。RSA 就是他们三人姓氏开头字母拼在一起组成的。
RSA只从使用的角度来说,只需要了解如下的大致的概念:
- 模数N、公钥指数pubE、私钥指数priE
- 加密:秘文=明文^priE mod N,秘文=明文^pubE mod N
- 解密:明文=秘文^pubE mod N,明文=秘文^priE mod N
从上面来看,私钥= 私钥指数priE + 模数N,公钥= 公钥指数pubE + 模数N。至于公钥,私钥,模数怎么来的,网上已有许多资料,有兴趣可以去看看。
基于openssl的RSA代码节选:
// 生成秘钥,秘钥里面包含了私钥+公钥
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
// 基于公钥和私钥的加解密
int RSA_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int RSA_private_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int RSA_public_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int RSA_private_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
散列函数(Hash function)
介绍:使用 散列函数(md5, sha1, sha256) 对原始数据进行处理,生成散列值(数字摘要)。这些散列函数保证一个输入对应一个输出,并且通过散列值无法得到原始数据输入,因此不属于加密。
此外,如果散列函数不够健壮,可能会出现碰撞的可能性。
意义:由于其不同的数据输入会得到不同的散列值,因此主要用来校验数据的完整性。
基于openssl的常见散列函数代码节选:
//注意,根据官网的描述,如下这些接口已经逐步被弃用,这里只是起示例作用。
int SHA1_Init(SHA_CTX *c);
int SHA1_Update(SHA_CTX *c, const void *data, size_t len);
int SHA1_Final(unsigned char *md, SHA_CTX *c);
//注意,根据官网的描述,如下这些接口已经逐步被弃用,这里只是起示例作用。
int SHA256_Init(SHA256_CTX *c);
int SHA256_Update(SHA256_CTX *c, const void *data, size_t len);
int SHA256_Final(unsigned char *md, SHA256_CTX *c);
其实做过编程的人,对hash这个概念并不陌生。
消息认证码
含义:使用 散列函数+秘钥来生成认证码(MAC)。相较于散列函数来说,对于同一个消息,需要指定的秘钥+散列函数才能够得到最终的认证码。
意义:在散列函数中,原始数据和散列值是绑定的。在一个消息传递系统中,散列函数只解决了数据完整性的问题,并没有解决数据来源是否可靠的问题(可以伪造原始数据+新散列值)。 通过消息验证码,由于有了秘钥的保护, 解决了 散列值+消息 来源不可靠的问题。
基于openssl的消息认证码代码节选:
//这里的evp_md用来描述不同的散列函数
unsigned char *HMAC(const EVP_MD *evp_md, const void *key,
int key_len, const unsigned char *d, size_t n,
unsigned char *md, unsigned int *md_len);
签名算法
下面是签名的一个简单流程:
- 基于公钥加密系统,生成秘钥对(公钥、私钥)。
- 对消息进行数字摘要计算。
- 对数字摘要进行私钥加密,得到数字签名。
- 将信息、数字签名、公钥发给接收者,接收者可以验证:信息的完整性+发送者的身份。
从这里来看,我们可以知道,签名其实和消息认证码具有相同的意义,都能够验证:完整性+发送者的身份。但是由于其原理,导致其应用场景不一致。例如:数字签名由于使用非对称加密,而消息认证码可以认为是使用了对称加密,导致他们的使用场景是不一样的。
CA机构与数字证书
其实从名字上来看,就知道CA机构与数字证书和签名算法相关,为了解决公钥加密系统中,公钥是否可信的问题。下面是它们的一些概念:
- CA(Certificate Authority)是“证书颁发机构”的简称,它是“受信任”的第三方组织,负责验证申请者身份并发放数字证书。
- 数字证书是:特定用户或系统身份信息(如域名、组织名等)+ 该用户公钥 + 由权威机构(CA)签署的数字签名(对用户的信息+公钥) 组成的数据结构。
简单来说,由于我们信任了CA的证书(CA的公钥),我们可以用CA的公钥解密出 数字证书用户的公钥,然后我们用 数字证书用户的公钥 和 数字证书用户加密通信。总的来说,数字证书其实是一个信任链的问题。
Base64 编码
介绍:一种将 二进制数据 编码为 可见字符 的编码方法。简单来说就是用 4个字节的可见字符 代替是 3个字节数据 的编码过程。
意义:可以将二进制数据表达为文本信息,方便后续对二进制数据进行处理。
数据区块填充,PKCS(Public-Key Cryptography Standards)
特别说明,PKCS是一系列公钥密码标准,里面具备很多的内容,其大概有15个标准,分别是pkcs1,pkcs2 ... ... pkcs14,pkcs15
从上面我们知道,现在常用的填充方法是:公钥加密标准(PKCS,Public-Key Cryptography Standards)里面的节选内容。其有很多填充类别,例如:PKCS1-padding节选, PKCS5-padding节选, PKCS7-padding节选,我们这里只讨论pkcs5和pkcs7。(注意,这些标准除了数据填充,还有其他定义内容。)
下面先介绍PKCS5-padding,先定义数据区块大小为SIZE,pkcs5和pkcs7的填充说明,下面以SIZE=8字节举例:
- 要填充7个字节,那么填入的值就是0×07;
- 如果只填充1个字节,那么填入的值就是0×01;
- 数据恰好是8的倍数时还要补8个字节的0×08。
从上面的PKCS5-padding,我们可以知道,这里需要数据区块固定为8字节。如果我们想给其他大小的数据区块做数据对齐,那么PKCS5-padding就不满足要求,因此就有PKCS7-padding的填充方法:
- PKCS7-padding的数据区块大小可以是:1-255字节。
- 其他的,PKCS7-padding填充原理和PKCS5一样。
从上面可知,PKCS7-padding节选包含了PKCS5-padding节选,且适用性范围更加的广泛。
到了这里,我们就能够对AES128或者AES256做基于PKCS7-padding的16字节对齐或者32字节对齐的操作了。
这里的代码实现很简单,这里提供一种方法,大概就是:首先对消息进行强制扩大255字节,然后根据数据区块大小做填充即可,基本可以实现pkcs7填充的原理。
后记
其实,我们从上面的内容来看,能发现一些规律:
由于信任链的存在,因此有了CA机构和数字证书,而数字证书与签名算法相关,而签名算法又与 非对称加密和散列函数强相关。
然后为了实现我们现在常见的加密系统,我们使用了:对称加密、非对称加密、散列函数、消息认证码和base64编码等手段。
参考文献
- 无
打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)
PS: 请尊重原创,不喜勿喷。
PS: 要转载请注明出处,本人版权所有。
PS: 有问题请留言,看到后我会第一时间回复。
常用加密及其相关的概念、简介(对称、AES、非对称、RSA、散列、HASH、消息认证码、HMAC、签名、CA、数字证书、base64、填充)的更多相关文章
- hmac库 密钥相关的哈希运算消息认证码
# -*- coding: cp936 -*- #xiaodeng #python 2.7.10 #HMAC是密钥相关的哈希运算消息认证码,HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一 ...
- 理解 HTTPS 工作原理(公钥、私钥、签名、数字证书、加密、认证)(转)
本文摘录参考: 细说 CA 和证书(主要讲解 CA 的使用) 数字签名是什么?(简单理解原理) 深入浅出 HTTPS 工作原理(深入理解原理) HTTP 协议由于是明文传送,所以存在三大风险: 1.被 ...
- Java使用Cipher类实现加密,包括DES,DES3,AES和RSA加密
一.先看一个简单加密,解密实现 1.1 加密 /** * content: 加密内容 * slatKey: 加密的盐,16位字符串 * vectorKey: 加密的向量,16位字符串 */ publi ...
- Redis散列(Hash)的相关命令
散列 就像一个减配的Redis 内部及其类似Java的Map 内容就是key:value结构 hash类型在面向对象编程的运用中及其适合,因为它可以直接保存编程语言中的实体类关系 增 hset hse ...
- Algorithm:Java加密解密之MAC(消息认证码)
MD5 消息摘要(数字摘要) 它是把一个文本/文件 通过摘要函数(hash函数)计算出一个结果.然后把文本/文件和摘要结果一同发给接受者接受者接收到文件之后,也进行摘要,把两个摘要结果进行对比.如果一 ...
- PHP的几个常用加密函数
在php的开发过程中,常常需要对部分数据(如用户密码)进行加密 一.加密类型: 1.单向散列加密 就是把任意长度的信息进行散列计算,得到固定长度的输出,这个散列计算过程是单向的,即不能对固定长度的输出 ...
- 2019-2-20C#开发中常用加密解密方法解析
C#开发中常用加密解密方法解析 一.MD5加密算法 我想这是大家都常听过的算法,可能也用的比较多.那么什么是MD5算法呢?MD5全称是 message-digest algorithm 5[|ˈmes ...
- https原理及其中所包含的对称加密、非对称加密、数字证书、数字签名
声明:本文章已授权公众号Hollis转载,如需转载请标明转载自https://www.cnblogs.com/wutianqi/p/10654245.html(安静的boy) 一.为什么要使用http ...
- HTTPS加密那点事-对称、非对称加密、数字证书
转自:[漫画]https 加密那点事 首先,HTTP协议的缺点:没有对数据进行加密,都是明文传输的.如果要改进这种明文传输的协议,该如何做呢? 对称加密: 在每次发送真实数据之前,服务器先生成一把密钥 ...
- C#开发中常用加密解密方法解析
一.MD5加密算法 我想这是大家都常听过的算法,可能也用的比较多.那么什么是MD5算法呢?MD5全称是message-digest algorithm 5,简单的说就是单向的加密,即是说无法根据密文推 ...
随机推荐
- 内存泄漏定位工具之 mtrace(二)
1 前言 mtrace(memory trace),是 GNU Glibc 自带的内存问题检测工具,它可以用来协助定位内存泄露问题.它的实现源码在glibc源码的malloc目录下,其基本设计原理为设 ...
- 修改文件权限后Git 文件目录被标记为修改
刚打开IDE,工作区的代码状态全部变成修改未提交的状态了?这是这么回事?这是因为Git忽略文件权限或者拥有者改变导致的git状态变化.默认Git会记录文件的权限信息,如果文件的权限信息被修改,在Git ...
- 【Lua】xLua逻辑热更新
1 前言 Lua基础语法 中系统介绍了 Lua 的语法体系,ToLua逻辑热更新 中介绍了 ToLua 的应用,本文将进一步介绍 Unity3D 中基于 xLua 实现逻辑热更新. 逻辑热更新 ...
- 优先队列(PriorityQueue)常用方法及简单案例
1 前言 PriorityQueue是一种特殊的队列,满足队列的"队尾进.队头出"条件,但是每次插入或删除元素后,都对队列进行调整,使得队列始终构成最小堆(或最大堆).具体调整如下 ...
- oracle中使用自定义函数解析指定分隔符的字符串
1.创建字符串表类型 create type tab_varchar is table of varchar2(2000); 2.创建管道函数 create or replace function g ...
- spring事务的传播
目录 事务的传播行为类型 注意事项 关于事务的传播,我们先确定一个场景:方法A调用方法B,方法A可能存在事务,也可能不存在事务,我们这里重点关注方法B上定义的事务传播行为,以及方法B中出现异常时,方法 ...
- Redis分布式锁的正确使用姿势
前言 分布式锁在日常开发中,用处非常的多.包括但不限于抢红包,秒杀,支付下单,幂等,等等场景. 分布式锁的实现方式有多种,包括redis实现,mysql实现,zookeeper实现等等.而其中redi ...
- OpenCV开发笔记(六十):红胖子8分钟带你深入了解Harris角点检测(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- 文件的拓展及文件函数,定义函数及函数参数---day09
1.文件的拓展模式 utf-8 编码格式下,默认一个中文三个字节,一个英文或符号占用一个字节 read() 功能:读取字符的个数(里面的参数代表字符个数) seek() 功能:调整指针的位置(里面的参 ...
- SOTIF很快将会取代ISO 26262?为您详细解读SOTIF标准ISO/PAS 21448
SOTIF很快将会取代ISO 26262?为您详细解读SOTIF标准ISO/PAS 21448 根据MES模赛思对其全球客户的问卷调查表明, 尽管有相当一部分的参与者(35%)认为SOTIF在功能安全 ...