/// <inheritsdoc /> public override bool TryUnwrapKey(ReadOnlySpan <byte> keyBytes, Span <byte> destination, JwtHeaderDocument header, out int bytesWritten) { if (!header.TryGetHeaderParameter(JwtHeaderParameterNames.IV.EncodedUtf8Bytes, out var encodedIV)) { ThrowHelper.ThrowJwtDescriptorException_HeaderIsRequired(JwtHeaderParameterNames.IV); } if (!header.TryGetHeaderParameter(JwtHeaderParameterNames.Tag.EncodedUtf8Bytes, out var encodedTag)) { ThrowHelper.ThrowJwtDescriptorException_HeaderIsRequired(JwtHeaderParameterNames.Tag); } var rawIV = encodedIV.GetRawValue(); Span <byte> nonce = stackalloc byte[Base64Url.GetArraySizeRequiredToDecode(rawIV.Length)]; var rawTag = encodedTag.GetRawValue(); Span <byte> tag = stackalloc byte[Base64Url.GetArraySizeRequiredToDecode(rawTag.Length)]; try { Base64Url.Decode(rawIV.Span, nonce); Base64Url.Decode(rawTag.Span, tag); using var aesGcm = new AesGcm(_key.K); if (destination.Length > keyBytes.Length) { destination = destination.Slice(0, keyBytes.Length); } aesGcm.Decrypt(nonce, keyBytes, tag, destination); bytesWritten = destination.Length; return(true); } catch (CryptographicException) { return(ThrowHelper.TryWriteError(out bytesWritten)); } }
private byte[] BuildSecretAppend(string?apuS, string?apvS) { byte[]? apuToReturn = null; byte[]? apvToReturn = null; byte[] secretAppend; try { int apuLength = apuS == null ? 0 : Utf8.GetMaxByteCount(apuS.Length); Span <byte> apu = apuLength <= Constants.MaxStackallocBytes ? stackalloc byte[apuLength] : (apuToReturn = ArrayPool <byte> .Shared.Rent(apuLength)); if (apuS != null) { apuLength = Utf8.GetBytes(apuS, apu); apu = apu.Slice(0, apuLength); } int apvLength = apvS == null ? 0 : Utf8.GetMaxByteCount(apvS.Length); Span <byte> apv = apvLength <= Constants.MaxStackallocBytes ? stackalloc byte[apvLength] : (apvToReturn = ArrayPool <byte> .Shared.Rent(apvLength)); if (apvS != null) { apvLength = Utf8.GetBytes(apvS, apv); apv = apv.Slice(0, apvLength); } apuLength = Base64Url.GetArraySizeRequiredToDecode(apuLength); apvLength = Base64Url.GetArraySizeRequiredToDecode(apvLength); int algorithmLength = sizeof(int) + _algorithmNameLength; int partyUInfoLength = sizeof(int) + apuLength; int partyVInfoLength = sizeof(int) + apvLength; const int suppPubInfoLength = sizeof(int); int secretAppendLength = algorithmLength + partyUInfoLength + partyVInfoLength + suppPubInfoLength; secretAppend = new byte[secretAppendLength]; var secretAppendSpan = secretAppend.AsSpan(); WriteAlgorithmId(secretAppendSpan); secretAppendSpan = secretAppendSpan.Slice(algorithmLength); WritePartyInfo(apu, apuLength, secretAppendSpan); secretAppendSpan = secretAppendSpan.Slice(partyUInfoLength); WritePartyInfo(apv, apvLength, secretAppendSpan); secretAppendSpan = secretAppendSpan.Slice(partyVInfoLength); BinaryPrimitives.WriteInt32BigEndian(secretAppendSpan, _keySizeInBytes << 3); } finally { if (apuToReturn != null) { ArrayPool <byte> .Shared.Return(apuToReturn); } if (apvToReturn != null) { ArrayPool <byte> .Shared.Return(apvToReturn); } } return(secretAppend); }