之前一直在用RN开发应用,最近Flutter很火,就研究了下,而大家在开发与服务端做接口交互时,为了保证安全性,基本上都会使用加密方式来隐藏通讯内容,非对称加密方式,相比其他固定算法加密方式要安全很多,
非对称加密使用了私钥、公钥来分别对数据进行解密、加密操作,公钥做加密后的数据,只有私钥才能解密,因此会非常的安全。
Flutter使用的是Dart语言,Dart语言和Java非常的像,基本上会使用Java的程序员可以直接上手,部分查下就Ok了。
在Dart中,非对称加密可以使用 encrypt 包,可以直接在 pubspec.yaml
中增加 encrypt: ^2.0.0
即可完成包的引用,当然,不要忘记执行 packages get
做非对称加密,就必须要有公钥和私钥,特别注意一点,当前的 encrypt 为2.0.0版本,当前仅支持 PKCS#1文件格式的密钥
首先我们要生成私钥
openssl genrsa -out private_key.pem 4096
这样就生成了一个私钥,而且就是PKCS#1格式的,如果有PKCS#8格式的,也可以用这个命令来转换为PKCS#1openssl pkcs8 -in pkcs8_private_key.pem -nocrypt -out pkcs1_private_key.pem
第一个坑,在flutter中,密钥文件直接存放在目录中是无法使用File读取到的,只能放在asset中才可以,所以需要在 pubspec.yaml
中增加相关密钥文件才行,例如将密钥文件存放在与 pubspec.yaml
同级的目录 keys
下,则需要在 pubspec.yaml
中增加如下代码
assets:
- keys/private_key.pem
- keys/public_key.pem
之后我们可以在代码中使用
String publicKeyString = await rootBundle.loadString('keys/public_key.pem');
来获取到公钥的文本,再通过parser = RSAKeyParser();
RSAPublicKey publicKey = parser.parse(publicKeyString);
来生成公钥,通过final encrypter = Encrypter(RSA(publicKey: publicKey));
创建加密器,再对原始数据加密encrypter.encrypt(srcContent)
解密和加密差不多方式,只不过需要用私钥做解密。
下面放一个加密解密的辅助类
import 'package:encrypt/encrypt.dart';
import 'package:pointycastle/asymmetric/api.dart';
import 'dart:async';
import 'package:flutter/services.dart' show rootBundle;
final parser = RSAKeyParser();
class EncryptHelper {
static Future<String> encode(String src) async {
String publicKeyString = await rootBundle.loadString('keys/public_key.pem');
RSAPublicKey publicKey = parser.parse(publicKeyString);
final encrypter = Encrypter(RSA(publicKey: publicKey));
return encrypter.encrypt(src).base64;
}
static Future<String> decode(String decoded) async {
String privateKeyString = await rootBundle.loadString('keys/private_key.pem');
final privateKey = parser.parse(privateKeyString);
final encrypter = Encrypter(RSA(privateKey: privateKey));
return encrypter.decrypt(Encrypted.fromBase64(decoded));
}
}
基本上再Flutter中的非对称加密就是这样的了,但是记得开发接口的时候,应该是用两套密钥,服务器存储一个私钥,用于解密应用调用接口过来的密文,同时服务器端还需要存储另一套RSA的公钥,用来加密返回的数据,而应用内存储的一个是服务器端私钥的公钥,另一个则是服务端公钥对应的私钥,用来解密服务器端返回的数据,这样通讯就完全通过两套RSA密钥来做安全性保护了。
现在不都是 客户端存公钥,服务端存私钥。客户端公钥加密服务端私钥解密,服务端私钥加密客户端公钥解密。
你好,请问加密参数太长,超过117字节,会提示参数太长,如何分段加密
你的意思是解析出来的不是加密前的吗?
但最终解析出来的都是
—–BEGIN
密钥
—–END
的字符串呀。
找了一圈都没有好用的RSA库
这个是必须要使用pem格式的证书的,用其他的都会报错
是否有其他方式,我最新太忙没有时间搞flutter这块,还没有时间去尝试下有没有别的办法
具体报错信息是 类型不匹配。
对于 报错就在 RSAPublicKey,
final modulus = (sequence.elements[0] as ASN1Integer).valueAsBigInteger;
在rsa.dart文件里的这行。
可不可以不用pem格式的文件呢,直接用hardcode公钥字符串来生成?
如果不可以,那么 需要使用多大的密钥才可以?
具体报错信息呢?使用了多大的秘钥
根据你提供的这个 加密辅助类, 这个过程就一直卡在RSAPublicKey publicKey = parser.parse(publicKeyString); 这里 ,就抛错误了