关于aes:密码学为什么不推荐在对称加密中使用CBC工作模式

引言这篇文章是我在公司外部分享中一部分内容的具体版本,如题目所言,我会通过文字、代码示例、带你残缺的搞懂为什么咱们不倡议你应用cbc加密模式,用了会导致什么平安问题,即便肯定要用须要留神哪些方面的内容。 注:本文仅从平安角度登程,未思考性能与兼容性等因素工作模式是个啥分组加密的工作模式与具体的分组加密算法没有关系,所以只有应用了cbc模式,不限于AES、DES、3DES等算法都一样存在问题。 以AES-128-CBC为例,能够屏蔽AES算法的外部实现,把AES算法当作一个黑盒,输出明文和密钥返回密文。 因为是分组加密算法,所以对于长的明文,须要依照算法约定的块大小进行分组,AES每一组为16B,不同组之间应用雷同的密钥进行计算的话,会产生一些平安问题,所以为了将分组明码利用到不同的理论利用,NIST定义了若干的工作模式,不同模式对分块的加密解决逻辑会不同,常见的工作模式有: 模式形容ECB(电码本)雷同的密钥分队明文分组进行加密CBC(分组链接)加密算法的输出是上一个密文组和以后明文组的异或CFB(密文反馈)一次解决s位,上一块密文作为下一块加密算法输出,产生伪随机数与明文异或或作为下一单元的密文OFB(输入反馈)相似CFB,仅加密算法的输出是上一次加密的输入,且应用整个分组CTR(技数器)每个明文分组都与一个通过加密的计数器相异或。对每个后续分组计数器递增ECB模式最为简略,假如存在明文分组a、b、c、d 每个分组别离在雷同密钥k进行aes加密后的密文为A、B、C、D,最终明文abcd对应的密文为ABCD,如图所示: ECB模式很简略可能从性能角度讲十分占优,因为分组之间没有关联,能够独立并行计算。但从平安角度来看这种间接将密文分组进行拼接的形式,很可能会被攻击者猜解出明文特色或替换抛弃局部密文块达到明文的替换与截取成果,以下的图十分清晰: <img src="https://9eek-1251521991.cos.ap-chengdu.myqcloud.com/article/img/20230302102403.png" alt="image-20230302102403380" style="zoom:67%;" /> 所以很容易了解ECB也不是举荐应用的工作模式。 CBC有了ECB的前事不忘;后事之师,CBC( Cipher Block Chaining)模式就提出将明文分组先于一个随机值分组IV进行异或且本组的密文又与下一组的明文进行异或的形式,这种形式减少了密文的随机性,防止了ECB的问题,具体过程见图: 加密过程 解释下这个图,存在明文分组a、b、c、d,cbc工作模式是存在执行程序的,即第一个密文分组计算后能力计算第二个分组,第一个明文分组在加密前明文a须要和一个初始分组IV进行异或运算 即 a^IV ,而后再用密钥K进行规范的AES加密,E(a^IV,K) 失去第一组的密文分组A,密文分组A会参加第二组密文的计算,计算过程相似,只不过第二次需将IV替换为A,如此循环,最初失去的密文ABCD即为CBC模式。 解密过程仔细观察CBC的加密过程,须要应用到一个随机分组IV,在规范的加密过程中,IV会被拼接到密文分组中去,假如存在两人甲和乙,甲方给到乙方的密文理论是 (IV)ABCD,乙在拿到密文后提取IV,而后进行下图的解密: 解密过程就是加密过程转变了下方向,注意两个图从abcd到ABCD的箭头方向。第一个密文分组先进行AES解密,失去的两头值咱们计为M_A,M_A再于初始向量IV进行异或失去a,第二个分组反复同样的动作,还是将IV替换为密文分组A,最终可失去明文分组abcd。 CBC有什么问题CBC减少了随机变量IV给密文减少了随机性,增大了密文剖析的难度是不是就平安了呢? 答案当然是不,CBC又引入了新的问题——能够通过扭转密文从而扭转明文。 CBC字节翻转攻打原理解说CBC字节翻转攻打原理非常简单,如图所示: 攻打往往产生在解密过程,黑客通过管制IV和密文分组能够达到批改明文的目标,图中黑客通过替换密文D分组为E分组能够篡改本来明文d为x(可能会波及填充验证,这里先不论),或者同样的情理黑客能够通过管制IV达到批改明文分组a的目标。 举个例子接下来用一个理论例子来演示其原理及危害。 为了保障不便进行原理解说,在加密时会将IV和key写死,防止每次运行的后果不一样。假如存在一个web服务利用,前后端通过Cookie来进行权限校验,cookie的内容为明文admin:0进行AES-128-CBC加密后的密文进行base64编码,数字0代表此时用户的权限为非管理员用户,当admin前面的数字为1时,后端会认为是一名管理员用户。 Cookie内容为:AAAAAAAAAAAAAAAAAAAAAJyycJTyrCtpsXM3jT1uVKU= 此时黑客在晓得校验原理的状况下可利用字节翻转攻打对此服务发动攻打,在不晓得密钥的状况下将cookie明文批改为admin:1,具体过程: AES以16B作为block size进行分块,admin:0在ascii编码下对应的二进制仅为7B,所以在加密时还会对原始明文进行填充直到刚好为16B的整数倍,所以还须要填充9B(填充细节上面再讲),因为CBC还会有IV,所以最终的密文是IV+Cipher,IV16B,cipher16B,总共32B,这里因为只有一个密文分块,所以扭转IV的第7个字节对应明文admin:0数字的地位,或者密文的第7个字节即可扭转明文数字局部的字段,通过一直的尝试,咱们将本来密文IV分组 00改为01,即可胜利翻转明文为1,即cookie明文变为admin:1,从而达到权限晋升的目标。 残缺代码: package com.example.springshiroproject;import org.apache.shiro.crypto.AesCipherService;import org.apache.shiro.util.ByteSource;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.security.Key;import java.util.Arrays;public class MyTest { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { AesCipherService aesCipherService = new AesCipherService(); // 写死密钥 byte[] key = new byte[128/8]; Arrays.fill(key,(byte) '\0'); // 写死的密钥,客户端及黑客未知 String plainText = "admin:0"; // cookie明文内容 byte[] plainTextBytes = plainText.getBytes(); // 写死IV byte[] iv_bytes = new byte[128/8]; Arrays.fill(iv_bytes, (byte) '\0');//// // 通过反射调用能够自定义IV的AES-128-cbc加密办法(原办法为private) Method encryptWithIV = aesCipherService.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredMethod("encrypt",new Class[]{byte[].class, byte[].class,byte[].class,boolean.class}); encryptWithIV.setAccessible(true); ByteSource cipherWithIV = (ByteSource) encryptWithIV.invoke(aesCipherService,new Object[]{plainTextBytes, key,iv_bytes,true}); System.out.println("明文:" + ByteSource.Util.bytes(plainTextBytes).toHex()); // 失常逻辑解密 byte[] cipher = cipherWithIV.getBytes(); System.out.println("原始密文: " + cipherWithIV.toHex()); System.out.println("Cookie内容: " + cipherWithIV.toBase64()); ByteSource decPlain = aesCipherService.decrypt(cipher, key); System.out.println("原始解密后明文:" + new String(decPlain.getBytes())); // 字节翻转攻打 cipher[6] = (byte)0x01; System.out.println("翻转后的密文: " + ByteSource.Util.bytes(cipher).toHex()); System.out.println("翻转后的cookie:"+ ByteSource.Util.bytes(cipher).toBase64()); decPlain = aesCipherService.decrypt(cipher, key); System.out.println("翻转解密后明文:" + new String(decPlain.getBytes())); }}这个例子只讲了一个分块的状况,在理论的场景中可能波及多个分块,而多个分块进行尝试扭转一个密文分组理论会影响两个明文分组,要求一直在雷同地位的向前的密文分组进行变换猜想,十分耗时。 ...

May 23, 2023 · 4 min · jiezi

关于aes:CryptoJs-使用-AES-CBC-加解密数据

AES CBC 模式废话不多说,间接上代码,加密步骤为: 约定 key, 生成本次加密须要的 iv数据体 cbc 加密 encData数据体 base64 编码 encDataBase64ed计算数据体的 hmac{iv, mac, encDataBase64ed} stringify = payloadpayload base64编码传输。payloadBase64ed<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>AesCBC加解密</title> <style> * { box-sizing: border-box; } input, textarea { width: 100%; padding: 10px 20px; border-radius: 10px; } </style></head><body><div style="padding: 0 20px"> <div> <h4>Key</h4> <input type="text" id="key" placeholder="请输出约定的Key"> </div> <div> <h4>密文</h4> <textarea name="encData" id="encData" rows="10" oninput="encDataDec()"></textarea> </div> <div> <h4>明文</h4> <textarea name="decData" id="decData" rows="10" oninput="decDataEnc()"></textarea> </div></div><script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"></script><script> function encDataDec() { let key = document.getElementById("key").value if (key.trim() === "") { alert("请输出约定的Key") return; } let encDataDom = document.getElementById("encData") let decDataDom = document.getElementById("decData") if (encDataDom.value === "") { decDataDom.value = "" return } try { decDataDom.value = AesCBCDecrypt(encDataDom.value, key) } catch (err) { decDataDom.value = err.toString() } } function decDataEnc() { let key = document.getElementById("key").value if (key.trim() === "") { alert("请输出约定的Key") return; } let encDataDom = document.getElementById("encData") let decDataDom = document.getElementById("decData") if (decDataDom.value === "") { encDataDom.value = "" return } try { encDataDom.value = AesCBCEncrypt(decDataDom.value, key) } catch (err) { encDataDom.value = err.toString() } } function AesCBCEncrypt(bizData, key) { let iv = "te21".repeat(4)//16位随机iv let waKey = CryptoJS.enc.Utf8.parse(key) let waIv = CryptoJS.enc.Utf8.parse(iv) let bizDataEnc = CryptoJS.AES.encrypt(bizData, waKey, { iv: waIv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) let bizDataEncBase64 = CryptoJS.enc.Base64.stringify(bizDataEnc.ciphertext) let ivBase64 = CryptoJS.enc.Base64.stringify(waIv) let mac = CryptoJS.HmacSHA256(ivBase64 + bizDataEncBase64, waKey).toString() let payloadJson = { iv: ivBase64, mac: mac, value: bizDataEncBase64 } return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(JSON.stringify(payloadJson))) } function AesCBCDecrypt(payloadEnc, key) { let payloadJson = JSON.parse(CryptoJS.enc.Utf8.stringify(CryptoJS.enc.Base64.parse(payloadEnc))) let waKey = CryptoJS.enc.Utf8.parse(key) let waIv = CryptoJS.enc.Base64.parse(payloadJson.iv) let bizData = CryptoJS.AES.decrypt(payloadJson.value, waKey, { iv: waIv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) return CryptoJS.enc.Utf8.stringify(bizData) }</script></body></html>

April 24, 2023 · 2 min · jiezi

关于aes:AES加解密使用总结

AESAES, 高级加密规范, 是采纳区块加密的一种规范, 又称Rijndael加密法. 严格上来讲, AES和Rijndael又不是齐全一样, AES的区块长度固定为128比特, 秘钥长度能够是128, 192或者256. Rijndael加密法能够反对更大范畴的区块和密钥长度, Rijndael应用的密钥和区块长度均能够是128,192或256比特. AES是对称加密最风行的算法之一. 咱们不去探讨具体的AES的实现, 因为其中要使用到大量的高等数学常识, 单纯的理解AES流程其实也没什么意义(没有数学根底难以了解), 所以咱们明天着重来总结一些应用过程中的小点. 加密模式 - ECB, CBC当然了分组明码的加密模式不仅仅是ECB和CBC这两种, 其余的咱们暂不波及. 下面说的AES是一种区块加密的规范, 那加密模式其实能够了解为解决不同区块的形式和分割. ECBECB能够看做最简略的模式, 须要加密的数据依照区块的大小分为N个块, 并对每个块独立的进行加密 此种办法的毛病在于同样的明文块会被加密成雷同的密文块, 因而, 在某些场合, 这种办法不能提供严格的数据保密性. 通过上面图示例子大家就很容易明确了 CBC咱们的我的项目中应用的就是这种模式, 在CBC模式中, 每个明文块与前一个块的加密后果进行异或后, 在进行加密, 所以每个块的加密都依赖后面块的加密后果的, 同时为了保障第一个块的加密, 在第一个块中须要引入初始化向量iv. CBC是最罕用的模式. 他的毛病是加密过程只能是串行的, 无奈并行, 因为每个块的加密要依赖到前一个块的加密后果, 同时在加密的时候明文中的轻微扭转, 会导致前面所有的密文块都发生变化. 但此种模式也是有长处的, 在解密的过程中, 每个块的解密依赖上一个块的加密后果, 所以咱们要解密一个块的时候, 只须要把他后面一个块也一起读取, 就能够实现本块的解密, 所以这个过程是能够并行操作的. 填充模式AES加密每个块blockSize是128比特, 那如果咱们要加密的数据不是128比特的倍数, 就会存在最初一个分块有余128比特, 那这个块怎么解决, 就用到了填充模式. 上面是罕用的填充模式. PKCS7 / PKCS5PKCS7可用于填充的块大小为1-255比特, 填充形式也很容易了解, 应用需填充长度的数值paddingSize 所示意的ASCII码 paddingChar = chr(paddingSize)对数据进行冗余填充. (前面有解释) ...

December 14, 2021 · 1 min · jiezi

关于aes:AESjs加密解密与C的相互转换

AES简介AES, Advanced Encryption Standard,其实是一套规范:FIPS 197,而咱们所说的AES算法其实是Rijndael算法。 NIST (National INstitute of Standards and Technology) 在1997年9月12日公开征集更高效更平安的代替DES加密算法,第一轮共有15种算法入选,其中5种算法入围了决赛,别离是MARS,RC6,Rijndael,Serpent和Twofish。又通过3年的验证、评测及公众探讨之后Rijndael算法最终入选。 Rijndael算法Rijndael算法是由比利时学者Joan Daemen和Vincent Rijmen所提出的,算法的名字就由两位作者的名字组合而成。Rijndael的劣势在于集安全性、性能、效率、可实现性及灵活性与一体。 背景因为在HTTP中参数都是通过URL或者Body进行传输的,那么就存在信息的裸露问题,这时候很多敏感的信息就须要进行加密,避免敏感信息泄露。 具体实现1、服务端加密/解密public class DecryptStringAES{ /// <summary> /// AES加密算法 /// </summary> /// <param name="input">明文字符串</param> /// <returns>字符串</returns> public static string EncryptByAES(string input) { if (string.IsNullOrWhiteSpace(input)) { return input; } using (RijndaelManaged rijndaelManaged = new RijndaelManaged()) { rijndaelManaged.Mode = CipherMode.CBC; rijndaelManaged.Padding = PaddingMode.PKCS7; rijndaelManaged.FeedbackSize = 128; rijndaelManaged.Key = Encoding.UTF8.GetBytes(Decrypt.Key); rijndaelManaged.IV = Encoding.UTF8.GetBytes(Decrypt.AES_IV); ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(rijndaelManaged.Key, rijndaelManaged.IV); using (MemoryStream msEncrypt = new MemoryStream()) { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) { using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) { swEncrypt.Write(input); } byte[] bytes = msEncrypt.ToArray(); return Convert.ToBase64String(bytes); } } } } /// <summary> /// AES解密 /// </summary> /// <param name="input">密文字节数组</param> /// <returns>返回解密后的字符串</returns> public static string DecryptByAES(string input) { if (string.IsNullOrWhiteSpace(input)) { return input; } var buffer = Convert.FromBase64String(input); using (RijndaelManaged rijndaelManaged = new RijndaelManaged()) { rijndaelManaged.Mode = CipherMode.CBC; rijndaelManaged.Padding = PaddingMode.PKCS7; rijndaelManaged.FeedbackSize = 128; rijndaelManaged.Key = Encoding.UTF8.GetBytes(Decrypt.Key); rijndaelManaged.IV = Encoding.UTF8.GetBytes(Decrypt.AES_IV); ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(rijndaelManaged.Key, rijndaelManaged.IV); using (MemoryStream msEncrypt = new MemoryStream(buffer)) { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, decryptor, CryptoStreamMode.Read)) { using (StreamReader srEncrypt = new StreamReader(csEncrypt)) { return srEncrypt.ReadToEnd(); } } } } } }2、 客户端(JS)应用包 ...

May 12, 2021 · 2 min · jiezi

关于aes:Go-加密解密算法总结

前言加密解密在理论开发中利用比拟宽泛,罕用加解密分为:“对称式”、“非对称式”和”数字签名“。 对称式:对称加密(也叫私钥加密)指加密和解密应用雷同密钥的加密算法。具体算法次要有DES算法,3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法。 非对称加密(公钥加密):指加密和解密应用不同密钥的加密算法,也称为公私钥加密。具体算法次要有RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。 数字签名:数字签名是非对称密钥加密技术与数字摘要技术的利用。次要算法有md5、hmac、sha1等。 以下介绍golang语言次要的加密解密算法实现。 md5MD5信息摘要算法是一种被宽泛应用的明码散列函数,能够产生出一个128位(16进制,32个字符)的散列值(hash value),用于确保信息传输残缺统一。 func GetMd5String(s string) string { h := md5.New() h.Write([]byte(s)) return hex.EncodeToString(h.Sum(nil))}hmacHMAC是密钥相干的哈希运算音讯认证码(Hash-based Message Authentication Code)的缩写, 它通过一个规范算法,在计算哈希的过程中,把key混入计算过程中。 和咱们自定义的加salt算法不同,Hmac算法针对所有哈希算法都通用,无论是MD5还是SHA-1。采纳Hmac代替咱们本人的salt算法,能够使程序算法更标准化,也更平安。 示例 //key随便设置 data 要加密数据func Hmac(key, data string) string { hash:= hmac.New(md5.New, []byte(key)) // 创立对应的md5哈希加密算法 hash.Write([]byte(data)) return hex.EncodeToString(hash.Sum([]byte("")))}func HmacSha256(key, data string) string { hash:= hmac.New(sha256.New, []byte(key)) //创立对应的sha256哈希加密算法 hash.Write([]byte(data)) return hex.EncodeToString(hash.Sum([]byte("")))}sha1SHA-1能够生成一个被称为音讯摘要的160位(20字节)散列值,散列值通常的出现模式为40个十六进制数。 func Sha1(data string) string { sha1 := sha1.New() sha1.Write([]byte(data)) return hex.EncodeToString(sha1.Sum([]byte("")))}AES密码学中的高级加密规范(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采纳的一种区块加密规范。这个规范用来代替原先的DES(Data Encryption Standard),曾经被多方剖析且广为全世界所应用。AES中常见的有三种解决方案,别离为AES-128、AES-192和AES-256。如果采纳真正的128位加密技术甚至256位加密技术,蛮力攻打要取得成功须要消耗相当长的工夫。 ...

September 23, 2020 · 5 min · jiezi

js使用AES加密PHP使用Openssl解密

最近遇到的几个网站在提交密码时提交的已经是密文,也就是说在网络上传输的密码是密文,这样提升了密码在网络传输中的安全性。 后端语言加解密已经有很成熟的方案了,前端的话Google之前出过一个crypto-js,为浏览器的js提供了加解密方案。今天一起来了解一下基于AES的前后端加解密流程。 Javascript安装npm包 npm install crypto-js加密代码 const CryptoJS = require("crypto-js");const key = CryptoJS.enc.Latin1.parse('1234567812345678');const iv = CryptoJS.enc.Latin1.parse('1234567812345678');const encoded = CryptoJS.AES.encrypt('hahaha', key, { iv: iv, mode: CryptoJS.mode.CBC, adding: CryptoJS.pad.ZeroPadding}).toString()console.log('encoded', encoded)解密代码 const key = CryptoJS.enc.Latin1.parse('123456781234567812345678');const iv = CryptoJS.enc.Latin1.parse('1234567812345678');const decoded = CryptoJS.AES.decrypt(encoded, key, { iv: iv, mode: CryptoJS.mode.CBC, adding: CryptoJS.pad.ZeroPadding}).toString(CryptoJS.enc.Utf8)console.log('decoded', decoded);输出如下 encoded 6bcgYd4f4ZgNOQH/3tqMpg==decoded hahahaPHP直接使用openssl解密即可,代码如下: $encoded = '6bcgYd4f4ZgNOQH/3tqMpg==';$key = '123456781234567812345678';$iv = '1234567812345678';var_dump(openssl_decrypt($encoded, 'AES-192-CBC', $key, 0,$iv));输出结果: string(6) "hahaha"注意事项 AES加密位数跟密钥key有关, 以下是密钥位数和加密对应关系 16 => AES-12824 => AES-19232 => AES-256iv是初始化向量. 超过16字节或者不足16字节都会被补足16字节或者截断到16字节。由于AES是块加密,铭文被分割成固定长度的块(一般是16字节长度),所以iv也是16字节。CBC是加密模式

July 11, 2019 · 1 min · jiezi

nodejs使用aes128ecb加密如何在c中解密

最近需要在nodejs上加密jwt,C#端解密jwt得到用户信息 class JwtService extends Service { encrypt(content) { const secretkey = this.app.config.jwt.key // 唯一(公共)秘钥 const cipher = crypto.createCipher('aes-128-ecb', secretkey) // 使用aes128加密 let enc = cipher.update(content, 'utf8', 'hex') // 编码方式从utf-8转为hex; enc += cipher.final('hex')// 编码方式转为hex; return enc }}却发现C#端怎么也解密不了,一直报错,改了一整天,后来终于发现,nodejs端加密用的key其实在使用之前已经使用md5加密了一次,服务端如果需要使用这个key解密,则需要也同样使用MD5加密 public static string AesDecrypt(string content, string key) { // nodejs aes加密默认的key使用了md5加密,所以C#解密的key也要默认使用md5 MD5 md5 = new MD5CryptoServiceProvider(); byte[] output = Encoding.UTF8.GetBytes(key); byte[] keyArray = md5.ComputeHash(output); byte[] toEncryptArray = HexStringToBinary(content); RijndaelManaged des = new RijndaelManaged(); des.Key = keyArray; des.Mode = CipherMode.ECB; des.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = des.CreateDecryptor(); byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); return Encoding.UTF8.GetString(resultArray); }代码使用了一个函数把16进制转成字节数组 ...

July 8, 2019 · 1 min · jiezi

永强持续教你加解密对称篇二

永强被吓坏了!因为永强看到了某个微信群有人指出公众号里上篇打酱油附送的那篇文章《震惊!北京一男子竟然用swoole做了这种事!》的内容实在是太low了,这种low文章就不要拿出来发了。 但是给永强留下了面积巨大的心理阴影。他尚未见识过社交网络的恶毒嘴脸。 所以永强本来昨天要发的文章拖到了今天,但是永强实在是怕了,他怕被人喷了被人骂了。虽然我百般鼓励,但他还是心有余悸。尽管我都已经直接告诉他“你那玩意根本就没人看”了,他还是依然不敢发了。然后我不得不摆出PS大法给他做了一张图,他看了看那张图后又收了我6.66元的微信红包,决定继续鼓起勇气发了。 是时候表现一下我的PS精湛技术了! “我们历经千辛万苦,摸打滚爬过数不清的错误,发射了不知道多少枚长征系列,耗费了一代航天人的心血,终于看到了地球与月亮通信的曙光,然后就在五分钟,我们惊讶地发现,原来老王的smartmesh技术早就实现了,甚至连地球文明与外形文明的通信都给出了完美的解决方案…” ——— 尼古拉斯 * 赵永强 众所周知,作为精通各种技术表演的我早就已经不屑于采用ppt的方式吹牛了,一般我都是直接上机操作表演,当然了,程序都是提前写好了的,全是mock的假数据,脚本实现自动化,无论谁来操作都是流畅的,一切都是完美的! 作为一个追求完美的人,我还得继续接着吹上次聊到结尾,好像是遗留了两个问题: ecb、cfb、cbc等这些后缀是什么意思iv向量又是什么意思鉴于DES和3DES已经属于不建议使用的方法了,所以这次我们直接用AES加密进行装逼表演,比如下面这坨代码,你们复制粘贴走运行一下: <?php$ava_methods = openssl_get_cipher_methods();// 选用aes-128-ecb$my_method = 'aes-128-ecb';if ( !in_array( $my_method, $ava_methods ) ) { exit( '错误的加密方法'.PHP_EOL );}// 加密用的密码$key = "1234567812345678";// 加密的内容$data = "12345678abcdxxoo12345678abcdxxoo";$enc_data = openssl_encrypt( $data, $my_method, $key, OPENSSL_RAW_DATA );$hex = bin2hex( $enc_data );echo $hex.' : '.strlen( $hex ).PHP_EOL;我这里运行结果是: c1391e34caf38f8c2a477cbda3772533c1391e34caf38f8c2a477cbda3772533d96aa42b59151a9e9b5925fc9d95adaf : 96分析一下上面代码:这次我们选用的加密方法是AES-128-ECB,这个128是什么意思?128就是密钥长度的意思:128bit;如果你留心的话,还会注意到有aes-192-ecb和aes-256-ecb,其实就是指加密密钥长度为192bit、256bit,然后是值得注意的一个地方是: $enc_data = openssl_encrypt( $data, $my_method, $key, OPENSSL_RAW_DATA );最后一个参数是OPENSSL_RAW_DATA,如果选用这个option的话,经过加密后的数据会是奇怪的二进制数据,无法直接通过文本方式查看,所以要看的话必须先使用bin2hex函数处理一下。 注意了哈,我选的这个密钥1234567812345678是有特殊用意的,这个密钥的长度是16字节也就是128bit,而我们选用的aes加密方法中要求的密钥长度就是128bit,那么我们尝试将密钥增加几位变成:1234567812345678abc,然后其他代码不做任何改动,再次执行加密,结果如下: c1391e34caf38f8c2a477cbda3772533c1391e34caf38f8c2a477cbda3772533d96aa42b59151a9e9b5925fc9d95adaf : 96就是说用“1234567812345678”和“1234567812345678abc”加密后的数据都是一样的。看起来如果我们选用128bit密钥长度的话,一旦密钥长度超过128bit后面多余的部分会被直接无视掉~~~ ...

June 18, 2019 · 1 min · jiezi

永强教你加解密对称篇一

大家好,我是永强,就是老李之前经常给你们说的区块链大神、大学肄业却依然大公司iOS主程一波儿流、只生活在老李口中尚未真实露面的骗钱高手、老王的左膀右臂 ——— 赵永强。我和尼古拉斯赵四之间并没有什么强关联,我只是单方面认识他而已。 之前老李企图让我发表一些关于如何进行高端骗工资骗钱的教程,被我义正言辞地拒绝了: 毕竟是毕生绝学,不能就这么轻而易举地教给你们不过后面有时间我可以给大家出一些关于“如何在公司混日子还能升职加薪”的入门级教程,传男不传女,独家绝技!敬请期待! 言归正传,那个一直以来我对加解密技术都是耿耿于怀的,因为很多年前有一次面试中被这东西给坑掉了,虽然我后来就自己对加解密中一些自己不懂的地方请教了对方而且他也没有给我讲清楚… 事情都过去好几年了,本人自我感觉已经一定程度掌握了一些关于加密的高端技术,因为决定出来装一波儿逼,时间比较紧张,我打算赶在2020年农历新年之前把逼装完,你们要注意配合。 我知道老李之前在社区发表了一些关于加密啊、解密啊之类的东西,甚至还扯上了什么DH什么ECDH,又是质数又是椭圆曲线,不过这并不与本系列产生冲突,这并不重要,不要在意这些细节,他那个too young too simple,sometimes naive… 这将是一个大概由四篇左右的文章组成的系列文章,所以在正式开始之前,我不得不强调一点 ——— 如下这几门学科的基础理论知识: 《离散数学》《微分与积分》《空间几何》《概率论》你并不需要具备。。。 不过你总得知道除了html和css之外的任意一门编程语言。尽管本人精通上到CLanguage下到Perl之类的各种语言,但是本文将采用世界上最好的语言进行一些程序演示,后面老李可能会使用CLanguage和Golang进行其他语言的演示补充。 简单说来呢,加解密技术就是分为两大类: 对称加解密非对称加解密其中,常见的对称加解密算法有DES、3DES、AES;而非对称加解密技术比较典型的则是RSA,就是什么公钥私钥证书什么乱七八糟的。 我们先从对称加解密开始,粗暴地说呢,对称加解密就是“加密和解密的时候用同一个密码”,听起来就非常对称,有没有? 用图表达一下就是: 最一开始的时候,我朝人民一般都是倾向于使用“天王盖地虎”,“宝塔镇河妖”这种加解密技术;然而,美帝用了一种叫做DES的技术进行对称加解密,这玩意一度成为业界通用的对称加解密技术,银行、五角大楼都爱用这玩意,可惜好景不长、世风日下、世态炎凉,这玩意的破解成本越来越低越来越低~~ 于是,为了续命,就又有一些白胡子老头给DES打补丁,缝缝补补搞出来一个玩意叫做3DES,继续用,又不是不能用…这个顾名思义就行了,别打我,真的:3DES就是用DES处理(注意是处理,我没说是加密)了三次的意思。就目前看来,3DES实际上用的可能也并不是十分广泛了,所以如果大家在选择对称加解密技术的时候,尽量避开DES和3DES就可以了。 呵呵,喜新厌旧的沙雕人类…虽然DES已经没人用了,但毕竟也是辉煌过,我觉得还是得动手表演一波儿。我们知道,在php7里,原来的mcrypt系列加解密已经被放弃掉了,官方建议我们使用openssl系列来进行加解密,所以确保你的PHP环境里安装了openssl标准扩展。 <?php// 这个函数打印出来openssl支持的所有加密方法以及模式的组合$arr_ava_methods = openssl_get_cipher_methods();print_r( $arr_ava_methods );文件保存成test.php后,执行一把:php test.php | grep des,结果你们感受一下: 其中带有ede的,比如des-ede*这样的就表示是3DES。还有这么多奇奇怪怪的后缀是什么含义?回头再说…又不是不能用。 筛选一下,我们看des(非des3)有几种带着尾巴的具体方法: des-cbcdes-cfb*(注意后面的通配符星号)des-ecbdes-ofb我们先用传统des方法继续进行装逼表演: <?php// 我们就选用des-ecb方法进行一次des加密$ava_methods = openssl_get_cipher_methods();$my_method = 'des-ecb';if ( !in_array( $my_method, $ava_methods ) ) { exit( '错误的加密方法'.PHP_EOL );}$key = "123456";$data = "helloMOTO";echo "明文:".$data.PHP_EOL;$enc_data = openssl_encrypt( $data, $my_method, $key );echo "密文:".$enc_data.PHP_EOL;$dec_data = openssl_decrypt( $enc_data, $my_method, $key );echo "明文:".$dec_data.PHP_EOL;保存为test.php执行一把: ...

June 12, 2019 · 1 min · jiezi

一套简单的基于-RSA-AES-加密机制的前端解决方案

前言因公司现有后台管理系统项目需对部分网络请求接口的重要数据进行加密,整合了一套简单的基于 RSA + AES 加密机制的前端解决方案。 参考文献:crypto 廖雪峰crypto-js aes 加解密rsa 加解密参考 API:crypto-jsJSEncrypt依赖crypto-js: npm i crypto-jsJSEncrypt:npm i jsencrypt加密流程先上图 因项目为后台管理系统,所以这里会有两种业务场景:用户在未登录前是没有鉴权 token 的,需在成功登录并获取 token 后和 encryptKey 一并上传后端,后端才能将 token 与 encryptKey 做绑定。用户已登录成功,页面刷新后将会重新生成 aesKey ,这时候需从 cookie 中获取 token 并和 encryptKey 上传后端,后端重新绑定 token 和 encryptKey。代码encryption.js 封装import CryptoJS from 'crypto-js'import JSEncrypt from 'jsencrypt'const encryptor = new JSEncrypt()// 生成 AESKEYexport const aesKey = createAesKey()export function createAesKey () { const expect = 16 let str = Math.random().toString(36).substr(2) while (str.length < expect) { str += Math.random().toString(36).substr(2) } str = str.substr(0, 16) return str}/** * AES 加密 * @param word 待加密字段 * @param keyStr 加密 key * @returns {string} 返回加密字段 */export function aesEncrypt (word, keyStr) { keyStr = keyStr || aesKey console.log(keyStr) const key = CryptoJS.enc.Utf8.parse(keyStr) let srcs = '' switch (typeof (word)) { case 'string': srcs = CryptoJS.enc.Utf8.parse(word) break case 'object': srcs = CryptoJS.enc.Utf8.parse(JSON.stringify(word)) break default: srcs = CryptoJS.enc.Utf8.parse(word.toString()) } const encrypted = CryptoJS.AES.encrypt(srcs, key, {iv: key, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7}) return encrypted.toString()}/** * AES 解密 * @param word 待解密数据 * @param keyStr 解密 key * @returns {string} 返回解密字符串 */export function aesDecrypt (word, keyStr) { keyStr = keyStr || aesKey const key = CryptoJS.enc.Utf8.parse(keyStr) const decrypt = CryptoJS.AES.decrypt(word, key, { iv: key, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) return CryptoJS.enc.Utf8.stringify(decrypt).toString()}/** * RSA 设置公钥 * @param val 公钥 */export function setPublicKey (val) { encryptor.setPublicKey(val)}/** * RSA 加密 * @param data 待加密数据 * @returns {PromiseLike<ArrayBuffer>} 返回加密字符串 */export function rsaEncrypt (data) { return encryptor.encrypt(data)}总结AES 加解密涉及到的模式(如 CBC、ECB 等)、偏移量和填充等,请参考文中前言提及的文献和 API本文仅为解决方案参考,请结合实际业务需求及业务场景自由发挥 ...

June 5, 2019 · 2 min · jiezi

关于PHP加解密的懒汉入门篇API安全加强篇一

懒汉入门这两点就足以说明这篇文章不想要着有什么高端大气的技术内容,我跟你讲,全是水。不可能有什么质数素数、椭圆曲线加密、迪菲-赫尔曼什么的,不可能有的。 首先我不懂,其次,反正你们也不懂。 不过这里还是要先说一点儿,就是很多泥腿子一直拿md5当加密算法来看待,但实际上md5是一种信息摘要算法(其实就是哈希),不是加密算法,因为md5不可逆,但是加解密是一个可逆的过程,所以以后这种低级错误还是不要犯的为好。 加密技术一直是技术圈中的一个独特领域和分支,其一些原理并不是随随便便就可以理解的来的。如果没有良好的数学底子,怕是很难研究下去。但是,作为一篇水文,不研究原理,仅仅来用一用来实践一把,还是没什么大问题的。 加密分为两大类: 对称加密,常见算法有DES、3DES、AES等等,据说AES是比较屌的最新最常用的算法非对称加密,RSA、DSA、ECDH等等对称加密用粗话说就是用同一个密钥对信息加解密。比如元首要操作东线战场了,给古德里安发了一段电报,大概意思就是“你给我闪开,让我操作!立马南下打基辅!”,但是元首又怕朱可夫给看到这段消息,于是元首就用了一个强壮的密钥123456来加密这段话,然后这段话就变成akjdslfjalwjglajwg了。古德里安收到这坨乱七八糟的玩意后,用123456来解密一下,得到明文“你给我闪开,让我操作!立马南下打基辅!”,然而朱可夫由于抓破脑壳也想不到这个超级密钥123456,所以朱可夫注定一脸懵逼,最终导致基辅60万苏军被奸!但是这里面有一个问题就是元首是如何告诉古德里安私钥是123456的。 两个人提前就商量好了,1941年6月22日的前一天偷偷商量好了。。。两个人不是提前商量好的,而是古德里安到东线后,元首通过打电话、发电报、QQ、微信。。。 。。。对于朱可夫来说,如果对方采用了方案1,那么他也没啥好办法,只能等潜伏在古德里安身边的特工卧底返回123456。由于密钥被暴露了,所以必须换新的密钥,元首这会儿只能走途径2告诉古德里安新的密钥,这会儿逗逼的事情来了,如何对密钥进行加密。答案是不能,此时问题陷入到欲要加密,必先加密的矛盾中。所以,这个密钥是注定要通过明文传输了,只要是明文传输,朱可夫就一定有机会把密钥搞到手。 非对称加密就是解决这个难题而生。密钥换来换去还想不暴露,扯犊子。还是元首和古德里安,这会儿他俩分别生成一对自己的公钥和私钥。这里需要强调的是: 公钥和私钥是成双成对生成的,二者之间通过某种神秘的数学原理连接着,具体是啥,我也不知道公钥加密的数据,只能通过相应的私钥解密;私钥加密的数据,只能通过对应的公钥解密公钥可以颁发给任何人,然而私钥你自己偷偷摸摸藏到自己裤裆里,别弄丢了这会儿就简单了,元首把自己公钥给古德里安,然后古德里安把自己公钥给元首,然后都偷偷摸摸保存好自己的私钥。有一天,元首告诉古德里安“你丫别干了,天天不听我操作!”,然后用古德里安颁发的公钥加密好了,然后让空军到东线直接仍传单,扔的满地都是,古德里安看到后从裤裆里拿出自己的私钥解密,然后就立马请假回家休息了,回去前用元首的公钥加密了如下消息“傻逼,老子还不伺候了!”,然后让空军回去撒了柏林一地,元首看到后从裤裆里拿出自己的私钥一解密:“卧槽。。。”。虽然这双方都是大大咧咧的发传单,但是朱可夫只能在旁边一脸懵逼、生无可恋。因为用于解密的私钥从来不会在外流通,所以,泄露的可能性是0。 但是,有一点是值得说明,那就是无论是对称加密还是非对称加密,都顶不住用机器是强行暴力猜解私钥。一年不行两年,两年不行二十年,二十年不行一百年,总是能猜出来的,这是没有办法的一件事情。大家可以搜一搜关于768bit RSA被KO的事件,是吧。 下面我们从gayhub上扒了一个对称加密的库下来,尝试一把aes对称加密算法,地址如下: https://github.com/ivantcholakov/gibberish-aes-php直接git clone到目录中,然后测试代码如下: <?phprequire 'GibberishAES.php';$pass = '123456';$string = '你好,古德里安,我是希特勒,你赶紧给我滚回来...';GibberishAES::size(256);$encrypted_string = GibberishAES::enc( $string, $pass );$decrypted_string = GibberishAES::dec( $encrypted_string, $pass );echo PHP_EOL."加密后的:".$encrypted_string.PHP_EOL;echo "解密后的:".$decrypted_string.PHP_EOL.PHP_EOL;保存为test.php,运行一下结果如下: 然后我们将上面代码反复运行100,000次,看看耗费多长时间: require 'GibberishAES.php';$pass = '123456';$string = '你好,古德里安,我是希特勒,你赶紧给我滚回来...';GibberishAES::size(256);$start_time = microtime( true );for( $i = 1; $i <= 100000; $i++ ) { $encrypted_string = GibberishAES::enc( $string, $pass ); $decrypted_string = GibberishAES::dec( $encrypted_string, $pass );}$end_time = microtime( true );echo "一共耗时:".( $end_time - $start_time ).PHP_EOL;保存为test.php,运行一下结果如下: ...

April 24, 2019 · 1 min · jiezi

【融云分析】当我们在谈通讯安全时,我们在谈些什么

当谈论通讯安全的时候,通常我们关心的是下面四个问题:1)防止消息窃听当传送的消息是机密内容的时,人们希望给消息加密。这样即使消息在传送过程中被截获,窃听者也无法确切的知道消息内容,从而达到保密的效果。2)防止消息篡改消息在传送过程中,有可能被攻击者篡改内容,这样接收者接到的就是错误的信息,通讯过程中应该提供某种方案防止篡改。3)防止消息伪造攻击者假冒发送者的名义,给接收者发送消息,这种行为称为消息伪造。4)防止否认发送者事后否认自己发送过消息,需要有一种机制来防止这种情况发生。下面,我们将详细分析下这四个问题。防窃听提到加密,很多人的第一反应是下面这样:“自己实现一个加密算法,然后将算法保密,这样就能保证安全。“在密码学的领域,这是个典型的误区。首先,开发高强度的加密算法是非常困难的。普通的算法在外行看起来牢不可破,但是专业破译者却有非常多的工具和攻击方式,使其破绽百出。其次,加密算法的秘密总有一天会公诸于世。到那时,所有基于这个算法的秘密都将被泄露。实践中使用的加密算法都是公开的,消息传递依靠保密的密钥来确保消息不被破解。正因此,它们经过攻击者长期尝试仍未被破解,所以保密强度较高。常用的加密体系分为三类,对称加密、非对称加密和混合加密。1.1 对称加密对称加密是指加密和解密用的是同一个密钥。这个密钥只有发送者和接收者知晓,其他没有密钥的人无法解密消息。常见的对称加密算法有 DES 、 3DES 和 AES 等。随着计算机硬件的进步,使用暴力破解法已经能在现实时间中完成对 DES 的破解; 3DES 处理速度不高,此外在安全性方面也逐渐显现出了些问题;目前应该选用的算法是 AES 。1.2 非对称加密与对称加密不同,非对称加密算法需要两个密钥——公钥和私钥。公钥和私钥是一对。公钥加密,对应的私钥才能解密,反之亦然。前面的场景适用于防窃听,后面的场景适用于数字签名,也就是防止否认。实现机密消息交换的基本过程是:甲方生成一对密钥并将其中一个作为公钥向其它方公开,得到该公钥的乙方使用该公钥对消息进行加密再发送给甲方,甲方再使用自己的私钥对消息进行解密。网络中的其他窃听者虽然也能拿到甲方的公钥,但是加密后的消息只有私钥才能解开,所以他们无法破译消息。最常使用的非对称加密算法是 RSA 。1.3 混合加密比较一下对称加密和非对称加密各自的特点:对称加密处理速度快,但是由于通讯双方使用的是同一个密钥,存在密钥配送困难的问题。要求通讯双方线下交换密钥是不现实的,而线上配送又存在被窃听的风险。非对称加密的公钥本身就是可以对外公开的,天然避免了密钥配送的问题;但是非对称加密的处理速度远远低于对称加密。混合加密体系是将上述两种优势相结合的办法。先看一下加密过程。通讯过程中传送了两部分内容:一部分是使用对称加密算法加密的消息,另一部分是对称加密的密钥。其中对称加密的密钥是由接收方的公钥加密过的,这样除了接收方之外,任何其他人都不能解开对称加密的密钥,从而也无法解开加密的消息。加密过程相比于要传送的消息本身,对称密钥的长度要短得多。非对称加密的处理速度慢,所以只用来加密对称密钥,而很长的消息则用处理速度快的对称算法来加密。下面是解密过程。先把对称加密的密钥和加密后消息这两部分分离开。对称密钥之前是用接收者的公钥加密的,所以只能使用接收者的私钥进行解密。对称密钥解出来之后,就可以对消息密文进行解密了,从而得到消息明文。防篡改通讯过程中,接收方有时候会有这样的疑问:“我接收到的消息确实就是发送者发过来的那条吗?在传输的过程中会不会已经被攻击者给改写了?“这是对消息完整性的挑战。实践中一般使用摘要算法来应对这种挑战。摘要算法有如下重要特性。第一,输入任意长度的字符串,输出固定长度的字符串。比起要传输的消息长度来说,输出的固定长度通常很短,因此很容易进行处理。第二,相同的输入总是对应相同的输出。发送方对消息进行摘要处理,同时把摘要附在消息里发送出来。接收方收到之后用同样的摘要算法对消息进行处理,再把计算出来的摘要和收到的摘要进行对比,如果不一致,就能知道消息已被篡改。第三,给定一个字符串 A ,经过摘要算法处理后的串 B ,很难找到一个字符串 C ,使其摘要后的串和串 B 相同。这个重要的特性称为抗碰撞性(弱抗碰撞性)。这条特性使得攻击者在篡改消息后,很难再计算出同样的摘要,从而规避摘要算法的检查。第四,这种转换具有单向性,即不能通过输出串倒推出输入串。常用的摘要算法包含 MD4 、 MD5 、 SHA-1 和 SHA-2 (包含 SHA-256 、SHA-384 和 SHA-512 )。上述算法中目前唯有 SHA-2 算法的强抗碰撞性尚未被攻破。防伪造防伪造指的是"消息来自正确的发送者”。防篡改关注的是消息内容,防伪造关注的是消息发送者本身。防篡改关注的是消息的完整性( integrity ),防伪造关注的是消息的认证( authentication )。消息认证码( Message Authentication Code )是一种既能检查消息完整性,又能做身份验证的技术,取三个单词的首字母,简称为 MAC 。实践中经常使用与密钥相关的摘要算法来实现消息认证码。消息认证码的使用步骤如下:发送者和接收者事先共享密钥;发送者使用共享密钥对消息计算 MAC 值;发送者将消息和 MAC 一起发给接收者;接收者使用共享密钥对接收到的消息计算 MAC 值;接收者将计算的 MAC 值跟接收到的 MAC 值做比较;由于攻击者没有共享密钥,所以无法跟接收者算出一样的 MAC 值。跟对称密钥一样,这里同样面临密钥配送的问题,我们仍然可以采用非对称加密的方式进行密钥配送。除此之外, Diffie-Hellman 算法也是常用的密钥交换方式。防否认想象一下这个场景, Bob 收到了一张 Alice 发来的五百万元的借条。使用事先约定好的共享密钥, Bob 计算出的 MAC 值跟借条里收到的 MAC 值一致,这表明消息没有被篡改,同时消息也不会是第三方伪造的,那么就没有任何后顾之忧了吗?并不是这样。问题在于共享密钥是两个人持有的,因此能算出正确 MAC 值的并不只是 Alice , Bob 也能。如果 Alice 声称自己没有发过这样的借条,那作为第三方仲裁者来说,无法证明借条是 Alice 生成的还是 Bob 生成的。我们需要寻求一种解决方案, Alice 使用的签名是由只有她自己才知道的密钥生成,同时别人还能顺利解开。这样别人无法伪造 Alice 的签名,同时还能验证这个签名。看上去是不是有点熟悉?没错,就是之前介绍过的非对称加密。Alice 使用自己的私钥对消息进行签名(加密),同时对外发布对应的公钥。无论是 Bob 还是第三方仲裁者,都可以使用公钥对签名进行验证(解密)。这种方案称为数字签名。后话到目前为止,看上去我们解决了之前提出的四个问题,但是通讯安全领域的问题还远不止这些。比如怎么验证公钥的可靠性?比如怎么才能生成一个可靠的随机数?再延伸下去我们会涉及到证书,认证机构和随机数的分级等领域,这里就不再一一展开了。最后,请大家记住一句话:只有完美的密码,没有完美的人。不管多精密的系统,在确保整体安全方面,人是一个特别巨大的弱点。很多时候,最脆弱的环节并不是各种算法,而是人类自己。 ...

