decodePemBlocks function
Decode a String of one or more concatenated PEM blocks.
Returns a list of base64 decoded bytes for each PEM block matching the
given label
. An empty list if no correctly formatted PEM blocks is found
in the given pemString
. This method will not throw an exception on
formatting errors.
The parser defaults to laxtextualmsg
from RFC 7468,
but if strict
is true
parser will require stricttextualmsg
.
It is generally safe to parse in non-strict mode, which just
ignores whitespace and allows widely used label aliases.
If unsafeIgnoreLabel
is set to true
the decoding parser will ignore
the label. This can be useful in certain legacy scenarios, but is
generally discouraged as it could lead to unintended usages of keys.
*Example
import 'package:pem/pem.dart';
// Parse in non-strict mode (default) which ignores extra whitespace.
final blocks = decodePemBlocks(PemLabel.publicKey, """
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEn1LlwLN/KBYQRVH6HfIMTzfEqJOVztLe
kLchp2hi78cCaMY81FBlYs8J9l7krc+M4aBeCGYFjba+hiXttJWPL7ydlE+5UG4U
Nkn3Eos8EiZByi9DVsyfy9eejh+8AXgp
-----END PUBLIC KEY-----
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEn1LlwLN/KBYQRVH6HfIMTzfEqJOVztLe
kLchp2hi78cCaMY81FBlYs8J9l7krc+M4aBeCGYFjba+hiXttJWPL7ydlE+5UG4U
Nkn3Eos8EiZByi9DVsyfy9eejh+8AXgp
-----END PUBLIC KEY-----
""");
// Print byte size of keys
print('1st public key has ${blocks[0].length} bytes');
print('2nd public key has ${blocks[1].length} bytes');
Implementation
List<List<int>> decodePemBlocks(
PemLabel label,
String pemString, {
bool strict = false,
bool unsafeIgnoreLabel = false,
}) {
final labels = _labels[label];
if (labels == null) {
throw AssertionError('Unkown label');
}
// Pick a parser
final p = strict ? stricttextualmsg : laxtextualmsg;
// Create results
final result = <List<int>>[];
for (final r in p.allMatches(pemString, overlapping: false)) {
final doc = r.cast<String>();
final preLabel = doc[0];
final data = doc[1];
final postLabel = doc[2];
// Pre and post label must match, unless we're in unsafe ignore label mode.
if (preLabel != postLabel && !unsafeIgnoreLabel) {
continue;
}
// Label much match an allowed alias, if not ignoring
if (!labels.contains(preLabel) && !unsafeIgnoreLabel) {
continue;
}
// Label much match canonical label name, if we're in strict mode
if (strict && labels.first != preLabel && !unsafeIgnoreLabel) {
continue;
}
try {
result.add(base64.decode(data));
} on Exception {
continue; // Ignore malformed base64
}
}
return result;
}