/// <summary> /// Try to get the header. /// </summary> /// <param name="header"></param> /// <param name="alg"></param> /// <param name="base64UrlHeader"></param> /// <returns></returns> public bool TryGetHeader(JwtObject header, SignatureAlgorithm alg, [NotNullWhen(true)] out byte[]?base64UrlHeader) { if (header.TryGetValue(HeaderParameters.KidUtf8, out var kidProperty) && kidProperty.Type == JwtTokenType.String && !(kidProperty.Value is null) && !(alg is null) && header.Count == 2) { var kid = (string)kidProperty.Value; var keyId = kid.AsSpan(); var node = _head; while (node != null) { if (keyId.SequenceEqual(node.Kid.AsSpan())) { if (node.Entries.TryGetValue(alg.Id, out var entry)) { base64UrlHeader = entry; if (node != _head) { MoveToHead(node); } return(true); } goto NotFound; } node = node.Next; } } NotFound: base64UrlHeader = null; return(false); }
/// <summary> /// Adds a base64url encoded header to the cache. /// </summary> /// <param name="header"></param> /// <param name="alg"></param> /// <param name="base6UrlHeader"></param> public void AddHeader(JwtObject header, SignatureAlgorithm alg, ReadOnlySpan <byte> base6UrlHeader) { if (header.TryGetValue(HeaderParameters.KidUtf8, out var kidProperty) && kidProperty.Type == JwtTokenType.String && !(kidProperty.Value is null) && !(alg is null) && header.Count == 2) { var kid = (string)kidProperty.Value; bool lockTaken = false; try { _spinLock.Enter(ref lockTaken); var node = _head; while (node != null) { if (string.Equals(node.Kid, kid, StringComparison.Ordinal)) { break; } node = node.Next; } var key = alg.Id; if (node is null) { node = new Bucket(kid, new Dictionary <long, byte[]>(1) { { key, base6UrlHeader.ToArray() } }) { Next = _head }; } else { if (node.Entries.ContainsKey(key)) { node.Entries[key] = base6UrlHeader.ToArray(); } } if (_count >= MaxSize) { RemoveLeastRecentlyUsed(); } else { _count++; } if (_head != null) { _head.Previous = node; } _head = node; if (_tail is null) { _tail = node; } } finally { if (lockTaken) { _spinLock.Exit(); } } } }