/// <inheritsdoc /> public override bool TryUnwrapKey(ReadOnlySpan <byte> keyBytes, Span <byte> destination, JwtHeaderDocument header, out int bytesWritten) { if (!header.TryGetHeaderParameter(JwtHeaderParameterNames.Epk.EncodedUtf8Bytes, out var epk)) { ThrowHelper.ThrowJwtDescriptorException_HeaderIsRequired(JwtHeaderParameterNames.Epk); } header.TryGetHeaderParameter(JwtHeaderParameterNames.Apu.EncodedUtf8Bytes, out JwtElement apu); header.TryGetHeaderParameter(JwtHeaderParameterNames.Apv.EncodedUtf8Bytes, out JwtElement apv); byte[] secretAppend = BuildSecretAppend(apu, apv); ReadOnlySpan <byte> exchangeHash; using (var ephemeralKey = ECDiffieHellman.Create(ECJwk.FromJwtElement(epk).ExportParameters())) { var privateKey = _key.CreateEcdhKey(); if (ephemeralKey.KeySize != privateKey.KeySize) { return(ThrowHelper.TryWriteError(out bytesWritten)); } exchangeHash = new ReadOnlySpan <byte>(privateKey.DeriveKeyFromHash(ephemeralKey.PublicKey, _hashAlgorithm, _secretPreprend, secretAppend), 0, _keySizeInBytes); } if (Algorithm.ProduceEncryptionKey) { using var keyUnwrapper = new AesKeyUnwrapper(exchangeHash, EncryptionAlgorithm, _keyManagementAlgorithm !); return(keyUnwrapper.TryUnwrapKey(keyBytes, destination, header, out bytesWritten)); } else { exchangeHash.CopyTo(destination); bytesWritten = destination.Length; return(true); } }