parseValidatorKeys function
Parses every ValidatorSecretKey from a validator PEM file.
Iterates over each -----BEGIN PRIVATE KEY for <label>----- /
-----END PRIVATE KEY for <label>----- block, base64-decodes the
body to recover the hex-encoded secret key bytes, then hex-decodes
those bytes into a 32-byte BLS secret key.
Parameters
pemText- Validator PEM file contents (one or many entries)
Returns
List<ValidatorSecretKey> - All validator keys, in file order
Throws
PemException- WhenpemTextis empty, contains no valid validator entries, or has malformed base64/hex content
Implementation
List<ValidatorSecretKey> parseValidatorKeys(String pemText) {
if (pemText.trim().isEmpty) {
throw const PemException('Empty validator PEM input');
}
/// Capture the BLS public-key label on both BEGIN and END markers so we
/// can assert they match (M2-17).
final RegExp blockPattern = RegExp(
r'-----BEGIN PRIVATE KEY for ([^-]+)-----\s*([A-Za-z0-9+/=\s]+?)\s*-----END PRIVATE KEY for ([^-]+)-----',
multiLine: true,
);
final Iterable<RegExpMatch> matches = blockPattern.allMatches(pemText);
if (matches.isEmpty) {
throw const PemException(
'No validator PEM entries found; expected BEGIN/END PRIVATE KEY headers',
);
}
/// 192 lowercase-hex chars = 96 bytes (BLS public key length).
final RegExp validatorPubKeyLabel = RegExp(r'^[0-9a-f]{192}$');
final List<ValidatorSecretKey> result = <ValidatorSecretKey>[];
for (final RegExpMatch match in matches) {
final String beginLabel = match.group(1)!.trim();
final String body = match.group(2)!.replaceAll(RegExp(r'\s+'), '');
final String endLabel = match.group(3)!.trim();
if (beginLabel != endLabel) {
throw PemException(
'Validator PEM BEGIN/END labels do not match: '
'"$beginLabel" vs "$endLabel"',
);
}
if (!validatorPubKeyLabel.hasMatch(beginLabel)) {
throw PemException(
'Validator PEM label must be exactly 192 lowercase hex chars '
'(BLS public key, 96 bytes); got "${beginLabel.length}" chars',
);
}
final Uint8List hexBytes;
try {
hexBytes = base64.decode(body);
} on FormatException catch (error, stackTrace) {
throw PemException(
'Invalid base64 in validator PEM body',
cause: error,
stackTrace: stackTrace,
);
}
final String hexString = utf8.decode(hexBytes);
final Uint8List secretBytes;
try {
secretBytes = Uint8List.fromList(convert.hex.decode(hexString));
} on FormatException catch (error, stackTrace) {
throw PemException(
'Invalid hex in validator PEM body',
cause: error,
stackTrace: stackTrace,
);
}
if (secretBytes.length != validatorSecretKeyLength) {
throw PemException(
'Invalid validator secret length: expected $validatorSecretKeyLength, got ${secretBytes.length}',
);
}
result.add(ValidatorSecretKey(secretBytes));
}
return result;
}