decryptWithJwk method
Implementation
DidcommMessage decryptWithJwk(Map<String, dynamic> privateKeyJwk,
[Map<String, dynamic>? senderPublicKeyJwk]) {
_decodeProtected();
var crv = privateKeyJwk['crv'];
elliptic.Curve? c;
dynamic receiverPrivate, epkPublic;
if (crv.startsWith('P') || crv.startsWith('secp256k1')) {
if (crv == 'P-256') {
c = elliptic.getP256();
} else if (crv == 'P-384') {
c = elliptic.getP384();
} else if (crv == 'P-521') {
c = elliptic.getP521();
} else if (crv == 'secp256k1') {
c = elliptic.getSecp256k1();
} else {
throw UnimplementedError("Curve `$crv` not supported");
}
receiverPrivate = elliptic.PrivateKey(
c,
bytesToUnsignedInt(
base64Decode(addPaddingToBase64(privateKeyJwk['d']))));
epkPublic = elliptic.PublicKey.fromPoint(
c,
elliptic.AffinePoint.fromXY(
bytesToUnsignedInt(
base64Decode(addPaddingToBase64(protectedHeaderEpk!['x']))),
bytesToUnsignedInt(
base64Decode(addPaddingToBase64(protectedHeaderEpk!['y'])))));
} else if (crv.startsWith('X')) {
receiverPrivate = base64Decode(addPaddingToBase64(privateKeyJwk['d']));
epkPublic = base64Decode(addPaddingToBase64(protectedHeaderEpk!['x']));
} else {
throw UnimplementedError("Curve `$crv` not supported");
}
//2) compute shared Secret
List<int> sharedSecret;
bool authcrypt = false;
if (protectedHeaderAlg!.startsWith('ECDH-ES')) {
sharedSecret =
_ecdhES(receiverPrivate, epkPublic, apv: protectedHeaderApv);
} else if (protectedHeaderAlg!.startsWith('ECDH-1PU')) {
authcrypt = true;
if (senderPublicKeyJwk == null) {
throw Exception('Public key of sender needed');
}
//var senderDid = base64Decode(addPaddingToBase64(apu));
Object senderPubKey;
if (crv.startsWith('P') || crv.startsWith('secp256k1')) {
senderPubKey = elliptic.PublicKey.fromPoint(
c!,
elliptic.AffinePoint.fromXY(
bytesToUnsignedInt(
base64Decode(addPaddingToBase64(senderPublicKeyJwk['x']))),
bytesToUnsignedInt(base64Decode(
addPaddingToBase64(senderPublicKeyJwk['y'])))));
} else if (crv.startsWith('X')) {
senderPubKey =
base64Decode(addPaddingToBase64(senderPublicKeyJwk['x']));
} else {
throw UnimplementedError("Curve `$crv` is not supported");
}
sharedSecret = _ecdh1PU(
receiverPrivate,
receiverPrivate,
epkPublic,
senderPubKey,
base64Decode(addPaddingToBase64(tag)),
protectedHeaderAlg!,
protectedHeaderApu!,
protectedHeaderApv!);
} else {
throw UnimplementedError("Algorithm `${protectedHeaderAlg!}`"
" is not supported");
}
//3) Decrypt cek
//a)search encrypted cek
String encryptedCek = '';
for (var entry in recipients) {
var kid = entry['header']['kid']!;
if (kid == privateKeyJwk['kid']) {
encryptedCek = entry['encrypted_key'];
break;
}
}
Map<String, dynamic> sharedSecretJwk = {
'kty': 'oct',
'k': base64UrlEncode(sharedSecret)
};
var keyWrapKey = KeyPair.fromJwk(sharedSecretJwk);
Encrypter kw = keyWrapKey.publicKey!
.createEncrypter(algorithms.encryption.aes.keyWrap);
var decryptedCek = kw.decrypt(
EncryptionResult(base64Decode(addPaddingToBase64(encryptedCek))));
var cek = SymmetricKey(keyValue: decryptedCek);
//4) Decrypt Body
Encrypter e;
if (protectedHeaderEnc! == 'A256CBC-HS512') {
e = cek.createEncrypter(algorithms.encryption.aes.cbcWithHmac.sha512);
} else if (protectedHeaderEnc == 'A256GCM') {
e = cek.createEncrypter(algorithms.encryption.aes.gcm);
} else {
throw UnimplementedError();
}
var toDecrypt = EncryptionResult(
base64Decode(addPaddingToBase64(ciphertext)),
authenticationTag: base64Decode(addPaddingToBase64(tag)),
additionalAuthenticatedData: ascii.encode(protectedHeader),
initializationVector: base64Decode(addPaddingToBase64(iv)));
var plain = e.decrypt(toDecrypt);
//5)return body
DidcommMessage m;
Map message = jsonDecode(utf8.decode(plain));
if (message.containsKey('id')) {
m = DidcommPlaintextMessage.fromJson(message);
m as DidcommPlaintextMessage;
if (authcrypt) {
if (m.from != null) {
if (m.from != protectedHeaderSkid!.split('#').first) {
throw Exception(
'From value of plaintext Message do not match skid of encrypted message');
}
} else {
throw Exception(
'from header in plaintext message is required if authcrypt is used');
}
}
} else if (message.containsKey('ciphertext')) {
m = DidcommSignedMessage.fromJson(message);
} else if (message.containsKey('signatures')) {
m = DidcommEncryptedMessage.fromJson(message);
} else {
throw Exception('Unknown Message type');
}
return m;
}