Encryption/Decryption 通过调整 java 代码在 flutter 中
Encryption/Decryption in flutter by adapting java code
我正在尝试在 flutter 中创建一个应用程序,我的示例代码在 java.
这是示例 java 代码要点
https://gist.github.com/kapiljhajhria/72a22ff75e238878f539f7bb21026208
这是我的 flutter 代码要点
https://gist.github.com/kapiljhajhria/795d1a7c7cf1c76ca8e327bf8b2f51de
这里是我所做工作的简要总结
- 生成唯一的会话密钥:AES 随机密钥 256
- 使用步骤 1 中的会话密钥加密 JSON 数据
- 生成 JSON 数据的 SHA256 哈希值
- 使用步骤 1 中的会话密钥加密步骤 3 中生成的哈希值。
- 使用 public 密钥加密会话密钥。 Public 密钥作为 certificate.cer 文件提供。我复制了 String 值并将其作为常量添加到 class 中,以使其更易于使用。不确定这是否是最佳方法。
- 创建了一个带有 3 个参数的 POST 请求。如java代码所示。我认为我正确地完成了这部分。
- 我将获得的响应将使用步骤 1 中的会话密钥进行加密。因此我将不得不解密该响应数据。还没到这一步。
我无法访问发出此请求的服务器。
由于 post 请求是使用网络视图发出的,因此我无法找到一种方法来从我的请求中获取正确的错误。我得到的只是显示“无效请求”的网页
所以我的第一个猜测是我没有正确使用 public 密钥来加密我的会话密钥。
如果那部分是正确的,那么我没有正确加密数据,或者我的加密方法与 java 代码中使用的加密方法不匹配 java 代码。也许我生成的会话密钥不正确。
如有任何帮助,我们将不胜感激。谢谢你。如果您需要我提供任何信息,请告诉我。
看看这个project,这是 Flutter 加密的一个例子,有很好的文档,有 3 种加密类型:
- AES 加密
- Fernet 加密
- Salsa20 加密
我用这个文档作为参考:https://developers.emsigner.com/signer-gateway/api-reference/signing-documents.html
您需要 2 个包:pointycastle
和 x509
,并按如下方式导入它们:
import 'package:pointycastle/export.dart';
import 'package:x509/x509.dart';
那么你需要这些辅助函数:
Uint8List generateSessionKey() {
final r = Random();
return Uint8List.fromList(List<int>.generate(32, (_) => r.nextInt(256)));
}
RSAPublicKey parseCert(String pemData) {
final cert = parsePem(pemData).first as X509Certificate;
final pub = cert.publicKey as RsaPublicKey;
return RSAPublicKey(pub.modulus, pub.exponent);
}
Uint8List encryptUsingPublicKey(RSAPublicKey key, Uint8List data) {
final cipher = PKCS1Encoding(RSAEngine())
..init(true, PublicKeyParameter<RSAPublicKey>(key));
return cipher.process(data);
}
Uint8List encryptUsingSessionKey(Uint8List key, Uint8List data) {
final cipher = PaddedBlockCipher('AES/ECB/PKCS7')
..init(true, PaddedBlockCipherParameters(KeyParameter(key), null));
return cipher.process(data);
}
Uint8List sha256Digest(Uint8List data) {
return SHA256Digest().process(data);
}
然后您将像这样构建 3 个参数:
final pem = File('cert2.pem').readAsStringSync();
final publicKey = parseCert(pem);
final sessionKey = generateSessionKey();
final encryptedSessionKey = encryptUsingPublicKey(publicKey, sessionKey);
final jsonString = json.encode(<String, dynamic>{
'FileType': 'PDF',
'SignaturePosition': 'Top-Left',
'AuthToken': 'some token',
'File': '',
'SUrl': 'http://localhost:3000/Success',
'FUrl': 'http://localhost:3000/Error',
'CUrl': 'http://localhost:3000/Cancel',
'ReferenceNumber': 'generate unique reference number',
});
final jsonBytes = utf8.encode(jsonString) as Uint8List;
final encryptedJson = encryptUsingSessionKey(sessionKey, jsonBytes);
final hash = sha256Digest(jsonBytes);
final encryptedHash = encryptUsingSessionKey(sessionKey, hash);
final p1 = base64.encode(encryptedSessionKey);
final p2 = base64.encode(encryptedJson);
final p3 = base64.encode(encryptedHash);
但是,我看到的最大问题是您如何执行 POST,因为您想要在网页中,对吗?并且普通的 flutter web 视图不支持初始 post。看起来确实还有另一个包裹。只需搜索 flutter webview post
.
顺便说一下,如果你不想使用 pointycastle 注册表,你可以重写 encryptUsingSessionKey
而不是 as:
final cipher = PaddedBlockCipherImpl(
PKCS7Padding(),
ECBBlockCipher(AESEngine()),
)..init(true, PaddedBlockCipherParameters(KeyParameter(key), null));
return cipher.process(data);
最后,至少在您了解 Web 视图问题之前,您可以使用 http
来完成 post。但是,让它完成编码参数和设置内容类型的工作,如下:
final response = await http.post(
Uri.parse('https://somewhere/V3_0/Index'),
body: <String, String>{
'Parameter1': p1,
'Parameter2': p2,
'Parameter3': p3,
},
);
print(response.statusCode);
print(response.body);
我正在尝试在 flutter 中创建一个应用程序,我的示例代码在 java.
这是示例 java 代码要点 https://gist.github.com/kapiljhajhria/72a22ff75e238878f539f7bb21026208
这是我的 flutter 代码要点 https://gist.github.com/kapiljhajhria/795d1a7c7cf1c76ca8e327bf8b2f51de
这里是我所做工作的简要总结
- 生成唯一的会话密钥:AES 随机密钥 256
- 使用步骤 1 中的会话密钥加密 JSON 数据
- 生成 JSON 数据的 SHA256 哈希值
- 使用步骤 1 中的会话密钥加密步骤 3 中生成的哈希值。
- 使用 public 密钥加密会话密钥。 Public 密钥作为 certificate.cer 文件提供。我复制了 String 值并将其作为常量添加到 class 中,以使其更易于使用。不确定这是否是最佳方法。
- 创建了一个带有 3 个参数的 POST 请求。如java代码所示。我认为我正确地完成了这部分。
- 我将获得的响应将使用步骤 1 中的会话密钥进行加密。因此我将不得不解密该响应数据。还没到这一步。
我无法访问发出此请求的服务器。 由于 post 请求是使用网络视图发出的,因此我无法找到一种方法来从我的请求中获取正确的错误。我得到的只是显示“无效请求”的网页
所以我的第一个猜测是我没有正确使用 public 密钥来加密我的会话密钥。 如果那部分是正确的,那么我没有正确加密数据,或者我的加密方法与 java 代码中使用的加密方法不匹配 java 代码。也许我生成的会话密钥不正确。
如有任何帮助,我们将不胜感激。谢谢你。如果您需要我提供任何信息,请告诉我。
看看这个project,这是 Flutter 加密的一个例子,有很好的文档,有 3 种加密类型:
- AES 加密
- Fernet 加密
- Salsa20 加密
我用这个文档作为参考:https://developers.emsigner.com/signer-gateway/api-reference/signing-documents.html
您需要 2 个包:pointycastle
和 x509
,并按如下方式导入它们:
import 'package:pointycastle/export.dart';
import 'package:x509/x509.dart';
那么你需要这些辅助函数:
Uint8List generateSessionKey() {
final r = Random();
return Uint8List.fromList(List<int>.generate(32, (_) => r.nextInt(256)));
}
RSAPublicKey parseCert(String pemData) {
final cert = parsePem(pemData).first as X509Certificate;
final pub = cert.publicKey as RsaPublicKey;
return RSAPublicKey(pub.modulus, pub.exponent);
}
Uint8List encryptUsingPublicKey(RSAPublicKey key, Uint8List data) {
final cipher = PKCS1Encoding(RSAEngine())
..init(true, PublicKeyParameter<RSAPublicKey>(key));
return cipher.process(data);
}
Uint8List encryptUsingSessionKey(Uint8List key, Uint8List data) {
final cipher = PaddedBlockCipher('AES/ECB/PKCS7')
..init(true, PaddedBlockCipherParameters(KeyParameter(key), null));
return cipher.process(data);
}
Uint8List sha256Digest(Uint8List data) {
return SHA256Digest().process(data);
}
然后您将像这样构建 3 个参数:
final pem = File('cert2.pem').readAsStringSync();
final publicKey = parseCert(pem);
final sessionKey = generateSessionKey();
final encryptedSessionKey = encryptUsingPublicKey(publicKey, sessionKey);
final jsonString = json.encode(<String, dynamic>{
'FileType': 'PDF',
'SignaturePosition': 'Top-Left',
'AuthToken': 'some token',
'File': '',
'SUrl': 'http://localhost:3000/Success',
'FUrl': 'http://localhost:3000/Error',
'CUrl': 'http://localhost:3000/Cancel',
'ReferenceNumber': 'generate unique reference number',
});
final jsonBytes = utf8.encode(jsonString) as Uint8List;
final encryptedJson = encryptUsingSessionKey(sessionKey, jsonBytes);
final hash = sha256Digest(jsonBytes);
final encryptedHash = encryptUsingSessionKey(sessionKey, hash);
final p1 = base64.encode(encryptedSessionKey);
final p2 = base64.encode(encryptedJson);
final p3 = base64.encode(encryptedHash);
但是,我看到的最大问题是您如何执行 POST,因为您想要在网页中,对吗?并且普通的 flutter web 视图不支持初始 post。看起来确实还有另一个包裹。只需搜索 flutter webview post
.
顺便说一下,如果你不想使用 pointycastle 注册表,你可以重写 encryptUsingSessionKey
而不是 as:
final cipher = PaddedBlockCipherImpl(
PKCS7Padding(),
ECBBlockCipher(AESEngine()),
)..init(true, PaddedBlockCipherParameters(KeyParameter(key), null));
return cipher.process(data);
最后,至少在您了解 Web 视图问题之前,您可以使用 http
来完成 post。但是,让它完成编码参数和设置内容类型的工作,如下:
final response = await http.post(
Uri.parse('https://somewhere/V3_0/Index'),
body: <String, String>{
'Parameter1': p1,
'Parameter2': p2,
'Parameter3': p3,
},
);
print(response.statusCode);
print(response.body);