public string BuildString() { End(); var result = NS2Bridge.CreateString(_jwtLength, _jwt, (destination, state) => { NS2Bridge.Latin1ToUtf16(state.AsSpan(0, _jwtLength), destination); }); return(result); }
public bool TryBuildTo(Span <char> destination, out int charsWritten) { End(); if (destination.Length < _jwtLength) { charsWritten = 0; return(false); } NS2Bridge.Latin1ToUtf16(_jwt.AsSpan(0, _jwtLength), destination); charsWritten = _jwtLength; return(true); }
/// <summary> /// Returns number of ASCII characters of the JTW. The actual token can be retrieved using Build or WriteTo /// </summary> /// <returns></returns> public int End() { if (_writer == null) { return(_jwtLength); // writer is set to null after token is formatted. } if (_isDisposed) { throw new ObjectDisposedException(nameof(JwtBuilder)); } _writer.WriteEndObject(); _writer.Flush(); Debug.Assert(_memoryStream.GetType() == typeof(MemoryStream)); int payloadLength = (int)_writer.BytesCommitted; // writer is wrrapping MemoryStream, and so the length will never overflow int. int payloadIndex = headerSha256.Length; int maxBufferLength; checked { maxBufferLength = Base64.GetMaxEncodedToUtf8Length(headerSha256.Length + payloadLength) + 1 // dot + Base64.GetMaxEncodedToUtf8Length(32); // signature SHA256 hash size } _memoryStream.Capacity = maxBufferLength; // make room for in-place Base64 conversion _jwt = _memoryStream.GetBuffer(); _writer = null; // this will prevent subsequent additions of claims. Span <byte> toEncode = _jwt.AsSpan(payloadIndex); OperationStatus status = NS2Bridge.Base64UrlEncodeInPlace(toEncode, payloadLength, out int payloadWritten); Debug.Assert(status == OperationStatus.Done); // Buffer is adjusted above, and so encoding should always fit // Add signature int headerAndPayloadLength = payloadWritten + headerSha256.Length; _jwt[headerAndPayloadLength] = (byte)'.'; int headerAndPayloadAndSeparatorLength = headerAndPayloadLength + 1; using (HMACSHA256 hash = new HMACSHA256(_key)) { var hashed = hash.ComputeHash(_jwt, 0, headerAndPayloadLength); status = NS2Bridge.Base64UrlEncode(hashed, _jwt.AsSpan(headerAndPayloadAndSeparatorLength), out int consumend, out int signatureLength); Debug.Assert(status == OperationStatus.Done); // Buffer is adjusted above, and so encoding should always fit _jwtLength = headerAndPayloadAndSeparatorLength + signatureLength; } return(_jwtLength); }