build method
Build the JsonWebSignature or JsonWebEncryption
Implementation
@override
JsonWebEncryption build() {
if (encryptionAlgorithm == null) {
throw StateError('No encryption algorithm set');
}
if (encryptionAlgorithm == 'none') {
throw StateError('Encryption algorithm cannot be `none`');
}
if (recipients.isEmpty) {
throw StateError('Need at least one recipient');
}
var payload = this.payload;
if (payload == null) {
throw StateError('No payload set');
}
var compact = recipients.length == 1 && additionalAuthenticatedData == null;
var cek = JsonWebKey.generate(encryptionAlgorithm);
var sharedUnprotectedHeaderParams = <String, dynamic>{
'enc': encryptionAlgorithm
};
var recipientsMapped = recipients.map((r) {
var key = r['_jwk'] as JsonWebKey;
var algorithm = r['alg'] ?? key.algorithmForOperation('wrapKey') ?? 'dir';
if (algorithm == 'dir') {
if (recipients.length > 1) {
throw StateError(
'JWE can only have one recipient when using direct encryption with a shared symmetric key.');
}
final k = JsonWebKey.fromJson({
'alg': encryptionAlgorithm,
...key.toJson(),
});
if (k == null) {
throw UnimplementedError('Unkown key.');
}
cek = k;
}
var encryptedKey = algorithm == 'dir'
? const <int>[]
: key.wrapKey(
cek,
algorithm: algorithm,
);
var unprotectedHeaderParams = <String, dynamic>{'alg': algorithm};
if (key.keyId != null) {
unprotectedHeaderParams['kid'] = key.keyId;
}
if (compact) {
sharedUnprotectedHeaderParams.addAll(unprotectedHeaderParams);
}
return _JweRecipient._(
encryptedKey: encryptedKey,
header: compact ? null : JsonObject.from(unprotectedHeaderParams));
}).toList();
var protectedHeader = payload.protectedHeader;
if (compact) {
protectedHeader = JsonObject.from(safeUnion(
[protectedHeader?.toJson(), sharedUnprotectedHeaderParams]));
}
var aad = protectedHeader!.toBase64EncodedString();
if (additionalAuthenticatedData != null) {
aad += '.${String.fromCharCodes(additionalAuthenticatedData!)}';
}
// RFC 7518 requires that a 96 bit iv is used with AESGCM and cjose insists
var iv = (encryptionAlgorithm != null &&
encryptionAlgorithm!.contains(RegExp('A[0-9][0-9][0-9]GCM')))
? Uint8List.fromList(
List.generate(12, (_) => Random.secure().nextInt(256)))
: null;
var encryptedData = cek.encrypt(data!,
initializationVector: iv,
additionalAuthenticatedData: Uint8List.fromList(aad.codeUnits));
return JsonWebEncryption._(encryptedData.data, recipientsMapped,
protectedHeader: protectedHeader,
unprotectedHeader:
compact ? null : JsonObject.from(sharedUnprotectedHeaderParams),
initializationVector: encryptedData.initializationVector!,
authenticationTag: encryptedData.authenticationTag!,
additionalAuthenticatedData: additionalAuthenticatedData);
}