河南移动商城网站建设,关键词优化技巧有哪些,微信广告平台推广,网站建设的推进方案加密常用于通信中#xff0c;如战争中电台通讯有明码和密码#xff0c;密码需要不断更换密码本#xff1b;另外#xff0c;商用软件也需要用到加密技术#xff0c;如根据电脑的mac地址设置权限#xff0c;防止软件被恶意传播。 文章目录一、介绍1. 单向散列/哈希算法2. 对… 加密常用于通信中如战争中电台通讯有明码和密码密码需要不断更换密码本另外商用软件也需要用到加密技术如根据电脑的mac地址设置权限防止软件被恶意传播。 文章目录一、介绍1. 单向散列/哈希算法2. 对称加密算法3. 非对称加密算法二、加密算法实现1. 造轮子AES算法SM4算法RSA算法MD5SHA-1sm32. openssl3. cryptoAES算法DES算法RSA算法SHA-256算法4. botan5. cryptlib三、性能与方案选择一、介绍
信息加密技术是利用数学或物理手段对电子信息在传输过程中和存储介质内进行保护以防止泄露的技术。通信加密技术是信息加密技术的重要分支是网络安全的重要组成部分。
加密就是通过密码算法对数据进行转化使之成为没有正确密钥任何人都无法读懂的报文。而这些以无法读懂的形式出现的数据一般被称为密文。为了读懂报文密文必须重新转变为它的最初形式——明文而含有以数学方式转换报文的双重密码就是密钥。
通信加密技术早期采用单向散列hash算法即明文加密成密文后不能再解密成明文。这种算法一般用来存储密码等信息验证密码时需要将密码转成的密文与数据库中密文进行对比。知名的单向散列算法有MD5、CRC32和SHA-256。
但如果我们只想在传输过程加密收到数据后还想将其转换成明文怎么办呢
为了解决上述问题对称加密算法出现了。明文通过对称加密算法的密钥加密成密文密文又可以通过对称加密算法的密钥解密成明文由于加密和解密过程使用同一把密钥所以称为对称加密。服务端和客户端之间的加密就常用到对称加密算法。知名的对称加密算法有DES和AES。
但是这个密钥放在哪里呢如果定义一个变量客户端和服务端各放一份我们在发送前肯定要对明文加密别人很容易通过OD调试器追踪到密钥如果只放在服务端第一次通信时发过去那别人也可以通过对客户端抓包找到密钥还有就是把密钥也加密发过去那密钥的密钥总是明文吧那就成了套娃。
为了解决以上问题非对称加密算法出现了。非对称加密算法很神奇它采用了一对密钥即公钥和私钥。对一串明文如果你用公钥加密就只能用私钥解密而用私钥加密就只能用公钥解密。但非对称加密过程很复杂所以处理很慢比对称加密慢几百倍用于网络传输不现实。知名的非对称加密算法有RSA和ECC。
对称加密不能确保安全非对称加密不能保证效率那怎么办呢
为了解决这个问题混合加密策略出现了即用非对称加密来解决对称加密的密钥传输密钥传输完成后A和B间采用对称加密算法通信。对称加密算法的密钥由服务端A生成A把对称加密算法的密钥用B的公钥加密B收到后用自己的私钥解密即“公钥加密私钥解密”得到对称加密算法的密钥AB都有对称加密的密钥了双方就可以正常进行对称加密通信了。混合加密策略解决了窃听的问题此外为了防止被逆向跟踪最好再搭配反调试异步回调多线程时钟扰乱增大逆向难度。
除了窃听常见的安全问题还有篡改和冒充。
要解决这个问题就来到了下面的数字签名技术。数字签名技术使用了hash算法和非对称加密算法。利用私钥加密公钥如果能成功解密得到摘要可以证明发送方的身份防止冒充对消息内容进行hash得到摘要经过摘要对比可以检测是否被篡改。
服务端A向客户端B发送数据先对明文使用hash算法生成摘要(digest)对这个摘要用A的私钥唯一性防止冒充加密生成数字签名(signature)将“明文数字签名”发送给B。
客户端B接收数据对数字签名用A的公钥解密得到摘要1再对明文用hash算法得到摘要2对比摘要1和摘要2若两者一致说明数据确实是A发过来的。
问题都解决了吗还没有。非对称加密时要先将A和B的公钥发送给对方在这个公钥分发的过程中可能会出现“中间人劫持”现象即中间人C截获A和B的公钥并将自己伪装成B和A分别和A和B通信这样中间人C获得了完整的数据。
那么如何安全地分发公钥呢即证明A的公钥确实是A的B的公钥确实是B的呢
现实世界中有公证处而网络世界中也有这样一种具有公信力的组织叫CA它可以给服务端A颁发一个数字证书上面有A的信息包含A的公钥这样如果拿到了证书也就拿到了可信任的A的公钥。
那么证书要怎么安全传输呢? 如果证书被篡改了怎么办? 现在的情况是需要一种既要能判断公钥是否冒充还要能判断数据是否被篡改的手段, 这不就是刚刚介绍的数字签名技术。具体操作其实就是把数字签名中的明文部分替换为 “数字证书”。客户端B向服务端A发送请求时服务端A会返回自己数字证书给客户端B。CA公钥是内置在客户电脑中的。
以上就是对通信加密技术的简单介绍。
为了信息安全我国也开发了国产密码算法简称国密算法是由国家密码局认定的拥有自主知识产权的密码算法在目前应用广泛的有SM2、SM3、SM4。
目前为止共计有近200多种加密算法按国际惯例将这近200种算法按照双方收发的密钥是否相同的标准划分为两大类一种是常规算法也叫私钥加密算法或对称加密算法其特征是收信方和发信方使用相同的密钥即加密密钥和解密密钥是相同或等价的。常规密码的优点是有很强的保密强度且经受住时间的检验和攻击但其密钥必须通过安全的途径传送。因此其密钥管理成为系统安全的重要因素。知名的私钥加密算法有DES、3DES和AES。
另一种是公钥加密算法也叫非对称加密算法其特征是收信方和发信方使用的密钥互不相同而且几乎不可能从加密密钥推导解密密钥。比较著名的公钥密码算法有RSA、DSA和ECC等。公钥密码的优点是可以适应网络的开放性要求且密钥管理问题也较为简单尤其可方便的实现数字签名和验证。但其算法复杂加密数据的速率较低。
纵观这两种算法一个从DES到3DES再到ADES一个从RSA到ECC。其发展角度无不是从密钥的简单性成本的低廉性管理的简易性算法的复杂性保密的安全性以及计算的快速性这几个方面去考虑。因此未来算法的发展也必定是从这几个角度出发的而且在实际操作中往往把这两种算法结合起来或许将来一种集两种算法有点于一身的新型算法将会出现到那时数据通信必将更加快捷与安全。
1. 单向散列/哈希算法
单向散列函数也称Hash函数指的是根据输入消息计算后输出固定长度数值的算法输出数值也称为“散列值”或“消息摘要”其长度通常在128256位之间。
常用的单向散列算法有MD5、SHA-x系列、CRC系列等。
MD5算法是指输入任意长度的信息经过处理输出为128位的信息数字指纹不同的输入得到不同的结果唯一性根据128位的输出结果不可能反推出输入的信息不可逆。对安全性要求不高的软件常用MD5算法。
CRC也叫循环冗余校验码是数据通信领域常用的一种查错校验码其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查CRC是一种数据传输检错功能对数据进行多项式计算。我们都知道反码求和法用的是加法而CRC算法用的是“除法”这里不是十进制除法而是二进制的异或取余。CRC8最终的余数是8位如果不满8位需要在高位补0CRC32最终的余数则是32位。车辆通信报文校验常用CRC算法。
SHA算法是在MD4算法的基础上演变而来由美国国家安全局设计有SHA-1和SHA-2两个系列。安全性要求一般时采用SHA-1安全性要求较高时则至少采用SHA-256算法SHA-256是指任意长度的消息文件通过SHA-256算法加密最终得到的密文都是256位32字节通常用一个长度为64的十六进制字符串来表示。https签名算法使用的是带RSA加密的SHA-256算法。
SM3算法哈希算法适用于商用密码应用中的数字签名和验证消息认证码的生成与验证以及随机数的生成可满足多种密码应用的安全需求。用于替换MD5、SHA-1等国际算法。为了保证杂凑算法的安全性其产生的杂凑值的长度不应太短例如MD5输出128比特杂凑值输出长度太短影响其安全性。SHA-1算法的输出长度为160比特SM3算法的输出长度为256比特因此SM3算法的安全性要高于MD5算法和SHA-1算法。
2. 对称加密算法
对称加密算法是应用较早的加密算法。在对称加密算法中数据发信方将明文和加密密钥一起经过特殊加密算法处理后使其变成复杂的加密密文发送出去。收信方收到密文后若想解读原文则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密才能使其恢复成可读明文。在对称加密算法中使用的密钥只有一个发收信双方都使用这个密钥对数据进行加密和解密这就要求解密方事先必须知道加密密钥。
DES是IBM公司1977年为美国政府研制的一种算法。DES是以56位密钥为基础的密码块加密技术。它的加密过程一般如下
一次性把64位明文块打乱置换把64位明文块拆成两个32位块用机密DES密钥把每个32位块打乱位置16次使用初始置换的逆置换。
但后来DES被容易地破解因此美国推出DES的改进版本——三重加密triple Data Encryption Standard3DES即在使用过程中收发双方都用三把密钥进行加解密无疑这种3*56式的加密算法大大提升了密码的安全性按现在计算机的运算速度这种破解几乎是不可能的。但是我们在为数据提供强有力的安全保护的同时也要花更多的时间来对信息进行三次加密和对每个密层进行解密。同时在这种前提下使用这种密钥的双发都必须拥有3个密钥如果丢失了其中任何一把其余两把都成了无用的密钥。这样私钥的数量一下又提升了3倍这显然不是我们想看到的。
于是美国国家标准与技术研究所推出了一个新的保密措施来保护金融交易。高级加密标准Advanced Encryption StandardAES美国国家技术标准委员会NIST在2000年10月选定了比利时的研究成果“Rijndael”作为AES的基础。AES内部有更简洁精确的数学算法,而加密数据只需一次通过。AES被设计成高速坚固的安全性能而且能够支持各种小型设备。AES与3DES相比不仅是安全性能有重大差别使用性能和资源有效利用上也有很大差别。
SM4算法对称加密算法。主要用于无线局域网标准用于替换DES/AES等算法。要保证一个对称密码算法的安全性的基本条件是其具备足够的密钥长度SM4算法与AES算法具有相同的密钥长度分组长度128比特因此在安全性上高于3DES算法。
3. 非对称加密算法
非对称加密算法是一种密钥的保密方法。非对称加密算法需要两个密钥公开密钥 publickey:简称公钥和私有密钥privatekey:简称私钥。公钥与私钥是一对如果用公钥对数据进行加密只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥所以这种算法称为非对称加密算法。
面对在执行过程中如何使用和分享密钥及保持其机密性等问题1975年Whitefield Diffe和Marti Hellman提出了公开的密钥密码技术的概念被称为Diffie-Hellman技术。从此公钥加密算法便产生了。
由于采取了公共密钥密钥的管理和分发就变得简单多了对于一个n个用户的网络来说只需要2n个密钥便可达到密度。同时使得公钥加密法的保密性全部集中在及其复杂的数学问题上它的安全性因而也得到了保证。但是在实际运用中公共密钥加密算法并没有完全的取代私钥加密算法。其重要的原因是它的实现速度远远赶不上私钥加密算法。又因为它的安全性所以常常用来加密一些重要的文件。
根据所基于的数学难题来分类有以下三类系统目前被认为是安全和有效的大整数因子分解系统代表性的有RSA、椭圆曲线离散对数系统ECC和离散对数系统代表性的有DSA。
RSA系统是公钥系统的最具有典型意义的算法大多数使用公钥密码进行加密和数字签名的产品和标准使用的都是RSA算法。它的具体算法如下
找两个非常大的质数越大越安全。把这两个质数叫做P和Q找一个能满足下列条件得数字EA是一个奇数B小于P×QC与P1×Q1互质只是指E和该方程的计算结果没有相同的质数因子计算出数值D满足下面性质D×E1能被P1×Q1整除。
公开密钥对是P×QE私人密钥是D公开密钥是E。 解密函数是 假设T是明文C是密文。 加密函数用公开密钥E和模P×Q 加密信息TE模P×Q。 解密函数用私人密钥D和模P×Q 解密信息CD模P×Q。 椭圆曲线加密技术ECC是建立在单向函数椭圆曲线离散对数的基础上由于它比RAS使用得离散对数要复杂得多而且该单向函数比RSA得要难所以与RSA相比它有安全性高、计算量小、存储空间占用小、占用带宽低等优点。
在实现非对称加密RSA算法前服务端A和客户端都要先用openssl开源密码库生成自己的公钥和私钥。命令如下
genrsa -out private_key.pem 2048 # 制作私钥
rsa -in private_key.pem -pubout -out public_key.pem # 制作公钥注意公钥是公开的因此程序开始A和B会传输各自的公钥给对方。
通过RSA算法传输数据的流程如下
A发送数据给BA先把明文用B的公钥进行加密这样除了B的私钥其他都解不了密B收到后用自己的私钥解密得到明文。
B发送数据给AB把明文用A的公钥进行加密A收到后用自己的私钥解密得到明文。
规则就是你要发给谁就用谁的公钥加密这样他收到后只有他自己的私钥能解密。
远程ssh连接git账户时生成密钥的算法就是RSA算法。
SM2算法非对称加密算法。基于椭圆曲线密码ECC的公钥密码算法标准提供数字签名、密钥交换和公钥加密。用于替换RSA等国际算法。SM2算法与RSA算法不同的是SM2算法是基于椭圆曲线上点群离散对数难题相对于RSA算法256位的SM2密码强度已经比2048位的RSA密码强度要高。
二、加密算法实现
1. 造轮子 自己编写相关加密算法。 AES算法
一个基于C的AES实现https://github.com/Urban82/Aes256 aes.h
#ifndef AES_H
#define AES_H/*** 参数 p: 明文的字符串数组。* 参数 plen: 明文的长度,长度必须为16的倍数。* 参数 key: 密钥的字符串数组。*/
void aes(char *p, int plen, char *key);/*** 参数 c: 密文的字符串数组。* 参数 clen: 密文的长度,长度必须为16的倍数。* 参数 key: 密钥的字符串数组。*/
void deAes(char *c, int clen, char *key);#endif
aes.cpp
#include stdio.h
#include stdlib.h
#include string.h
#include aes.hvoid aes(char *p, int plen, char *key);
void deAes(char *c, int clen, char *key);
/*** S盒*/
static const int S[16][16] { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };/*** 逆S盒*/
static const int S2[16][16] { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };/*** 获取int数据的低8位的左4个位*/
static int getLeft4Bit(int num) {int left num 0x000000f0;return left 4;
}/*** 获取int数据的低8位的右4个位*/
static int getRight4Bit(int num) {return num 0x0000000f;
}
/*** 根据索引从S盒中获得元素*/
static int getNumFromSBox(int index) {int row getLeft4Bit(index);int col getRight4Bit(index);return S[row][col];
}/*** 把一个字符转变成整型*/
static int getIntFromChar(char c) {int result (int) c;return result 0x000000ff;
}/*** 把16个字符转变成4X4的数组* 该矩阵中字节的排列顺序为从上到下* 从左到右依次排列。*/
static void convertToIntArray(char *str, int pa[4][4]) {int k 0;for(int i 0; i 4; i)for(int j 0; j 4; j) {pa[j][i] getIntFromChar(str[k]);k;}
}/*** 打印4X4的数组*/
static void printArray(int a[4][4]) {for(int i 0; i 4; i){for(int j 0; j 4; j)printf(a[%d][%d] 0x%x , i, j, a[i][j]);printf(\n);}printf(\n);
}/*** 打印字符串的ASSCI* 以十六进制显示。*/
static void printASSCI(char *str, int len) {for(int i 0; i len; i)printf(0x%x , getIntFromChar(str[i]));printf(\n);
}/*** 把连续的4个字符合并成一个4字节的整型*/
static int getWordFromStr(char *str) {int one getIntFromChar(str[0]);one one 24;int two getIntFromChar(str[1]);two two 16;int three getIntFromChar(str[2]);three three 8;int four getIntFromChar(str[3]);return one | two | three | four;
}/*** 把一个4字节的数的第一、二、三、四个字节取出* 入进一个4个元素的整型数组里面。*/
static void splitIntToArray(int num, int array[4]) {int one num 24;array[0] one 0x000000ff;int two num 16;array[1] two 0x000000ff;int three num 8;array[2] three 0x000000ff;array[3] num 0x000000ff;
}/*** 将数组中的元素循环左移step位*/
static void leftLoop4int(int array[4], int step) {int temp[4];for(int i 0; i 4; i)temp[i] array[i];int index step % 4 0 ? 0 : step % 4;for(int i 0; i 4; i){array[i] temp[index];index;index index % 4;}
}/*** 把数组中的第一、二、三和四元素分别作为* 4字节整型的第一、二、三和四字节合并成一个4字节整型*/
static int mergeArrayToInt(int array[4]) {int one array[0] 24;int two array[1] 16;int three array[2] 8;int four array[3];return one | two | three | four;
}/*** 常量轮值表*/
static const unsigned int Rcon[10] { 0x01000000, 0x02000000,0x04000000, 0x08000000,0x10000000, 0x20000000,0x40000000, 0x80000000,0x1b000000, 0x36000000 };
/*** 密钥扩展中的T函数*/
static int T(int num, int round) {int numArray[4];splitIntToArray(num, numArray);leftLoop4int(numArray, 1);//字循环//字节代换for(int i 0; i 4; i)numArray[i] getNumFromSBox(numArray[i]);int result mergeArrayToInt(numArray);return result ^ Rcon[round];
}//密钥对应的扩展数组
static int w[44];/*** 扩展密钥结果是把w[44]中的每个元素初始化*/
static void extendKey(char *key) {for(int i 0; i 4; i)w[i] getWordFromStr(key i * 4);for(int i 4, j 0; i 44; i) {if( i % 4 0) {w[i] w[i - 4] ^ T(w[i - 1], j);j;//下一轮}else {w[i] w[i - 4] ^ w[i - 1];}}}/*** 轮密钥加*/
static void addRoundKey(int array[4][4], int round) {int warray[4];for(int i 0; i 4; i) {splitIntToArray(w[ round * 4 i], warray);for(int j 0; j 4; j) {array[j][i] array[j][i] ^ warray[j];}}
}/*** 字节代换*/
static void subBytes(int array[4][4]){for(int i 0; i 4; i)for(int j 0; j 4; j)array[i][j] getNumFromSBox(array[i][j]);
}/*** 行移位*/
static void shiftRows(int array[4][4]) {int rowTwo[4], rowThree[4], rowFour[4];//复制状态矩阵的第2,3,4行for(int i 0; i 4; i) {rowTwo[i] array[1][i];rowThree[i] array[2][i];rowFour[i] array[3][i];}//循环左移相应的位数leftLoop4int(rowTwo, 1);leftLoop4int(rowThree, 2);leftLoop4int(rowFour, 3);//把左移后的行复制回状态矩阵中for(int i 0; i 4; i) {array[1][i] rowTwo[i];array[2][i] rowThree[i];array[3][i] rowFour[i];}
}/*** 列混合要用到的矩阵*/
static const int colM[4][4] { 2, 3, 1, 1,1, 2, 3, 1,1, 1, 2, 3,3, 1, 1, 2 };static int GFMul2(int s) {int result s 1;int a7 result 0x00000100;if(a7 ! 0) {result result 0x000000ff;result result ^ 0x1b;}return result;
}static int GFMul3(int s) {return GFMul2(s) ^ s;
}static int GFMul4(int s) {return GFMul2(GFMul2(s));
}static int GFMul8(int s) {return GFMul2(GFMul4(s));
}static int GFMul9(int s) {return GFMul8(s) ^ s;
}static int GFMul11(int s) {return GFMul9(s) ^ GFMul2(s);
}static int GFMul12(int s) {return GFMul8(s) ^ GFMul4(s);
}static int GFMul13(int s) {return GFMul12(s) ^ s;
}static int GFMul14(int s) {return GFMul12(s) ^ GFMul2(s);
}/*** GF上的二元运算*/
static int GFMul(int n, int s) {int result;if(n 1)result s;else if(n 2)result GFMul2(s);else if(n 3)result GFMul3(s);else if(n 0x9)result GFMul9(s);else if(n 0xb)//11result GFMul11(s);else if(n 0xd)//13result GFMul13(s);else if(n 0xe)//14result GFMul14(s);return result;
}
/*** 列混合*/
static void mixColumns(int array[4][4]) {int tempArray[4][4];for(int i 0; i 4; i)for(int j 0; j 4; j)tempArray[i][j] array[i][j];for(int i 0; i 4; i)for(int j 0; j 4; j){array[i][j] GFMul(colM[i][0],tempArray[0][j]) ^ GFMul(colM[i][1],tempArray[1][j]) ^ GFMul(colM[i][2],tempArray[2][j]) ^ GFMul(colM[i][3], tempArray[3][j]);}
}
/*** 把4X4数组转回字符串*/
static void convertArrayToStr(int array[4][4], char *str) {for(int i 0; i 4; i)for(int j 0; j 4; j)*str (char)array[j][i];
}
/*** 检查密钥长度*/
static int checkKeyLen(int len) {if(len 4)return 1;elsereturn 0;
}/*** 参数 p: 明文的字符串数组。* 参数 plen: 明文的长度。* 参数 key: 密钥的字符串数组。*/
void aes(char *p, int plen, char *key){int keylen strlen(key);if(plen 0 || plen % 4 ! 0) {printf(明文字符长度必须为4的倍数\n);exit(0);}if(!checkKeyLen(keylen)) {printf(密钥字符长度错误长度必须为16、24和32。当前长度为%d\n,keylen);exit(0);}extendKey(key);//扩展密钥int pArray[4][4];for(int k 0; k plen; k 16) { convertToIntArray(p k, pArray);addRoundKey(pArray, 0);//一开始的轮密钥加for(int i 1; i 10; i){//前9轮subBytes(pArray);//字节代换shiftRows(pArray);//行移位mixColumns(pArray);//列混合addRoundKey(pArray, i);}//第10轮subBytes(pArray);//字节代换shiftRows(pArray);//行移位addRoundKey(pArray, 10);convertArrayToStr(pArray, p k);}
}
/*** 根据索引从逆S盒中获取值*/
static int getNumFromS1Box(int index) {int row getLeft4Bit(index);int col getRight4Bit(index);return S2[row][col];
}
/*** 逆字节变换*/
static void deSubBytes(int array[4][4]) {for(int i 0; i 4; i)for(int j 0; j 4; j)array[i][j] getNumFromS1Box(array[i][j]);
}
/*** 把4个元素的数组循环右移step位*/
static void rightLoop4int(int array[4], int step) {int temp[4];for(int i 0; i 4; i)temp[i] array[i];int index step % 4 0 ? 0 : step % 4;index 3 - index;for(int i 3; i 0; i--) {array[i] temp[index];index--;index index -1 ? 3 : index;}
}/*** 逆行移位*/
static void deShiftRows(int array[4][4]) {int rowTwo[4], rowThree[4], rowFour[4];for(int i 0; i 4; i) {rowTwo[i] array[1][i];rowThree[i] array[2][i];rowFour[i] array[3][i];}rightLoop4int(rowTwo, 1);rightLoop4int(rowThree, 2);rightLoop4int(rowFour, 3);for(int i 0; i 4; i) {array[1][i] rowTwo[i];array[2][i] rowThree[i];array[3][i] rowFour[i];}
}
/*** 逆列混合用到的矩阵*/
static const int deColM[4][4] { 0xe, 0xb, 0xd, 0x9,0x9, 0xe, 0xb, 0xd,0xd, 0x9, 0xe, 0xb,0xb, 0xd, 0x9, 0xe };/*** 逆列混合*/
static void deMixColumns(int array[4][4]) {int tempArray[4][4];for(int i 0; i 4; i)for(int j 0; j 4; j)tempArray[i][j] array[i][j];for(int i 0; i 4; i)for(int j 0; j 4; j){array[i][j] GFMul(deColM[i][0],tempArray[0][j]) ^ GFMul(deColM[i][1],tempArray[1][j]) ^ GFMul(deColM[i][2],tempArray[2][j]) ^ GFMul(deColM[i][3], tempArray[3][j]);}
}
/*** 把两个4X4数组进行异或*/
static void addRoundTowArray(int aArray[4][4],int bArray[4][4]) {for(int i 0; i 4; i)for(int j 0; j 4; j)aArray[i][j] aArray[i][j] ^ bArray[i][j];
}
/*** 从4个32位的密钥字中获得4X4数组* 用于进行逆列混合*/
static void getArrayFrom4W(int i, int array[4][4]) {int index i * 4;int colOne[4], colTwo[4], colThree[4], colFour[4];splitIntToArray(w[index], colOne);splitIntToArray(w[index 1], colTwo);splitIntToArray(w[index 2], colThree);splitIntToArray(w[index 3], colFour);for(int i 0; i 4; i) {array[i][0] colOne[i];array[i][1] colTwo[i];array[i][2] colThree[i];array[i][3] colFour[i];}}/*** 参数 c: 密文的字符串数组。* 参数 clen: 密文的长度。* 参数 key: 密钥的字符串数组。*/
void deAes(char *c, int clen, char *key) {int keylen strlen(key);if(clen 0 || clen % 4 ! 0) {printf(密文字符长度必须为4的倍数现在的长度为%d\n,clen);exit(0);}if(!checkKeyLen(keylen)) {printf(密钥字符长度错误长度必须为16、24和32。当前长度为%d\n,keylen);exit(0);}extendKey(key);//扩展密钥int cArray[4][4];for(int k 0; k clen; k 16) {convertToIntArray(c k, cArray);addRoundKey(cArray, 10);int wArray[4][4];for(int i 9; i 1; i--) {deSubBytes(cArray);deShiftRows(cArray);deMixColumns(cArray);getArrayFrom4W(i, wArray);deMixColumns(wArray);addRoundTowArray(cArray, wArray);}deSubBytes(cArray);deShiftRows(cArray);addRoundKey(cArray, 0);convertArrayToStr(cArray, c k);}
}
参考main.cpp实现
#include stdio.h
#include unistd.h
#include string.h
#include stdlib.h
#include time.h
#include iostream#include aes.h#define MAXLEN 1024//获取字符串
void getString(char *str, int len){int slen read(0, str, len);for(int i 0; i slen; i,str){if(*str \n){*str \0;break;}}
}//输出ASCII
void printASCII(char *str, int len) {int c;for(int i 0; i len; i) {c (int)*str;c c 0x000000ff;//保留低8位printf(0x%x , c);}printf(\n);
}/*** 从标准输入中读取用户输入的字符串*/
void readPlainText(char *str, int *len) {int plen;while(1) {getString(str, MAXLEN);plen strlen(str);if(plen ! 0 plen % 4 0) {printf(你输入的明文为%s\n, str);break;}else{printf(明文字符长度必须为4的倍数,现在的长度为%d\n, plen);}}*len plen;
}
/*** 把字符串写进文件*/
void writeStrToFile(char *str, int len, char *fileName) {FILE *fp;fp fopen(fileName, wb);for(int i 0; i len; i)putc(str[i], fp);fclose(fp);
}//字符串写进文件
void aesStrToFile(char *key) {char p[MAXLEN];int plen;printf(请输入你的明文明文字符长度必须为4的倍数\n);readPlainText(p,plen);printf(进行AES加密..................\n);aes(p, plen, key);//AES加密printf(加密完后的明文的ASCII为\n);printASCII(p, plen);char fileName[64];printf(请输入你想要写进的文件名比如test.txt:\n);if(scanf(%s, fileName) 1) { writeStrToFile(p, plen, fileName);printf(已经将密文写进%s中了,可以在运行该程序的当前目录中找到它。\n, fileName);}
}
/*** 从文件中读取字符串*/
int readStrFromFile(char *fileName, char *str) {FILE *fp fopen(fileName, rb);if(fp NULL) {printf(打开文件出错请确认文件存在当前目录下\n);exit(0);}int i;for(i 0; i MAXLEN (str[i] getc(fp)) ! EOF; i);if(i MAXLEN) {printf(解密文件过大\n);exit(0);}str[i] \0;fclose(fp);return i;
}//解密文件
void deAesFile(char *key) {char fileName[64];char c[MAXLEN];//密文字符串printf(请输入要解密的文件名该文件必须和本程序在同一个目录\n);if(scanf(%s, fileName) 1) {int clen readStrFromFile(fileName, c);printf(开始解密.........\n);deAes(c, clen, key);printf(解密后的明文ASCII为\n);printASCII(c, clen);printf(明文为%s\n, c);writeStrToFile(c,clen,fileName);printf(现在可以打开%s来查看解密后的密文了\n,fileName);}
}//加密文件
void aesFile(char *key) {char fileName[64];char fileP[MAXLEN];printf(请输入要加密的文件名该文件必须和本程序在同一个目录\n);if(scanf(%s, fileName) 1) {readStrFromFile(fileName, fileP);int plen strlen(fileP);printf(开始加密.........\n);printf(加密前文件中字符的ASCII为\n);printASCII(fileP, plen);aes(fileP, plen, key);//开始加密printf(加密后的密文ASCII为\n);printASCII(fileP, plen);writeStrToFile(fileP,plen,fileName);printf(已经将加密后的密文写进%s中了\n,fileName);}
}int main(int argc, char const *argv[]) {clock_t start,finish;start clock();char key[17];printf(请输入4个字符的密钥\n);int klen;while(1){getString(key,17);klen strlen(key);if(klen ! 4){printf(请输入4个字符的密钥,当前密钥的长度为%d\n,klen);}else{printf(你输入的密钥为%s\n,key);break;}}printf(输入s表示要加密输入的字符串,并将加密后的内容写入到文件\n);printf(请输入要功能选项并按回车输入f表示要加密文件\n);printf(输入p表示要解密文件\n);char c;if(scanf(%s,c) 1) {if(c s)aesStrToFile(key);//用AES加密字符串并将字符串写进文件中else if(c p)deAesFile(key);//把文件中的密文解密并写回文件中else if(c f)//用AES加密文件aesFile(key);}finish clock();std::cout std::endlthe time cost is: double(finish - start) / CLOCKS_PER_SEC std::endl;return 0;
}
编译 Windows可在VS2017下不依赖其他库实现 Linux编译g -o aes -static aes.cpp main.cpp
SM4算法
一个SM的算法https://github.com/tonyonce2017/SM4
#ifndef _SM4_H
#define _SM4_H
#includestdio.h
#includetime.h
#includeiomanip
#includestdlib.htypedef unsigned int word;// 密钥扩展
// param:
// mk[4]: 加密密钥
// return: 轮密钥
word* keyExpansion(word mk[4]);// 迭代
// param¿
// x[4]: 加密结果
// mk[4]:密钥 128 bits
// flag: true加密 flase:解密
void encryption(word x[4], word mk[4], bool flag);// sm4加密CBC模式
// param¿
// result加密结果
// arr 待加密数据
// bits 待加密数据的bit数
// mk[4] 密钥128 bits
// return 加密结果result的bit数
unsigned int sm4_encryption(word* result, word* arr, unsigned int bits, word mk[4]);// sm4解密CBC模式
// param¿
// result: 解密结果
// arr : 待解密数据
// bits : 待解密数据的bit数
// mk[4] : 密钥128 bits
// return 解密结果result的bit数
unsigned int sm4_decryption(word* result, word* arr, unsigned int bits, word mk[4]);const word S[] {0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, //00x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, //10x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, //20xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, //30x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, //40x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35, //50x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87, //60xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, //70xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1, //80xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3, //90x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, //A0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51, //B0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8, //C0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, //D0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84, //E0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48 //F
};#define ShiftLeft(x,k) (x(32-k)|(xk))
#define L(x) (x^ShiftLeft(x,2)^ShiftLeft(x,10)^ShiftLeft(x,18)^ShiftLeft(x,24))//¿¿¿¿L
#define LL(x) (x^ShiftLeft(x,13)^ShiftLeft(x,23))//¿¿¿¿¿¿¿¿¿
#define F(x) (T(x))
#define lamda(x) ((S[x 24 0xff] 24) | (S[x 16 0xff] 16) | (S[x 8 0xff] 8) | S[x 0xff])//¿¿¿¿¿//密钥扩展函数
word* keyExpansion(word mk[4]) {word* rk new word[32];word Fk[4] { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc };word CK[32], k[4];for (int i 0; i 32; i) {CK[i] 0;for (int j 0; j 4; j)CK[i] CK[i] * 256 ((4 * i j) * 7) % 256;}for (int i 0; i 4; i) {k[i] mk[i] ^ Fk[i];}word temp;for (int i 0; i 32; i) {temp k[1] ^ k[2] ^ k[3] ^ CK[i];temp lamda(temp);temp k[0] ^ LL(temp);k[0] k[1]; k[1] k[2]; k[2] k[3]; k[3] temp;rk[i] temp;}return rk;
}//迭代
void encryption(word x[4], word mk[4], bool flag) {word temp;word* rk keyExpansion(mk);for (int i 0; i 32; i) {temp x[1] ^ x[2] ^ x[3];if (flag false) temp ^ rk[31 - i];else temp ^ rk[i];temp lamda(temp);temp L(temp) ^ x[0];x[0] x[1]; x[1] x[2]; x[2] x[3]; x[3] temp;}temp x[0]; x[0] x[3]; x[3] temp;temp x[1]; x[1] x[2]; x[2] temp;delete[] rk;
}//sm4加密函数CBC模式
unsigned int sm4_encryption(word* result, word* arr, unsigned int bits, word mk[4]) {//return bitsword* temp;unsigned int temp_size;unsigned int s 128 - bits % 128;//s:填充的比特数if (s 0)s 128;else if (s 1)s 128;temp_size 4 ((bits s) 5);temp new unsigned int[temp_size];int i;for (i 4; i 4 ((bits 31) 5); i)temp[i] arr[i - 4];for (; i temp_size; i)temp[i] 0;temp[i - 1] | s;//用零填充最后8比特用s填充srand((int)time(0));for (i 0; i 4; i)temp[i] rand();//前128比特为初始向量result new unsigned int[temp_size];for (i 0; i 4; i)result[i] temp[i];for (i 4; i temp_size; i 4) {result[i] temp[i] ^ result[i - 4];result[i 1] temp[i 1] ^ result[i - 3];result[i 2] temp[i 2] ^ result[i - 2];result[i 3] temp[i 3] ^ result[i - 1];encryption(result[i], mk, true);}return temp_size * 32;
}//sm4解密CBC模式
unsigned int sm4_decryption(word* result, word* arr, unsigned int bits, word mk[4]) {unsigned int size bits / 32 - 4;result new unsigned int[size];unsigned int i;for (i 0; i size; i 4) {result[i] arr[i 4];result[i 1] arr[i 5];result[i 2] arr[i 6];result[i 3] arr[i 7];encryption(result[i], mk, false);result[i] ^ arr[i];result[i 1] ^ arr[i 1];result[i 2] ^ arr[i 2];result[i 3] ^ arr[i 3];}i result[size - 1] 0xff;return size * 32 - i;
}#endif
RSA算法
#include iostream
#include stdio.h
#include stdlib.h
#include ctype.h
#includestring.h
#include math.h
#includealgorithm
#include time.husing namespace std;
typedef long long ll;// e是公钥
// d是私钥ll e, d, n;ll gcd(ll a, ll b) //求最大公约数
{ll c 0;if(ab) swap(a,b);c b;do{b c;c a%b;a b;}while (c ! 0);return b;
}// 0不是 1是
ll isPrime(ll i) //判断i是否是素数
{ll flag0;for(ll a2; ai; a){if(i%a0){flag1;break;}}if(flag1) return 0;else return 1;}ll myPow(ll a, ll b, ll n) //求a^b mod n
{ll y;/*使用二进制平方乘法计算 pow(a,b) % n*/y1;while(b ! 0){/*对于b中的每个1累加y*/if(b 1)y (y*a) % n;/*对于b中的每一位计算a的平方*/a (a*a) % n;/*准备b中的下一位*/b b1;}return y;
}void extgcd(ll a,ll b,ll d,ll x,ll y)
{if(!b){da;x1;y0;}else{extgcd(b,a%b,d,y,x);y-x*(a/b);}
}ll ModularInverse(ll a,ll b) //获取(1/a)mod b的结果
{ll d,x,y;extgcd(a,b,d,x,y);return d1?(xb)%b:-1;}void KeyGeneration() //获取公钥密钥
{ll p, q;ll phi_n;do{dop rand();while (p % 2 0);}while (!isPrime(p)); // 得到素数 p do{doq rand();while (q % 2 0);}while (!isPrime(q)); // 得到素数q n p * q;phi_n (p - 1) * (q - 1);doe rand() % (phi_n - 2) 2; // 1 e phi_nwhile (gcd(e, phi_n) ! 1);d ModularInverse(e,phi_n);
}// 一位一位地输出加密的结果
ll Encryption(ll value) //加密
{ll cipher;cipher myPow(value, e, n);coutcipher;return cipher;
}// 一位一位地输出解 密的结果
void Decryption(ll value) //解密
{ll decipher;decipher myPow(value, d, n);coutdecipher;
}
int main()
{clock_t start,finish;start clock();// 对6位的数字进行稳定加密 ll num;cout请输入要加密的明文数字,enter结束endl;//while(cinnum){cin num;ll de;cout输入的明文为numendl; KeyGeneration(); //获取公钥密钥cout加密密钥eendl; cout加密结果为:;de Encryption( num );cout\n私钥为d;
// coutdedeendl;cout\n解密结果; Decryption(de); cout\n-------------endl;//}finish clock();cout endlthe time cost is: double(finish - start) / CLOCKS_PER_SECendl;return 0;
}
MD5
#include iostream
#include vector
#include cstdlib
#include string
#include time.husing namespace std;#define A 0x67452301
#define B 0xefcdab89
#define C 0x98badcfe
#define D 0x10325476const char str16[] 0123456789abcdef;const unsigned int T[] {0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391 };//行*列16*4const unsigned int s[] { 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21};//行*列4*16class MD5 {
private:unsigned int tempA, tempB, tempC, tempD, strlength;
public:MD5() {tempA A;tempB B;tempC C;tempD D;strlength 0;}// F函数unsigned int F(unsigned int b, unsigned int c, unsigned int d) {return (b c) | ((~b) d);}// G函数unsigned int G(unsigned int b, unsigned int c, unsigned int d) {return (b d) | (c (~d));}// H函数unsigned int H(unsigned int b, unsigned int c, unsigned int d) {return b ^ c ^ d;}// I函数unsigned int I(unsigned int b, unsigned int c, unsigned int d) {return c ^ (b | (~d));}// 移位操作函数unsigned int shift(unsigned int a, unsigned int n) {return (a n) | (a (32 - n));}// 编码函数(重要)string encode(string src) {vectorunsigned int rec padding(src);//填充字符串for(unsigned int i 0; i strlength/16; i) {unsigned int num[16];for(int j 0; j 16; j) {num[j] rec[i*16j];}iterateFunc(num, 16);//循环压缩}return format(tempA) format(tempB) format(tempC) format(tempD);//整理输出}// 循环压缩void iterateFunc(unsigned int* X, int size 16) {unsigned int a tempA,b tempB,c tempC,d tempD,rec 0,g, k;for(int i 0; i 64; i) {if(i 16) {// F迭代g F(b, c, d);k i;}else if(i 32) {// G迭代g G(b, c, d);k (1 5*i) % 16;}else if(i 48) {// H迭代g H(b, c, d);k (5 3*i) % 16;}else {// I迭代g I(b, c, d);k (7*i) % 16;}rec d;d c;c b;b b shift(a g X[k] T[i], s[i]);a rec;}tempA a;tempB b;tempC c;tempD d;}// 填充字符串vectorunsigned int padding(string src) {// 以512位,64个字节为一组unsigned int num ((src.length() 8) / 64) 1;vectorunsigned int rec(num*16);strlength num*16;for(unsigned int i 0; i src.length(); i){// 一个unsigned int对应4个字节保存4个字符信息rec[i2] | (int)(src[i]) ((i % 4) * 8);}// 补充1000...000rec[src.length() 2] | (0x80 ((src.length() % 4)*8));// 填充原文长度rec[rec.size()-2] (src.length() 3);return rec;}// 整理输出string format(unsigned int num) {string res ;unsigned int base 1 8;for(int i 0; i 4; i) {string tmp ;unsigned int b (num (i * 8)) % base 0xff;for(int j 0; j 2; j) {tmp str16[b%16] tmp;b / 16;}res tmp;}return res;}
};int main() {clock_t start,finish;start clock();MD5 test;string a ;cout 请输入密码: ;getline(cin,a);cout MD5单向加密result: test.encode(a) endl;finish clock();cout endlthe time cost is: double(finish - start) / CLOCKS_PER_SECendl;
}//解密网站https://www.cmd5.com/
SHA-1
#include iostream
#include string
#include bitset
#include math.h
#include time.husing namespace std;long long pad[75] { 0 };
int lenth_pad 0;bitset32 Kt[4] { 0x5A827999,0x6ED9EBA1,0x8F1BBCDC,0xCA62C1D6 };
bitset32 Ht[5] { 0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0 };//Ft函数
bitset32 Ft(int t, bitset32 B, bitset32 C, bitset32 D)
{if (0 t t 19){return ((BC) | ((~B)D));}else if (20 t t 39){return (B^C^D);}else if (40 t t 59){return ((BC) | (BD) | (CD));}else if (60 t t 79){return (B^C^D);}
}//字符串的拓展函数
void SHA_PAD(string x)
{long long l x.length();long long i 0;pad[i] 128;i;l 1;if ((l * 8) % 512 ! 448){for (; (l * 8) % 512 ! 448; l){i;}}l x.length();l l * 8;int a 1;pad[i 7] l % 256;while (l / 256 0){l l / 256;pad[i 7 - a] l % 256;a;}for (; a 8; a){pad[i 7 - a] 0;}lenth_pad i 7;
}//循环左移函数
bitset32 ROTL(int s, bitset32 W)
{bitset32m W s;for (int i 0; i s; i){m[i] W[32 - s i];}return m;
}//模2^32加函数
bitset32 ADD(bitset32a, bitset32b)
{bitset32 c;int d 0;for (int i 0; i 32; i){c[i] (a[i] b[i] d) % 2;if (a[i] b[i] d 2){d 1;}else if (a[i] b[i] d 2){d 0;}}return c;
}//循环体
void DO(bitset512 M)
{bitset32 Wt[80] { 0 };for (int i 0; i 16; i){for (int n 0; n 32; n){Wt[i][n] M[(15 - i) * 32 n];}}for (int t 16; t 79; t){Wt[t] ROTL(1, Wt[t - 3] ^ Wt[t - 8] ^ Wt[t - 14] ^ Wt[t - 16]);}bitset32 A Ht[0];bitset32 B Ht[1];bitset32 C Ht[2];bitset32 D Ht[3];bitset32 E Ht[4];for (int t 0; t 79; t){bitset32 temp ADD(ADD(ADD(ROTL(5, A), Ft(t, B, C, D)), ADD(E, Wt[t])), Kt[t/20]);E D;D C;C ROTL(30, B);B A;A temp;}Ht[0] ADD(Ht[0], A);Ht[1] ADD(Ht[1], B);Ht[2] ADD(Ht[2], C);Ht[3] ADD(Ht[3], D);Ht[4] ADD(Ht[4], E);
}int main()
{clock_t start,finish;start clock();string x;cout please enter the text:;getline(cin, x);SHA_PAD(x);long long l 0;//循环体while (l x.length()){long long i l;string Sx;for (; (i 64 l) (i x.length()); i){bitset8 mark int(x[i]);Sx mark.to_string();}l 64;if (i x.length()){if(lenth_pad63)for (int n 0; n lenth_pad; n){bitset8 mark pad[n];Sx mark.to_string();}else{int n 0;for (; i l; i){bitset8 mark pad[n];n;Sx mark.to_string();}bitset512Mx(Sx);DO(Mx);string last_Sx;for (; n lenth_pad; n){bitset8 mark pad[n];last_Sx mark.to_string();}bitset512last_Mx(last_Sx);DO(last_Mx);break;}}bitset512 Mx(Sx);DO(Mx);}//输出cout The hash of text is:;for (int i 0; i 5; i){string s Ht[i].to_string();for (int n 0; n 32;){int result 0;for (int m 0; m 4; m){result (s[n m] - 0)*pow(2, 3 - m);}cout hex result;n 4;}}cout \n;//getchar();finish clock();cout the time cost is: double(finish-start) / CLOCKS_PER_SEC endl;return 0;
}sm3
#include iostream
#include string
#include cmath
#include time.h
using namespace std;//二进制转换为十六进制函数实现
string BinToHex(string str) {string hex ;//用来存储最后生成的十六进制数int temp 0;//用来存储每次四位二进制数的十进制值while (str.size() % 4 ! 0) {//因为每四位二进制数就能够成为一个十六进制数所以将二进制数长度转换为4的倍数str 0 str;//最高位添0直到长度为4的倍数即可}for (int i 0; i str.size(); i 4) {temp (str[i] - 0) * 8 (str[i 1] - 0) * 4 (str[i 2] - 0) * 2 (str[i 3] - 0) * 1;//判断出4位二进制数的十进制大小为多少if (temp 10) {//当得到的值小于10时可以直接用0-9来代替hex to_string(temp);}else {//当得到的值大于10时需要进行A-F的转换hex A (temp - 10);}}return hex;
}//十六进制转换为二进制函数实现
string HexToBin(string str) {string bin ;string table[16] { 0000,0001,0010,0011,0100,0101,0110,0111,1000,1001,1010,1011,1100,1101,1110,1111 };for (int i 0; i str.size(); i) {if (str[i] Astr[i] F) {bin table[str[i] - A 10];}else {bin table[str[i] - 0];}}return bin;
}//二进制转换为十进制的函数实现
int BinToDec(string str) {int dec 0;for (int i 0; i str.size(); i) {dec (str[i] - 0)*pow(2, str.size() - i - 1);}return dec;
}//十进制转换为二进制的函数实现
string DecToBin(int str) {string bin ;while (str 1) {bin to_string(str % 2) bin;str str / 2;}return bin;
}//十六进制转换为十进制的函数实现
int HexToDec(string str) {int dec 0;for (int i 0; i str.size(); i) {if (str[i] Astr[i] F) {dec (str[i] - A 10)*pow(16, str.size() - i - 1);}else {dec (str[i] - 0)*pow(16, str.size() - i - 1);}}return dec;
}//十进制转换为十六进制的函数实现
string DecToHex(int str) {string hex ;int temp 0;while (str 1) {temp str % 16;if (temp 10 temp 0) {hex to_string(temp) hex;}else {hex (A (temp - 10));}str str / 16;}return hex;
}string padding(string str) {//对数据进行填充 string res ;for (int i 0; i str.size(); i) {//首先将输入值转换为16进制字符串res DecToHex((int)str[i]);}cout 输入字符串的ASCII码表示为 endl;for (int i 0; i res.size(); i) {cout res[i];if ((i 1) % 8 0) {cout ;}if ((i 1) % 64 0 || (i 1) res.size()) {cout endl;}}cout endl;int res_length res.size() * 4;//记录的长度为2进制下的长度res 8;//在获得的数据后面添1在16进制下相当于是添加8while (res.size() % 128 ! 112) {res 0;//“0”数据填充}string res_len DecToHex(res_length);//用于记录数据长度的字符串while (res_len.size() ! 16) {res_len 0 res_len;}res res_len;return res;
}string LeftShift(string str, int len) {//实现循环左移len位功能string res HexToBin(str);res res.substr(len) res.substr(0, len);return BinToHex(res);
}string XOR(string str1, string str2) {//实现异或操作string res1 HexToBin(str1);string res2 HexToBin(str2);string res ;for (int i 0; i res1.size(); i) {if (res1[i] res2[i]) {res 0;}else {res 1;}}return BinToHex(res);
}string AND(string str1, string str2) {//实现与操作string res1 HexToBin(str1);string res2 HexToBin(str2);string res ;for (int i 0; i res1.size(); i) {if (res1[i] 1 res2[i] 1) {res 1;}else {res 0;}}return BinToHex(res);
}string OR(string str1, string str2) {//实现或操作string res1 HexToBin(str1);string res2 HexToBin(str2);string res ;for (int i 0; i res1.size(); i) {if (res1[i] 0 res2[i] 0) {res 0;}else {res 1;}}return BinToHex(res);
}string NOT(string str) {//实现非操作string res1 HexToBin(str);string res ;for (int i 0; i res1.size(); i) {if (res1[i] 0) {res 1;}else {res 0;}}return BinToHex(res);
}char binXor (char str1, char str2) {//实现单比特的异或操作return str1 str2 ? 0 : 1;
}char binAnd(char str1, char str2) {//实现单比特的与操作return (str1 1str2 1) ? 1 : 0;
}string ModAdd(string str1, string str2) {//mod 2^32运算的函数实现string res1 HexToBin(str1);string res2 HexToBin(str2);char temp 0;string res ;for (int i res1.size() - 1; i 0; i--) {res binXor(binXor(res1[i], res2[i]), temp) res;if (binAnd(res1[i], res2[i]) 1) {temp 1;}else {if (binXor(res1[i], res2[i]) 1) {temp binAnd(1, temp);}else {temp 0;}}}return BinToHex(res);
}string P1(string str) {//实现置换功能P1Xreturn XOR(XOR(str, LeftShift(str, 15)), LeftShift(str, 23));
}string P0(string str) {//实现置换功能P0Xreturn XOR(XOR(str, LeftShift(str, 9)), LeftShift(str, 17));
}string T(int j) {//返回Tj常量值的函数实现if (0 j j 15) {return 79CC4519;}else {return 7A879D8A;}
}string FF(string str1, string str2, string str3, int j) {//实现布尔函数FF功能if (0 j j 15) {return XOR(XOR(str1, str2), str3);}else {return OR(OR(AND(str1, str2), AND(str1, str3)), AND(str2, str3));}
}string GG(string str1, string str2, string str3, int j) {//实现布尔函数GG功能if (0 j j 15) {return XOR(XOR(str1, str2), str3);}else {return OR(AND(str1, str2), AND(NOT(str1), str3));}
}
string extension(string str) {//消息扩展函数string res str;//字符串类型存储前68位存储扩展字W值for (int i 16; i 68; i) {//根据公式生成第17位到第68位的W值res XOR(XOR(P1(XOR(XOR(res.substr((i-16)*8,8), res.substr((i - 9) * 8, 8)), LeftShift(res.substr((i - 3) * 8, 8), 15))), LeftShift(res.substr((i - 13) * 8, 8), 7)), res.substr((i - 6) * 8, 8));}cout 扩展后的消息 endl;cout W0,W1,……,W67的消息 endl;for (int i 0; i 8; i) {for (int j 0; j 8; j) {cout res.substr(i * 64 j * 8, 8) ;}cout endl;}cout res.substr(512, 8) res.substr(520, 8) res.substr(528, 8) res.substr(536, 8) endl;cout endl;for (int i 0; i 64; i) {//根据公式生成64位W值res XOR(res.substr(i * 8, 8), res.substr((i 4) * 8, 8));}cout W0,W1,……,W63的消息 endl;for (int i 0; i 8; i) {for (int j 0; j 8; j) {cout res.substr(544i * 64 j * 8, 8) ;}cout endl;}cout endl;return res;
}string compress(string str1, string str2) {//消息压缩函数string IV str2;string A IV.substr(0, 8), B IV.substr(8, 8), C IV.substr(16, 8), D IV.substr(24, 8), E IV.substr(32, 8), F IV.substr(40, 8), G IV.substr(48, 8), H IV.substr(56, 8);string SS1 , SS2 , TT1 , TT2 ;cout 迭代压缩中间值: endl;cout A B C D E F G H endl;cout A B C D E F G H endl;for (int j 0; j 64; j) {SS1 LeftShift(ModAdd(ModAdd(LeftShift(A, 12), E), LeftShift(T(j), (j%32))), 7);SS2 XOR(SS1, LeftShift(A, 12));TT1 ModAdd(ModAdd(ModAdd(FF(A, B, C, j), D), SS2), str1.substr((j 68) * 8, 8));TT2 ModAdd(ModAdd(ModAdd(GG(E, F, G, j), H), SS1), str1.substr(j * 8, 8));D C;C LeftShift(B, 9);B A;A TT1;H G;G LeftShift(F, 19);F E;E P0(TT2);cout A B C D E F G H endl;}string res (A B C D E F G H);cout endl;return res;
}string iteration(string str) {//迭代压缩函数实现int num str.size() / 128;cout 消息经过填充之后共有 to_string(num) 个消息分组。 endl;cout endl;string V 7380166F4914B2B9172442D7DA8A0600A96F30BC163138AAE38DEE4DB0FB0E4E;string B , extensionB , compressB ;for (int i 0; i num; i) {cout 第 to_string(i1) 个消息分组 endl;cout endl;B str.substr(i * 128, 128);extensionB extension(B);compressB compress(extensionB, V);V XOR(V, compressB);}return V;
}int main() {//主函数clock_t start, finish;//clock_t为CPU时钟计时单元数start clock();//clock()函数返回此时CPU时钟计时单元数string str[2];str[0] abcdabcdabcdabcd;str[1] 1234567812345678;for (int num 0; num 2; num) {cout 示例 to_string(num 1) 输入消息为字符串: str[num] endl;cout endl;string paddingValue padding(str[num]);cout 填充后的消息为 endl;for (int i 0; i paddingValue.size() / 64; i) {for (int j 0; j 8; j) {cout paddingValue.substr(i * 64 j * 8, 8) ;}cout endl;}cout endl;string result iteration(paddingValue);cout 杂凑值 endl;for (int i 0; i 8; i) {cout result.substr(i * 8, 8) ;}cout endl;cout endl;}finish clock();//clock()函数返回此时CPU时钟计时单元数cout endlthe time cost is: double(finish - start) / CLOCKS_PER_SECendl;//finish与start的差值即为程序运行花费的CPU时钟单元数量再除每秒CPU有多少个时钟单元即为程序耗时return 0;
}
2. openssl OpenSSL is written in C, and has an Apache style license. It is distinguished by its support for the SSL and TLS protocols, as well as a family of command line applications. openssl现在的状态不佳自从心脏出血事件之后可谓是墙倒众人推网上也有好多人说它的代码写的很差没有良好的代码规范基于这些理由又是项目中使用的所以还是不去冒这个险了。
地址http://www.openssl.org/
OpenSSL是一个安全套接字层密码库其包括常用的密码算法、常用的密钥生成和证书封装管理功能及SSL协议并提供了丰富的应用程序以供测试。
OpenSSL 是一个开源项目其组成主要包括一下三个组件
openssl多用途的命令行工具libcrypto加密算法库libssl加密模块应用库实现了ssl及tls
安装参考https://blog.csdn.net/weixin_39274753/article/details/107958283
应用如下
1.单向散列加密应用
OpenSSL单向加密的子命令为dgst其语法如下
openssl dgst [-md5|-md4|-md2|-sha1|-sha|-mdc2|-ripemd160|-dss1] [-c] [-d] [-hex] [-binary] [-out filename] [-sign filename] [-keyform arg] [-passin arg] [-verify filename] [-prverify filename] [-signature filename] [-hmac key] [file…]
其常用的选项为
[-md5|-md4|-md2|-sha1|-sha|-mdc2|-ripemd160|-dss1]指定一种单向加密算法
-out FILENAME将加密的内容保存到指定的文件中
单向加密除了 openssl dgst 工具还有 md5sumsha1sumsha224sumsha256sum sha384sumsha512sum
生成指定文件的特征码案例openssl dgst -md5 /tmp/fstab
md5sum /tmp/fstab
echo hello,world | md5sum
echo hello,world | openssl dgst -md5
2.对称加密算法应用
OpenSSL一共提供了8种对称加密算法其中7种是分组加密算法仅有的一种流加密算法是RC4。这7种分组加密算法分别是AES、DES、Blowfish、CAST、IDEA、RC2、RC5。利用OpenSSL作对称加密需要使用其子命令enc其用法为
openssl enc -ciphername [-in filename] [-out filename] [-pass arg] [-e] [-d] [-a/-base64] [-A] [-k password] [-kfile filename] [-K key] [-iv IV] [-S salt] [-salt] [-nosalt] [-z] [-md] [-p] [-P] [-bufsize number] [-nopad] [-debug] [-none] [-engine id]
其中常用的选项为
-e加密
-d解密
-ciphernameciphername为相应的对称加密算法名字如-des3、-ase128、-cast、-blowfish等等。
-a/-base64使用base-64位编码格式
-salt自动插入一个随机数作为文件内容加密默认选项
-in FILENAME指定要加密的文件的存放路径
-out FILENAME指定加密后的文件的存放路径
加密字符串案例echo hello,world | openssl enc -aes128 -e -a –salt -in
加解密文件案例openssl enc -des3 -e -a -in /etc/fstab -out /tmp/fstab
openssl enc -d -des3 -a -salt -in /tmp/fstab
3.非对称加密算法应用
OpenSSL一共实现了4种非对称加密算法包括DH算法、RSA算法、DSA算法和椭圆曲线算法EC。DH算法一般用户密钥交换。RSA算法既可以用于密钥交换也可以用于数字签名。
利用openssl命令的子命令genrsa生成私钥然后再使用子命令rsa私钥中提取公钥。
genrsa的语法如下
openssl genrsa [-out filename] [-passout arg] [-des] [-des3] [-idea] [-f4] [-3] [-rand file(s)] [-engine id] [numbits]
常用选项
-out FILENAME将生成的私钥保存至指定的文件中
[-des] [-des3] [-idea]指定加密算法
numbits指明生成的私钥大小默认是512
通常来说秘钥文件的权限一般只能由管理员访问因此可以结合umask命令来设置生成的密钥文件的权限如
(umask 077;openssl genrsa -out CA.key 4096)
随后可利用rsa子命令生成的私钥文件中提取公钥rsa子命令的语法为
openssl rsa [-inform PEM|NET|DER] [-outform PEM|NET|DER] [-in filename] [-passin arg] [-out filename] [-passout arg] [-sgckey] [-des] [-des3] [-idea] [-text] [-noout] [-modulus] [-check] [-pubin] [-pubout] [-engine id]
常用选项为
-in FILENAME指明私钥文件的存放路径
-out FILENAME指明将公钥的保存路径
-pubout根据提供的私钥从中提取出公钥
使用案例openssl rsa -pubout -in CA.key
利用公钥加密、私钥解密数据
使用rsautl进行加密和解密操作语法如下
openssl rsautl [-in file] [-out file] [-inkey file] [-pubin] [-certin] [-sign] [-verify] [-encrypt] [-decrypt] [-pkcs] [-ssl] [-raw] [-hexdump] [-asn1parse]
openssl rsautl -h
Usage: rsautl [options]
-in file input file 输入文件
-out file output file 输出文件
-inkey file input key 指定私有密钥文件格式是RSA私有密钥文件
-keyform arg private key format - default PEM 指定私钥格式
-pubin input is an RSA public 指定输入的是RSA公钥
-certin input is a certificate carrying an RSA public key 指定输入的是证书文件
-ssl 使用SSLv2的填充方式
-raw 不进行填充
-pkcs 使用V1.5的填充方式(默认)
-oaep 使用OAEP的填充方式
-sign 使用私钥做签名
-verify 使用公钥认证签名
-encrypt 使用公钥加密
-decrypt 使用私钥解密
-hexdump 以16进制打印
-engine e 指定三方库或者硬件设备
-passin arg pass phrase source 传递密码来源
操作示例
/*创建需要加密的文件*/
echo 123456789 hello world! plain.txt
/*生成RSA密钥采用des3对称加密私钥*/
openssl genrsa -des3 -passout pass:123456 -out RSA.pem
/*提取公钥*/
openssl rsa -in RSA.pem -passin pass:123456 -pubout -out pub.pem
/*使用RSA作为密钥进行加密实际上使用其中的公钥进行加密*/
openssl rsautl -encrypt -in plain.txt -inkey RSA.pem -passin pass:123456 -out enc.txt
/*使用RSA作为密钥进行解密实际上使用其中的私钥进行解密*/
openssl rsautl -decrypt -in enc.txt -inkey RSA.pem -passin pass:123456 -out replain.txt
4.生成随机数
openssl命令也支持生成随机数其子命令为rand对应的语法为
openssl rand [-out file] [-rand file(s)] [-base64] [-hex] num
常用选项有
-base64以base64编码格式输出
-hex使用十六进制编码格式
-out FILE将生成的内容保存在指定的文件中
使用案例openssl rand -base64 10
5.加密密码
OpenSSL还支持生成密码的hash离散值其子命令为passwd语法如下
openssl passwd [-crypt] [-1] [-apr1] [-salt string] [-in file] [-stdin] [-noverify] [-quiet] [-table] {password}
常用选项为
-salt STRING添加随机数
-in FILE对输入的文件内容进行加密
-stdin对标准输入的内容进行加密
生成密码的hash值案例openssl passwd -1 -salt 123456 PASSWORD
6. 数字签名
和非对称加密相反如果是用私钥进行加密公钥解密叫做数字签名因为私钥只有一份用公钥解密出来验证确认是你用这个私钥做的签名这就是签名和验证。
先用pkcs8子命令提取出pkcs8格式的私钥rsa默认生成pkcs1格式的私钥当然也可以直接使用默认的来做签名和验证在用java等一些开发中需要要求私钥是pkcs8格式pkcs8子命令格式以及参数如下
openssl pkcs8
[-inform PEM|DER] [-outform PEM|DER] [-in filename] [-passin arg] [-out filename]
[-passout arg] [-topk8] [-noiter] [-nocrypt] [-nooct] [-embed] [-nsdb] [-v2 alg]
[-v1 alg] [-engine id]
参数说明
-inform PEM|DER 输入文件格式DER或者PEM格式。DER格式采用ASN1的DER标准格式。一般用的多的都是PEM格式就是base64编码格式。
-outform DER|PEM 输出文件格式DER或者PEM格式。
-in filename 输入的密钥文件默认为标准输入。如果密钥被加密会提示输入一个密钥口令。
-passin arg 输入文件口令保护来源。
-out filename 输出文件默认为标准输出。如果任何加密操作已经执行会提示输入一个密钥值。输出的文件名字不能和输入的文件名一样。
-passout arg 输出文件口令保护来源。
-topk8 通常的是输入一个pkcs8文件和传统的格式私钥文件将会被写出。设置了此选项后位置转换过来输入一个传统格式的私钥文件输出一个PKCS#8格式的文件。
-noiter MAC保护计算次数为1。
-nocrypt PKCS#8密钥产生或输入一般用一个适当地密钥来加密PKCS#8 EncryptedPrivateKeyInfo结构。设置了此选项后一个不加密的PrivateKeyInfo结构将会被输出。这个选项一直不加密私钥文件在绝对必要的时候才能够使用。某些软件例如一些JAVA代码签名软件使用不加密的私钥文件。
-nooct 这个选项产生的RSA私钥文件是一个坏的格式一些软件将会使用。特别的是私钥文件必须附上一个八位组字符串但是一些软件仅仅包含本身的结构体没有使八位组字符串所环绕。不采用八位组表示私钥。
-embed 这个选项产生的RSA私钥文件是一个坏的格式。在私钥结构体中采用嵌入式DSA参数格式。在这个表单中八位组字符串包含了ASN1 SEQUENCE中的两种结构一个SEQUENCE包含了密钥参数一个ASN1 INTEGER包含私钥值。
-nsdb 这个选项产生的RSA私钥文件是一个坏的格式并兼容了Netscape私钥文件数据库。采用NetscapeDB的DSA格式。
-v2 alg 采用PKCS#5 v2.0并指定加密算法默认的是PKCS#8私钥文件被叫做BpbeWithMD5AndDES-CBC该算法用56字节的DES加密但是在PKCS#5 v1.5中有更加强壮的加密算法的加密算法用口令进行加密。用B-v2选项PKCS#5 v2.0相关的算法将会被使用可以是des3168字节和rc2128字节推荐des3。
-v1 alg 采用PKCS#5 v1.5或pkcs12并指定加密算法。-engine id 指定硬件引擎。
然后用rsautl子命令-sign生成签名-verify验证示例如下
/*提取PCKS8格式的私钥*/
openssl pkcs8 -topk8 -in RSA.pem -passin pass:123456 -out pri.pem –nocrypt
/*使用私钥生成签名*/
openssl rsautl -sign -in plain.txt -inkey pri.pem -out sign.txt
/*使用公钥对签名进行验证*/
openssl rsautl -verify -in sign.txt -inkey pub.pem -pubin -out replain.txt
/*用默认的rsa生成的pkcs1格式私钥生成签名*/
openssl rsautl -sign -in plain.txt -inkey RSA.pem -passin pass:123456 -out sign1.txt
/*用公钥验证签名*/
openssl rsautl -verify -in sign1.txt -inkey pub.pem -pubin -out replain1.txt
/*查看解密内容*/
xxd replain1.txt
3. crypto Crypto is written in C, and is mostly public domain files, although there are a few restrictions on the use of the collection. Crypto includes a set of ECC functions. 基于c的cryptlib这个库在网上的评价还算不错的支持多种加密算法。
这里暂时选择Cryto这个库选择这个库主要是因为现在手头找到的关于它的资料文档最多容易快速上手。
地址http://www.cryptopp.com/
AES算法
#include iostream
#include aes.h#pragma comment( lib, cryptlib.lib )
using namespace std;
using namespace CryptoPP;
int main()
{
//AES中的固定参数是以类AES中定义的enum数据类型而不是成员函数或变量
cout AES Parameters: endl;
cout Algorithm name : AES::StaticAlgorithmName() endl; //Crypto库中一般用字节数来表示长度
cout Block size : AES::BLOCKSIZE * 8 endl;
cout Min key length : AES::MIN_KEYLENGTH * 8 endl;
cout Max key length : AES::MAX_KEYLENGTH * 8 endl;//AES中只包含一些固定的数据而加密解密的功能由AESEncryption和AESDecryption来完成
//加密过程
AESEncryption aesEncryptor; //加密器 unsigned char aesKey[AES::DEFAULT_KEYLENGTH]; //密钥
unsigned char inBlock[AES::BLOCKSIZE] 123456789; //要加密的数据块
unsigned char outBlock[AES::BLOCKSIZE]; //加密后的密文块
unsigned char xorBlock[AES::BLOCKSIZE]; //必须设定为全零memset( xorBlock, 0, AES::BLOCKSIZE ); //置零aesEncryptor.SetKey( aesKey, AES::DEFAULT_KEYLENGTH ); //设定加密密钥
aesEncryptor.ProcessAndXorBlock( inBlock, xorBlock, outBlock ); //加密//以16进制显示加密后的数据
for( int i0; i16; i ) {
cout hex (int)outBlock[i] ;
}
cout endl;//解密
AESDecryption aesDecryptor;
unsigned char plainText[AES::BLOCKSIZE];aesDecryptor.SetKey( aesKey, AES::DEFAULT_KEYLENGTH );
aesDecryptor.ProcessAndXorBlock( outBlock, xorBlock, plainText );for( int i0; i16; i )
{
cout plainText[i];
}
cout endl;return 0;}
DES算法
#include iostream
#include des.h#pragma comment( lib, cryptlib.lib )using namespace std;
using namespace CryptoPP;int main( void )
{cout DES Parameters: endl;cout Algorithm name : DES::StaticAlgorithmName() endl;unsigned char key[ DES::DEFAULT_KEYLENGTH ];unsigned char input[ DES::BLOCKSIZE ] 12345;unsigned char output[ DES::BLOCKSIZE ];unsigned char txt[ DES::BLOCKSIZE ];cout input is: input endl;//首先构造一个加密器DESEncryption encryption_DES;//设置密匙。encryption_DES.SetKey( key, DES::KEYLENGTH );//进行加密encryption_DES.ProcessBlock( input, output );//显示结果//for和for之后的cout可有可无主要为了运行的时候看加密结果//把字符串的长度写成一个常量其实并不被推荐。//这里主要是把output也就是加密后的内容以十六进制的整数形式输出。for( int i 0; i 5; i ){cout hex (int)output[ i ] ends;}cout endl;//构造一个解密器DESDecryption decryption_DES;//加密和解密都是同一个密匙decryption_DES.SetKey( key, DES::KEYLENGTH );//进行解密把结果写到txt中//decryption_DES.ProcessAndXorBlock( output, xorBlock, txt );decryption_DES.ProcessBlock( output, txt );//验证加密前的明文和解密后的译文是否相等。if ( memcmp( input, txt, 5 ) ! 0 ){cerr DES Encryption/decryption failed.\n;abort();}cout DES Encryption/decryption succeeded.\n;return 0;
}
RSA算法
#include randpool.h
#include rsa.h
#include hex.h
#include files.h
#include iostreamusing namespace std;
using namespace CryptoPP;#pragma comment(lib, cryptlib.lib)void GenerateRSAKey( unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed );
string RSAEncryptString( const char *pubFilename, const char *seed, const char *message );
string RSADecryptString( const char *privFilename, const char *ciphertext );
RandomPool GlobalRNG();void main( void ){char priKey[ 128 ] { 0 };char pubKey[ 128 ] { 0 };char seed[ 1024 ] { 0 };// 生成 RSA 密钥对strcpy( priKey, pri ); // 生成的私钥文件strcpy( pubKey, pub ); // 生成的公钥文件strcpy( seed, seed );GenerateRSAKey( 1024, priKey, pubKey, seed );// RSA 加解密char message[ 1024 ] { 0 };cout Origin Text:\t Hello World! endl endl;strcpy( message, Hello World! );string encryptedText RSAEncryptString( pubKey, seed, message ); // RSA 公匙加密coutEncrypted Text:\t encryptedText endl endl;string decryptedText RSADecryptString( priKey, encryptedText.c_str() ); // RSA 私匙解密
}// 生成密钥对
void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed)
{RandomPool randPool;randPool.Put((byte *)seed, strlen(seed));RSAES_OAEP_SHA_Decryptor priv(randPool, keyLength);HexEncoder privFile(new FileSink(privFilename));priv.DEREncode(privFile);privFile.MessageEnd();RSAES_OAEP_SHA_Encryptor pub(priv);HexEncoder pubFile(new FileSink(pubFilename));pub.DEREncode(pubFile);pubFile.MessageEnd();return
}// RSA加密
string RSAEncryptString( const char *pubFilename, const char *seed, const char *message )
{FileSource pubFile( pubFilename, true, new HexDecoder );RSAES_OAEP_SHA_Encryptor pub( pubFile );RandomPool randPool;randPool.Put( (byte *)seed, strlen(seed) );string result;StringSource( message, true, new PK_EncryptorFilter(randPool, pub, new HexEncoder(new StringSink(result))) );return result;
}// RSA解密
string RSADecryptString( const char *privFilename, const char *ciphertext )
{FileSource privFile( privFilename, true, new HexDecoder );RSAES_OAEP_SHA_Decryptor priv(privFile);string result;StringSource( ciphertext, true, new HexDecoder(new PK_DecryptorFilter(GlobalRNG(), priv, new StringSink(result))) );return result;
}// 定义全局的随机数池
RandomPool GlobalRNG()
{static RandomPool randomPool;return randomPool;
}
SHA-256算法
//参考 http://hi.baidu.com/magic475/blog/item/19b37a8c1fa15a14b21bbaeb.html
#include iostream
#include string.h#include sha.h
#include secblock.h
#include modes.h
#include hex.h#pragma comment( lib, cryptlib.lib)using namespace std;
using namespace CryptoPP;void CalculateDigest(string Digest, const string Message);
bool VerifyDigest(const string Digest, const string Message);int main( void )
{string strMessage( Hello world );string strDigest; // 摘要//string strMessage2( hello world ); //只是第一个字母不同//string strDigest2;CalculateDigest( strDigest, strMessage ); //计算Hash值并打印一些debug信息cout the size of Digest is: strDigest.size() endl;cout Digest is: strDigest endl;bool bIsSuccess false;bIsSuccess VerifyDigest( strDigest, strMessage );//通过校验看看strDigest是否对应原来的messageif( bIsSuccess ){cout sussessive verify endl;cout origin string is: strMessage endl endl;}else{cout fail! endl;}//通过strDigest2与strMessage进行校验要是相等//就证明strDigest2是对应的strMessage2跟strMessage1相等。/*CalculateDigest( strDigest2, strMessage2 );bIsSuccess VerifyDigest( strDigest2, strMessage );if( !bIsSuccess ){cout success! the tiny modification is discovered~ endl;cout the origin message is: \n strMessage endl;cout after modify is: \n strMessage2 endl;}*/return 0;
}void CalculateDigest(string Digest, const string Message)
{SHA256 sha256;int DigestSize sha256.DigestSize();char* byDigest;char* strDigest;byDigest new char[ DigestSize ];strDigest new char[ DigestSize * 2 1 ];sha256.CalculateDigest((byte*)byDigest, (const byte *)Message.c_str(), Message.size());memset(strDigest, 0, sizeof(strDigest));//uCharToHex(strDigest, byDigest, DigestSize);Digest byDigest;delete []byDigest;byDigest NULL;delete []strDigest;strDigest NULL;return;
}bool VerifyDigest(const string Digest, const string Message)
{bool Result;SHA256 sha256;char* byDigest;byDigest new char[ sha256.DigestSize() ];strcpy( byDigest, Digest.c_str() );//HexTouChar(byDigest, Digest.c_str(), Digest.size());Result sha256.VerifyDigest( (byte*)byDigest, (const byte *)Message.c_str(), Message.size() );delete []byDigest;byDigest NULL;return Result;
}
获取设备mac物理地址程序
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif // !_CRT_SECURE_NO_WARNINGS//#include stdafx.h
#include windows.h
#include wincon.h
#include stdlib.h
#include stdio.h
#include time.h
#include Nb30.h#include fstream
#include iostream
#include string
#pragma comment(lib,netapi32.lib)int GetMac(char * mac)
{NCB ncb;typedef struct _ASTAT_{ADAPTER_STATUS adapt;NAME_BUFFER NameBuff[30];}ASTAT, *PASTAT;ASTAT Adapter;typedef struct _LANA_ENUM{UCHAR length;UCHAR lana[MAX_LANA];}LANA_ENUM;LANA_ENUM lana_enum;UCHAR uRetCode;memset(ncb, 0, sizeof(ncb));memset(lana_enum, 0, sizeof(lana_enum));ncb.ncb_command NCBENUM;ncb.ncb_buffer (unsigned char *)lana_enum;ncb.ncb_length sizeof(LANA_ENUM);uRetCode Netbios(ncb);if (uRetCode ! NRC_GOODRET)return uRetCode;for (int lana 0; lana lana_enum.length; lana){ncb.ncb_command NCBRESET;ncb.ncb_lana_num lana_enum.lana[lana];uRetCode Netbios(ncb);if (uRetCode NRC_GOODRET)break;}if (uRetCode ! NRC_GOODRET)return uRetCode;memset(ncb, 0, sizeof(ncb));ncb.ncb_command NCBASTAT;ncb.ncb_lana_num lana_enum.lana[0];strcpy((char*)ncb.ncb_callname, *);ncb.ncb_buffer (unsigned char *)Adapter;ncb.ncb_length sizeof(Adapter);uRetCode Netbios(ncb);if (uRetCode ! NRC_GOODRET)return uRetCode;sprintf(mac, %02X-%02X-%02X-%02X-%02X-%02X,Adapter.adapt.adapter_address[0],Adapter.adapt.adapter_address[1],Adapter.adapt.adapter_address[2],Adapter.adapt.adapter_address[3],Adapter.adapt.adapter_address[4],Adapter.adapt.adapter_address[5]);return 0;
}int main(int argc, char* argv[])
{//1.未授权的钥匙int is_authorized 0;char mac_empty[200] asghjkkklll;//电脑mac地std::string key_file_name key.txt;std::ofstream outfile(key_file_name);std::ifstream infile(key_file_name);//写入文件夹std::fstream file(key_file_name, std::ios::out);//文件夹清空outfile std::to_string(is_authorized) std::endl;outfile mac_empty std::endl;char mac_empty1[200] 000000000;//电脑mac地int is_authorized1 0;if (!infile.is_open()){std::cout 文件夹已经打开 std::endl;return -1;}//2.读取密钥信息std::string mac_name;std::string is_authorized2_str;if (!infile.is_open()){std::cout 文件夹已经打开 std::endl;return -1;}std::getline(infile, is_authorized2_str);std::getline(infile, mac_name);const std::string is_authorized11 is_authorized2_str;int is_authorized3 std::stoi(is_authorized11);//3.判定如果软件还未授权则授权if (is_authorized3 0){GetMac(mac_empty);is_authorized 1;std::fstream file(key_file_name, std::ios::out);//文件夹清空outfile is_authorized std::endl;outfile mac_empty std::endl;printf(授权成功/n);}//4.再次读取授权状态if (!infile.is_open()){std::cout 文件夹已经打开 std::endl;return -1;}std::getline(infile, is_authorized2_str);std::getline(infile, mac_name);const std::string is_authorized12 is_authorized2_str;is_authorized3 std::stoi(is_authorized12);if (is_authorized3 1){ char mac_real[200] 1111111;//电脑mac地GetMac(mac_real);if (strcmp(mac_real, mac_name.c_str()) 0){std::cout mac 地址正确 std::endl;}else{std::cout mac 地址错误软件未授权 std::endl;}}printf(The Mac Address is : %s \n, mac_empty);system(pause);return 0;
}
4. botan
这个库没有太多的了解也仅仅是刚知道也是支持多种加密算法的。
地址http://botan.randombit.net/
5. cryptlib
基于c的加密库。
地址http://www.cryptlib.com/
如果应用涉及到 SSL 等 PKI 协议应该使用 openssl如果只是应用一些加密算法则建议使用 Cryptlib。
三、性能与方案选择
加密技术包括两个元素算法和密钥。密钥是用来对数据进行编码和解码的一种方法而算法是将明文与密钥结合产生不可理解的密文的步骤。
单向散列算法诞生较早技术成熟运行速度最快但只能单向加密对称加密算法是指客户端和服务端共用一套密钥用相同的密钥去加密和解密运行速度较快安全性也较高非对称加密算法有公钥和私钥较难破解安全等级最高但运行速度较慢。
常用加密算法性能和安全性对比 通过了解各种算法的实现方式、优缺点及相关应用得出以下结论校验时可以使用单向散列算法如MD5、CRC32一般加密需求时可以使用对称加密算法如AES、DES但加密要求较高时建议选用混合加密策略即用非对称加密算法如RSA来解决对称加密的密钥传输密钥传输完成后A和B之间采用对称加密算法如AES进行通信。这样做既可以保证密钥的安全性也能保证数据正常传输过程中的运行效率。
以上。