signDigest function
Implementation
Future<String> signDigest(
String digestBase64, String privateKeyBase64OrPem) async {
if (digestBase64.isEmpty) {
throw ArgumentError('El parámetro "digestBase64" es requerido.');
}
if (privateKeyBase64OrPem.isEmpty) {
throw ArgumentError('El parámetro "privateKeyBase64OrPem" es requerido.');
}
// Preparar PEM de la clave privada: si la entrada ya tiene header PEM, la usamos.
String privatePem;
final trimmed = privateKeyBase64OrPem.trim();
if (trimmed.startsWith('-----BEGIN')) {
privatePem = trimmed;
} else {
// Intentamos decodificar base64 y obtener el PEM resultante.
try {
final decoded = utf8.decode(base64.decode(trimmed));
if (decoded.trim().startsWith('-----BEGIN')) {
privatePem = decoded;
} else {
throw FormatException(
'La clave privada base64 decodificada no contiene un PEM válido.');
}
} catch (e) {
throw FormatException(
'No se pudo decodificar privateKeyBase64OrPem como base64 PEM: $e');
}
}
// Parsear la clave privada a RSAPrivateKey
final priv = CryptoUtils.rsaPrivateKeyFromPem(privatePem);
if (priv == null || priv is! RSAPrivateKey) {
throw FormatException(
'No se pudo parsear la clave privada a RSAPrivateKey.');
}
// Decodificar el digest (base64) a bytes
final messageBytes = base64.decode(digestBase64);
// Firmar usando Signer de pointycastle: SHA-256/RSA (PKCS#1 v1.5)
final signer = Signer('SHA-256/RSA');
final privParams = PrivateKeyParameter<RSAPrivateKey>(priv);
try {
signer.init(true, privParams);
final signature = signer.generateSignature(Uint8List.fromList(messageBytes))
as RSASignature;
final sigBytes = signature.bytes;
return base64.encode(sigBytes);
} catch (e) {
throw Exception('Error al firmar el digest: $e');
}
}