目录
- 对称加密
- 非对称加密
- 第一步、首先pubspec.yaml中添加依赖
- 第二步、获取公钥私钥文件
- 第三步、在pubspec.yaml文件中添加公钥私钥文件。
- 第四步、实现Encrypt加密解密工具类
- 第五步、使用Encrypt工具类实现加密
- 第六步、项目实际需求,
- 第七步、关于秘钥的格式(非常重要)
- 第八步、使用Encrypt具类实现加密
数据加密有对称加密(对称密钥方案) 和非对称加密(公钥加密) 两种加密方式。
对称加密
在对称加密算法中,加密和解密密钥是相同的。通信双方必须具有相同的密钥才能实现加密解密的全过程。主要目的为了防止数据存储的管理方直接获取敏感信息,是数据存储安全当中重要的一环。
对称加密算法主要有两种形式:分组加密和序列加密。
非对称加密
在非对称加密算法中,需要两个密钥来进行加密和解密,且加密和解密密钥是不同的,分别是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。
公开密钥与私有密钥是成对的,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
非对称加密主要是保证数据传输过程中的数据安全。例如:我们的登录操作过程中的密码传输,银行账户信息传输……。
在Flutter中加密的库非常多,通过这篇博文介绍一下使用频率比较高的encrypt
库,主流的加密方式也都支持。
先看一下常规用法:
第一步、首先pubspec.yaml中添加依赖
dev_dependencies: flutter_test: sdk: flutter # The "flutter_lints" package below contains a set of recommended lints to # encourage good coding practices. The lint set provided by the package is # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^1.0.0 # 全局状态管理 provider: ^6.0.2 # 数据请求 dio: ^4.0.4 # 本地数据持久化 shared_preferences: ^2.0.13 # 前端加密 encrypt: ^5.0.1
第二步、获取公钥私钥文件
在assets
目录下新建rsa_key
文件夹,用来存储我们的公钥私钥文件。
第三步、在pubspec.yaml文件中添加公钥私钥文件。
flutter: # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true # To add assets to your application, add an assets section, like this: assets: - assets/fonts/iconfont.json - assets/rsa_key/rsa_public_key.pem - assets/rsa_key/rsa_private_key.pem # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg - assets/images/home_logo.png
第四步、实现Encrypt加密解密工具类
在lib/utils
目录下新建rsa_encrypt.dart
文件,用来开发我们的加密解密工具类。
import 'dart:convert'; import 'package:encrypt/encrypt.dart'; import 'package:flutter/services.dart'; import 'package:pointycastle/asymmetric/api.dart'; class Encrypt { /// 加密 static encryption(content) async { final parser = RSAKeyParser(); String publicKeyString = await rootBundle.loadString('assets/rsa_key/rsa_public_key.pem'); print('publicKeyString=$publicKeyString'); // 注意这一行的输出 RSAPublicKey publicKey = parser.parse(publicKeyString) as RSAPublicKey; final encrypter = Encrypter(RSA(publicKey: publicKey)); return encrypter.encrypt(content).base64; } /// 解密 static Future<String> decrypt(String decoded) async { final parser = RSAKeyParser(); String privateKeyString = await rootBundle.loadString('assets/rsa_key/rsa_private_key.pem'); final privateKey = parser.parse(privateKeyString) as RSAPrivateKey; final encrypter = Encrypter(RSA(privateKey: privateKey)); return encrypter.decrypt(Encrypted.fromBase64(decoded)); } }
print('publicKeyString=$publicKeyString');
输出的内容如下所示:
至此我们就已经实现了对加密解密工具类的封装。
第五步、使用Encrypt工具类实现加密
void _userLogin() async { /// 数据加密 var password = await Encrypt.encryption(_formData["password"]); print('_formData=$password'); }
到这里这篇博客所介绍的内容网上基本一搜一大把,希望大家能继续接着往下看。
第六步、项目实际需求,
为了数据安全起见,我们所采用的的加密方案是一密一用
,也就是说,生成的私钥公钥我们只进行一次加密解密操作之后就回废弃,下次使用会重新生成新的公钥和私钥。这样的话前端生成公钥私钥肯定是不行的,所以公钥私钥都是在后端生成,每次进行加密之前先向后端发起数据请求,拿到公钥之后再进行加密。因此,我们的工具类我们就可以调整为如下所示:
import 'dart:convert'; import 'package:cyber_security/utils/http.dart'; import 'package:encrypt/encrypt.dart'; import 'package:flutter/services.dart'; import 'package:pointycastle/asymmetric/api.dart'; class Encrypt { /// 公钥 static String pubKey = ''; /// 可以理解为是本次使用的公钥的id static String key = ''; /// 获取公钥 static getKey() async { /// DioRequest 是我自己封装的数据请求的工具类,如果想学习看下面的连接。 var response = await DioRequest.getInstance().dio.get('/getKey'); var data = jsonDecode(response.toString()); pubKey = data['key']; key = data['_key']; } /// 加密 static encryption(content) async { final parser = RSAKeyParser(); /// start /// 这个格式千万别动,相信我 String publicKeyString = ''' -----BEGIN PUBLIC KEY----- $pubKey -----END PUBLIC KEY----- '''; /// end RSAPublicKey publicKey = parser.parse(publicKeyString) as RSAPublicKey; final encrypter = Encrypter(RSA(publicKey: publicKey)); return encrypter.encrypt(content).base64; } }
还记得前面print('publicKeyString=$publicKeyString');
输出的内容吧。
publicKeyString=-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDb6bKQPmUBcifd5L8hxzbluv50 26g5Jj5l1nYoq8mpxze6+iyIdJTUYbMVOGF4SEwSYL+0f0na4gC8m68n4eSnNUTB ynG9BG8RfLKVPow3nH+0ND7WgE2iek0Z1ECqcDkim8sM3FDmVJLsSuCTlZOiorOx bxI41zKKhL9AoO6sBQIDAQAB -----END PUBLIC KEY-----
第七步、关于秘钥的格式(非常重要)
现在我们说说这个publicKeyString
的格式吧。
第一、中间的秘钥部分可以不换行,且前后可以有多个换行,但是不能有空格;
第二、开始和结束的-----BEGIN PUBLIC KEY-----
、 -----END PUBLIC KEY-----
必须要有;
第三、-----BEGIN PUBLIC KEY-----
前面不允许有空格,最多只能有一个换行;
第四、-----END PUBLIC KEY-----
前面可以有多个换行但是坚决不能有任何空格。
第八步、使用Encrypt具类实现加密
void _userLogin() async { /// 获取公钥 await Encrypt.getKey(); /// 数据加密 var password = await Encrypt.encryption(_formData["password"]); print('_formData=$password'); }