/// <inheritdoc/> public bool TryGetHeader(JwtHeader header, KeyManagementAlgorithm alg, EncryptionAlgorithm enc, JsonEncodedText kid, string?typ, string?cty, [NotNullWhen(true)] out byte[]?base64UrlHeader) { if (ReferenceEquals(_firstHeader.Header, header)) { base64UrlHeader = _firstHeader.BinaryHeader; goto Found; } if (IsEligibleHeaderForJwe(header.Count, kid, typ, cty)) { int algorithmId = enc.ComputeKey(alg); var node = _head; while (node != null) { if (algorithmId == node.AlgorithmId) { if (node.TryGetEntry(kid, out var entry)) { if (cty != entry.Cty) { goto NotFound; } if (typ != entry.Typ) { goto NotFound; } base64UrlHeader = entry.Data; if (node != _head) { MoveToHead(node); } goto Found; } } node = node.Next; } } NotFound: #if NET5_0_OR_GREATER Unsafe.SkipInit(out base64UrlHeader); #else base64UrlHeader = default; #endif return(false); Found: return(true); }
/// <inheritdoc/> public void AddHeader(JwtHeader header, KeyManagementAlgorithm alg, EncryptionAlgorithm enc, JsonEncodedText kid, string?typ, string?cty, ReadOnlySpan <byte> base6UrlHeader) { _firstHeader = new WrappedHeader(header, base6UrlHeader.ToArray()); if (IsEligibleHeaderForJwe(header.Count, kid, typ, cty)) { int algorithmId = enc.ComputeKey(alg); bool lockTaken = false; try { _spinLock.Enter(ref lockTaken); if (_count >= MaxSize) { _head = null; _tail = null; _count = 0; } var node = _head; while (node != null) { if (algorithmId == node.AlgorithmId) { break; } node = node.Next; } var key = alg.Id; if (node is null) { _count++; node = new Bucket(algorithmId, kid, new CacheEntry(base6UrlHeader.ToArray(), typ, cty)) { Next = _head }; } else { if (!node.Entries.ContainsKey(kid !)) { _count++; node.Entries[kid] = new CacheEntry(base6UrlHeader.ToArray(), typ, cty); } } if (!ReferenceEquals(_head, node)) { if (_head != null) { _head.Previous = node; } _head = node; } if (_tail is null) { _tail = node; } } finally { if (lockTaken) { _spinLock.Exit(); } } } }