April 10, 2019 · 1 min · jiezi

AES128/ECB/PKCS5Padding 的实现

AES的相关基础知识直接看WikiPedia:高级加密标准附上 C/C++ 可用代码:AES_Cipher

February 28, 2019 · 1 min · jiezi

Flutter使用Cipher2插件实现AES加解密

Flutter是当下最流行的新兴APP跨平台开发架构。学习需趁早。因为我的项目需要使用AES加解密,而flutter package中并没有支持Dart 2的AES加密库,所以写了Cipher2插件并拿出来开源给大家用。本文介绍如何使用Cipher2插件在Flutter app中实现AES加密解密。本文不讲述如何安装配置Flutter开发环境。如有需要我会写关于安装配置flutter开环环境的文章。Cipher2插件地址:https://pub.dartlang.org/pack…https://github.com/shyandsy/c…各位如果有其他加密算法需求,请在github发issue,我会尽快跟进。PR is welcome!创建项目打开cmd命令行,cd命令定位到你想要创建项目的目录。然后创建flutter app项目flutter create cipher2_test用vscode打开项目目录安装Cipher2插件打开上图中pubspec.yaml文件的dependencies中,添加如下内容。然后ctrl + s保存,vscode会自动为你安装好插件。dependencies: flutter: sdk: flutter cipher2: anyCipher2的API解释Cipher2插件目前支持AES加密的cbc(128位 padding7)模式和gcm模式(128位)。插件提供了5个方法来实现加密解密。本插件所有字符串均使用UTF8编码。在处理第三方密文的时候,请注意字符串编码,以免不必要的麻烦。AES cbc 128位padding7加密/Cipher2.encryptAesCbc128Padding7参数: plainText: 被加密字符串 key:128 bit字符串 iv: 128 bit字符串返回: 经过base64编码的密文字符串/String encryptedString = await Cipher2.encryptAesCbc128Padding7(plainText, key, iv);AES cbc 128位padding7解密/Cipher2.decryptAesCbc128Padding7参数: encryptedString: base64编码的密文字符串 key:128 bit字符串 iv: 128 bit字符串返回: 明文字符串/String decryptedString = await Cipher2.decryptAesCbc128Padding7(encryptedString, key, iv);生成GCM模式的nonceString nonce = Cipher2.generateNonce()AES gcm 128位加密/Cipher2.encryptAesGcm128参数: plainText: 被加密字符串 key:128 bit字符串 nonce: based4编码的92bit nonce,可以用Cipher2.generateNonce()生成返回: 经过base64编码的密文字符串/String encryptedString = await Cipher2.encryptAesGcm128(plaintext, key, nonce);AES gcm 128位解密/Cipher2.decryptAesGcm128参数: encryptedString: base64编码的密文字符串 key:128 bit字符串 nonce: based4编码的92bit nonce,可以用Cipher2.generateNonce()生成返回: 明文字符串/result = await Cipher2.decryptAesGcm128(encryptedString, key, nonce);使用Cipher2插件官方提供了非常简单明了的测试用例,方便加密解密和异常捕获https://github.com/shyandsy/c…// Platform messages are asynchronous, so we initialize in an async method. Future<void> initPlatformState() async { String encryptedString; String plainText = ‘我是shyandsy,never give up man’; String key = ‘xxxxxxxxxxxxxxxx’; String iv = ‘yyyyyyyyyyyyyyyy’; String decryptedString; // 测试AES 128bit cbc padding 7加密 await testEncryptAesCbc128Padding7(); // 测试AES 128bit cbc padding 7解密 await testDecryptAesCbc128Padding7(); // 测试AES 128bit gcm加解密 await testEncryptAesGcm128(); // GenerateNonce(); // 加密,然后解密 try { // 加密 encryptedString = await Cipher2.encryptAesCbc128Padding7(plainText, key, iv); // 解密 decryptedString = await Cipher2.decryptAesCbc128Padding7(encryptedString, key, iv); } on PlatformException catch(e) { encryptedString = “”; decryptedString = “”; print(“exception code: " + e.code); print(“exception message: " + e.message); } // If the widget was removed from the tree while the asynchronous platform // message was in flight, we want to discard the reply rather than calling // setState to update our non-existent appearance. if (!mounted) return; setState(() { _plainText = plainText; _encryptedString = encryptedString; _decryptedString = decryptedString; }); }读一遍test case就会用了。这里不再重复 ...

February 1, 2019 · 2 min · jiezi