如何在 flutter dart 中使用 publicKey.xml 文件进行 rsa 加密,我遇到问题 FormatException: Could not parse BigInt

问题描述 投票:0回答:1
<RSAKeyValue><Modulus>D4ZblrI8NsZgnZOQbHJuEv7Lg0pCOuhwmGIS10rwlJ9Z/hGbes=</Modulus><Exponent>ABCD</Exponent><P>86TWhp553PrrlQ/xdOpGDbGy8/h3/5vg+P==</P><Q>D33zQmGtBnoO8OaQhCwbwqai1w==</Q><DP>i0RwPcLPh+WQKt5L75SR1PQ==</DP><DQ>3vayrPOJ1WMFxPzCpqMaUDWwWsBJ/c0PRwRhvrSw4/TR+6BlEkU/5b17/==</DQ><InverseQ>CbuGb8ZNvjCkSHqvSTJvFpFfqxxQjH09ABxBZx3K7SNvw3+6+LfKeRzoz7==</InverseQ><D>p6etDZ1ghROHdHWAauTUe6zn/RQzm7HE5aCWVOgMqcg9VkFMMZ3H+R1rec=</D></RSAKeyValue>

上面你可以看到我的publicKey.xml文件的示例格式,我需要将其转换为pem格式进行rsa加密,主要需要加密用户名和密码。

import 'dart:convert';
import 'dart:typed_data';
import 'package:pointycastle/export.dart';
import 'package:xml/xml.dart' as xml;

void encryptRSa() {
  String publicKeyXML = '''
   <RSAKeyValue><Modulus>D4ZblrI8NsZgnZOQbHJuEv7Lg0pCOuhwmGIS10rwlJ9Z/hGbes=</Modulus><Exponent>ABCD</Exponent><P>86TWhp553PrrlQ/xdOpGDbGy8/h3/5vg+P==</P><Q>D33zQmGtBnoO8OaQhCwbwqai1w==</Q><DP>i0RwPcLPh+WQKt5L75SR1PQ==</DP><DQ>3vayrPOJ1WMFxPzCpqMaUDWwWsBJ/c0PRwRhvrSw4/TR+6BlEkU/5b17/==</DQ><InverseQ>CbuGb8ZNvjCkSHqvSTJvFpFfqxxQjH09ABxBZx3K7SNvw3+6+LfKeRzoz7==</InverseQ><D>p6etDZ1ghROHdHWAauTUe6zn/RQzm7HE5aCWVOgMqcg9VkFMMZ3H+R1rec=</D></RSAKeyValue>
  ''';

  var document = xml.XmlDocument.parse(publicKeyXML);
  var modulusBase64 = document.findAllElements('Modulus').single.text;
  var exponentBase64 = document.findAllElements('Exponent').single.text;

  var modulusBytes = Uint8List.fromList(base64.decode(modulusBase64));
  var exponentBytes = Uint8List.fromList(base64.decode(exponentBase64));

  var modulus = decodeBigIntFromBytes(modulusBytes);
  var exponent = decodeBigIntFromBytes(exponentBytes);

  var publicKey = RSAPublicKey(modulus, exponent);

  var encryptor = OAEPEncoding(RSAEngine())
    ..init(true, PublicKeyParameter<RSAPublicKey>(publicKey));

  String message = 'Hello, World!';

  var encrypted = encryptor.process(Uint8List.fromList(utf8.encode(message)));

  print('EncryptedOne: ${base64.encode(encrypted)}');
}

BigInt decodeBigIntFromBytes(Uint8List bytes) {
  return BigInt.parse(base64.encode(bytes), radix: 16);
}

我正在使用 pointcastle 和 xml 库进行加密,当我运行此代码时,我遇到了问题 FormatException:无法解析 BigInt

flutter cryptography bouncycastle public-key-encryption pointycastle
1个回答
0
投票

该错误是在函数

decodeBigIntFromBytes()
中,
BigInt.parse()
中的数据未正确进行 Base64 编码。正确的是十六进制编码,对应你使用的基数16:

import 'package:convert/convert.dart';
...
BigInt decodeBigIntFromBytes(Uint8List bytes) {
  return BigInt.parse(hex.encode(bytes), radix: 16);
}

通过此更改,代码可以正常工作,无论是公钥的导入还是加密本身。


额外但次要的:应使用

text
,而不是过期的 
innerText
,例如:

var modulusBase64 = document.findAllElements('Modulus').single.innerText;

如果您想导出/导入PEM格式的密钥,basic_utils包提供了合适的功能,例如

CryptoUtils.encodeRSAPublicKeyToPem()
可用于导出以X.509/SPKI格式编码的公钥PEM:

import 'package:basic_utils/basic_utils.dart';
...
print('X.509/SPKI, PEM: ${CryptoUtils.encodeRSAPublicKeyToPem(publicKey)}');

请注意,正如评论中已经指出的那样,发布的密钥确实是一个 private RSA 密钥。 public密钥仅包含

Modulus
Exponent
字段(所有其他字段属于私钥,不得泄露)。然而,由于这显然是一个测试密钥,因此披露可能并不重要。

© www.soinside.com 2019 - 2024. All rights reserved.