Пример #1
0
        /// <summary>Decodes a string of UTF-8 base64url-encoded text.</summary>
        /// <remarks>This method allocate an array of bytes. Use <see cref="Decode(ReadOnlySpan{byte}, Span{byte})"/> when possible.</remarks>
        public static byte[] Decode(string data)
        {
            if (data is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.data);
            }

            int length = Utf8.GetMaxByteCount(data.Length);

            byte[]? utf8ArrayToReturn = null;
            try
            {
                Span <byte> tmp = length > Constants.MaxStackallocBytes
                    ? (utf8ArrayToReturn = ArrayPool <byte> .Shared.Rent(length))
                    : stackalloc byte[Constants.MaxStackallocBytes];
                int written = Utf8.GetBytes(data, tmp);
                return(Decode(tmp.Slice(0, written)));
            }
            finally
            {
                if (utf8ArrayToReturn != null)
                {
                    ArrayPool <byte> .Shared.Return(utf8ArrayToReturn);
                }
            }
        }
Пример #2
0
        /// <inheritsdoc />
        public override void Encode(EncodingContext context)
        {
            if (Payload != null)
            {
                int payloadLength = Utf8.GetMaxByteCount(Payload.Length);
                byte[]? payloadToReturnToPool = null;
                Span <byte> encodedPayload = payloadLength > Constants.MaxStackallocBytes
                                 ? (payloadToReturnToPool = ArrayPool <byte> .Shared.Rent(payloadLength))
                                 : stackalloc byte[payloadLength];

                try
                {
                    int bytesWritten = Utf8.GetBytes(Payload, encodedPayload);
                    EncryptToken(encodedPayload.Slice(0, bytesWritten), context);
                }
                finally
                {
                    if (payloadToReturnToPool != null)
                    {
                        ArrayPool <byte> .Shared.Return(payloadToReturnToPool);
                    }
                }
            }
            else
            {
                ThrowHelper.ThrowInvalidOperationException_UndefinedPayload();
            }
        }
Пример #3
0
        /// <summary>Returns a new instance of <see cref="Jwks"/>.</summary>
        /// <param name="issuer">The issuer of the keys.</param>
        /// <param name="json">A string that contains JSON Web Key parameters in JSON format.</param>
        public static Jwks FromJson(string issuer, string json)
        {
            if (json is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.json);
            }

            byte[]? jsonToReturn = null;
            try
            {
                int         length   = Utf8.GetMaxByteCount(json.Length);
                Span <byte> jsonSpan = length <= Constants.MaxStackallocBytes
                            ? stackalloc byte[length]
                            : (jsonToReturn = ArrayPool <byte> .Shared.Rent(length));
                length = Utf8.GetBytes(json, jsonSpan);
                return(FromJson(issuer, jsonSpan.Slice(0, length)));
            }
            finally
            {
                if (jsonToReturn != null)
                {
                    ArrayPool <byte> .Shared.Return(jsonToReturn);
                }
            }
        }
Пример #4
0
 /// <summary>
 /// Initializes a new instance of <see cref="SignatureAlgorithm"/>.
 /// </summary>
 /// <param name="id"></param>
 /// <param name="name"></param>
 /// <param name="category"></param>
 /// <param name="requiredKeySizeInBits"></param>
 /// <param name="hashAlgorithm"></param>
 public SignatureAlgorithm(int id, string name, AlgorithmCategory category, ushort requiredKeySizeInBits, HashAlgorithmName hashAlgorithm)
 {
     _id       = id;
     _utf8Name = Utf8.GetBytes(name);
     _category = category;
     _requiredKeySizeInBits = requiredKeySizeInBits;
     _hashAlgorithm         = hashAlgorithm;
 }
Пример #5
0
 /// <summary>
 /// Initializes a new instance of <see cref="KeyManagementAlgorithm"/>.
 /// </summary>
 /// <param name="id"></param>
 /// <param name="name"></param>
 /// <param name="keyType"></param>
 /// <param name="requiredKeySizeInBits"></param>
 /// <param name="wrappedAlgorithm"></param>
 /// <param name="produceEncryptedKey"></param>
 public KeyManagementAlgorithm(byte id, string name, AlgorithmCategory keyType, ushort requiredKeySizeInBits, KeyManagementAlgorithm?wrappedAlgorithm, bool produceEncryptedKey)
 {
     _id       = id;
     _utf8Name = Utf8.GetBytes(name);
     _category = keyType;
     _requiredKeySizeInBits = requiredKeySizeInBits;
     _wrappedAlgorithm      = wrappedAlgorithm;
     _produceEncryptionKey  = produceEncryptedKey;
 }
Пример #6
0
        /// <summary>
        /// Decodes a string of UTF-8 base64url-encoded text.
        /// </summary>
        public static byte[] Decode(string data)
        {
            if (data is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.data);
            }

            return(Decode(Utf8.GetBytes(data)));
        }
Пример #7
0
 /// <summary>
 /// Initializes a new instance of <see cref="EncryptionAlgorithm"/>.
 /// </summary>
 /// <param name="id"></param>
 /// <param name="name"></param>
 /// <param name="requiredKeySizeInBytes"></param>
 /// <param name="hashAlgorithm"></param>
 /// <param name="requiredKeyWrappedSizeInBytes"></param>
 /// <param name="category"></param>
 public EncryptionAlgorithm(sbyte id, string name, ushort requiredKeySizeInBytes, SignatureAlgorithm?hashAlgorithm, ushort requiredKeyWrappedSizeInBytes, EncryptionType category)
 {
     _id       = id;
     _utf8Name = Utf8.GetBytes(name);
     _requiredKeySizeInBytes = requiredKeySizeInBytes;
     _signatureAlgorithm     = hashAlgorithm;
     _keyWrappedSizeInBytes  = requiredKeyWrappedSizeInBytes;
     _category = category;
 }
Пример #8
0
        /// <summary>Returns a new instance of <see cref="PasswordBasedJwk"/>.</summary>
        /// <remarks>The passphrase should not be longer that 128 bytes, and at least 16 bytes for "PBES2-HS256+A128KW",
        /// 24 bytes for "PBES2-HS384+A192KW" and 32 bytes for "PBES2-HS512+A256KW"</remarks>
        /// <param name="passphrase">The passphrase used for the key derivation.
        /// This should not be longer that 128 bytes, and at least 16 bytes for "PBES2-HS256+A128KW",
        /// 24 bytes for "PBES2-HS384+A192KW" and 32 bytes for "PBES2-HS512+A256KW"</param>
        /// <param name="algorithm">The key encryption algorithm. It must be a PBES2 algorithm.</param>
        /// <param name="iterationCount">The number of iterations. Should be at least 1000.</param>
        /// <param name="saltSizeInBytes">The salt size, in bytes. Should be at least 8 bytes. Value greater than 256 bytes is not supported.</param>
        /// <param name="computeThumbprint">Defines whether the thubpring should be computed.</param>
        public static PasswordBasedJwk FromPassphrase(string passphrase, KeyManagementAlgorithm algorithm, uint iterationCount = 1000, uint saltSizeInBytes = 8, bool computeThumbprint = true)
        {
            if (passphrase is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.bytes);
            }

            var innerKey = SymmetricJwk.FromByteArray(Utf8.GetBytes(passphrase), algorithm, computeThumbprint);

            return(new PasswordBasedJwk(innerKey, iterationCount, saltSizeInBytes, algorithm));
        }
        /// <summary>Requires a specific issuer. This value is used if no issuer is defined by the method <see cref="RequireSignatureByDefault(string, IKeyProvider, SignatureAlgorithm?)"/>.</summary>
        public TokenValidationPolicyBuilder DefaultIssuer(string issuer)
        {
            if (string.IsNullOrEmpty(issuer))
            {
                throw new ArgumentNullException(nameof(issuer));
            }

            _issuers.Add(Utf8.GetBytes(issuer));
            _control |= TokenValidationPolicy.IssuerMask;
            return(this);
        }
Пример #10
0
        /// <summary>Requires a specific audience.</summary>
        public TokenValidationPolicyBuilder RequireAudience(string audience)
        {
            if (string.IsNullOrEmpty(audience))
            {
                throw new ArgumentNullException(nameof(audience));
            }

            _audiences.Add(Utf8.GetBytes(audience));
            _control |= TokenValidationPolicy.AudienceMask;
            return(this);
        }
Пример #11
0
        /// <summary>
        /// Requires a specific issuer.
        /// </summary>
        /// <param name="issuer"></param>
        /// <returns></returns>
        public TokenValidationPolicyBuilder RequireIssuer(string issuer)
        {
            if (string.IsNullOrEmpty(issuer))
            {
                throw new ArgumentNullException(nameof(issuer));
            }

            _issuer   = Utf8.GetBytes(issuer);
            _control |= TokenValidationPolicy.IssuerFlag;
            return(this);
        }
Пример #12
0
        /// <summary>
        /// Defines the default signature validation when there is no issuer configuration.
        /// Use the method <see cref="RequireSignature(string, Jwk, SignatureAlgorithm)"/> for linking the issuer with the signature.
        /// </summary>
        public TokenValidationPolicyBuilder RequireSignatureByDefault(Jwk key, string algorithm)
        {
            if (algorithm is null)
            {
                throw new ArgumentNullException(nameof(algorithm));
            }

            if (!SignatureAlgorithm.TryParse(Utf8.GetBytes(algorithm), out var alg))
            {
                throw new NotSupportedException($"The algorithm '{alg}' is not supported.");
            }

            return(RequireSignatureByDefault(new Jwks(key), alg));
        }
Пример #13
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CompressionAlgorithm"/> class.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="name"></param>
        /// <param name="compressor"></param>
        public CompressionAlgorithm(sbyte id, string name, Compressor compressor)
        {
            if (name is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.name);
            }

            if (compressor is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.compressor);
            }

            _id        = id;
            _utf8Name  = Utf8.GetBytes(name);
            Compressor = compressor;
        }
Пример #14
0
 internal static int GetUtf8FromText(ReadOnlySpan <char> text, Span <byte> dest)
 {
     try
     {
         return(Utf8.GetBytes(text, dest));
     }
     catch (EncoderFallbackException ex)
     {
         // We want to be consistent with the exception being thrown
         // so the user only has to catch a single exception.
         // Since we already throw ArgumentException when validating other arguments,
         // using that exception for failure to encode invalid UTF-16 chars as well.
         // Therefore, wrapping the EncoderFallbackException around an ArgumentException.
         //throw  ThrowHelper.GetArgumentException_ReadInvalidUTF16(ex);
         throw new InvalidOperationException("Invalid UTF16", ex);
     }
 }
Пример #15
0
        /// <summary>Requires a least one audience contained in the <paramref name="audiences"/>.</summary>
        public TokenValidationPolicyBuilder RequireAudience(IEnumerable <string> audiences)
        {
            if (audiences == null)
            {
                throw new ArgumentNullException(nameof(audiences));
            }

            foreach (var audience in audiences)
            {
                if (audience != null)
                {
                    _audiences.Add(Utf8.GetBytes(audience));
                    _control |= TokenValidationPolicy.AudienceMask;
                }
            }

            return(this);
        }
Пример #16
0
        /// <summary>Parses and validates a JWT encoded as a JWS or JWE in compact serialized format.</summary>
        /// <param name="token">The JWT encoded as JWE or JWS</param>
        /// <param name="policy">The validation policy.</param>
        /// <param name="jwt">The resulting <see cref="Jwt"/>.</param>
        public static bool TryParse(string token, TokenValidationPolicy policy, out Jwt jwt)
        {
            if (token is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.token);
            }

            if (policy is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.policy);
            }

            if (token.Length == 0)
            {
                jwt = new Jwt(TokenValidationError.MalformedToken());
                return(false);
            }

            int length = Utf8.GetMaxByteCount(token.Length);

            if (length > policy.MaximumTokenSizeInBytes)
            {
                jwt = new Jwt(TokenValidationError.MalformedToken());
                return(false);
            }

            byte[]? utf8ArrayToReturnToPool = null;
            var utf8Token = length <= Constants.MaxStackallocBytes
                  ? stackalloc byte[length]
                  : (utf8ArrayToReturnToPool = ArrayPool <byte> .Shared.Rent(length));

            try
            {
                int bytesWritten = Utf8.GetBytes(token, utf8Token);
                return(TryParse(utf8Token.Slice(0, bytesWritten), policy, out jwt));
            }
            finally
            {
                if (utf8ArrayToReturnToPool != null)
                {
                    ArrayPool <byte> .Shared.Return(utf8ArrayToReturnToPool);
                }
            }
        }
Пример #17
0
        /// <summary>Decodes a span of UTF-8 base64-encoded text into a span of bytes.</summary>
        /// <returns>The number of the bytes written to <paramref name="data"/>.</returns>
        public static int Decode(ReadOnlySpan <char> base64, Span <byte> data)
        {
            byte[]? arrayToReturn = null;
            var buffer = base64.Length > Constants.MaxStackallocBytes
                ? (arrayToReturn = ArrayPool <byte> .Shared.Rent(base64.Length))
                : stackalloc byte[Constants.MaxStackallocBytes];

            try
            {
                int length = Utf8.GetBytes(base64, buffer);
                return(Decode(buffer.Slice(0, length), data));
            }
            finally
            {
                if (arrayToReturn != null)
                {
                    ArrayPool <byte> .Shared.Return(arrayToReturn);
                }
            }
        }
Пример #18
0
        /// <summary>
        /// Encodes a string of UTF-8 text.
        /// </summary>
        /// <returns>The base64-url encoded string.</returns>
        public static byte[] Encode(ReadOnlySpan <char> data)
        {
            byte[]? utf8ArrayToReturn = null;
            try
            {
                var utf8Data = data.Length > Constants.MaxStackallocBytes
                    ? (utf8ArrayToReturn = ArrayPool <byte> .Shared.Rent(data.Length)).AsSpan(0, data.Length)
                    : stackalloc byte[data.Length];

                Utf8.GetBytes(data, utf8Data);
                return(Encode(utf8Data));
            }
            finally
            {
                if (utf8ArrayToReturn != null)
                {
                    ArrayPool <byte> .Shared.Return(utf8ArrayToReturn);
                }
            }
        }
Пример #19
0
        /// <summary>
        /// Decodes a span of UTF-8 base64url-encoded text into a span of bytes.
        /// </summary>
        /// <returns>The number of the bytes written to <paramref name="data"/>.</returns>
        public static int Decode(ReadOnlySpan <char> base64Url, Span <byte> data)
        {
            byte[]? arrayToReturn = null;
            var buffer = base64Url.Length > Constants.MaxStackallocBytes
                ? (arrayToReturn = ArrayPool <byte> .Shared.Rent(base64Url.Length)).AsSpan(0, base64Url.Length)
                : stackalloc byte[base64Url.Length];

            try
            {
                Utf8.GetBytes(base64Url, buffer);
                return(Decode(buffer, data));
            }
            finally
            {
                if (arrayToReturn != null)
                {
                    ArrayPool <byte> .Shared.Return(arrayToReturn);
                }
            }
        }
Пример #20
0
        /// <summary>Encodes a string of UTF-8 text.</summary>
        /// <returns>The base64-url encoded string.</returns>
        /// <remarks>This method allocate an array of bytes. Use <see cref="Encode(ReadOnlySpan{byte}, Span{byte})"/> when possible.</remarks>
        public static byte[] Encode(ReadOnlySpan <char> data)
        {
            byte[]? utf8ArrayToReturn = null;
            try
            {
                int length   = Utf8.GetMaxByteCount(data.Length);
                var utf8Data = length > Constants.MaxStackallocBytes
                    ? (utf8ArrayToReturn = ArrayPool <byte> .Shared.Rent(length))
                    : stackalloc byte[Constants.MaxStackallocBytes];

                int written = Utf8.GetBytes(data, utf8Data);
                return(Encode(utf8Data.Slice(0, written)));
            }
            finally
            {
                if (utf8ArrayToReturn != null)
                {
                    ArrayPool <byte> .Shared.Return(utf8ArrayToReturn);
                }
            }
        }
Пример #21
0
        /// <inheritsdoc />
        public override void Encode(EncodingContext context, IBufferWriter <byte> output)
        {
            int payloadLength = Utf8.GetMaxByteCount(Payload.Length);

            byte[]? payloadToReturnToPool = null;
            Span <byte> encodedPayload = payloadLength > Constants.MaxStackallocBytes
                             ? (payloadToReturnToPool = ArrayPool <byte> .Shared.Rent(payloadLength))
                             : stackalloc byte[payloadLength];

            try
            {
                int bytesWritten = Utf8.GetBytes(Payload, encodedPayload);
                EncryptToken(context, encodedPayload.Slice(0, bytesWritten), output);
            }
            finally
            {
                if (payloadToReturnToPool != null)
                {
                    ArrayPool <byte> .Shared.Return(payloadToReturnToPool);
                }
            }
        }
Пример #22
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Jwk"/> class.
 /// </summary>
 /// <param name="alg"></param>
 protected Jwk(string alg)
 {
     Alg = Utf8.GetBytes(alg);
 }
Пример #23
0
 /// <summary>
 /// Gets or sets the <see cref="JwtProperty"/> at the specified key;
 /// </summary>
 /// <param name="key"></param>
 /// <returns></returns>
 public JwtProperty this[string key] => this[Utf8.GetBytes(key).AsSpan()];
Пример #24
0
 public SingleIssuerSignatureValidationPolicy(string issuer, SignatureValidationPolicy policy)
 {
     _issuer = Utf8.GetBytes(issuer);
     _policy = policy;
 }
Пример #25
0
 public MultiIssuersSignatureValidationPolicy(Dictionary <string, SignatureValidationPolicy> policies, SignatureValidationPolicy defaultPolicy)
 {
     _policies      = policies.ToDictionary(issuer => Utf8.GetBytes(issuer.Key), v => v.Value).ToArray();
     _defaultPolicy = defaultPolicy;
 }
Пример #26
0
 /// <summary>
 /// Adds a claim.
 /// </summary>
 /// <param name="name"></param>
 /// <param name="value"></param>
 /// <returns></returns>
 public JwtDescriptorBuilder AddClaim(string name, JwtObject value)
 => AddClaim(Utf8.GetBytes(name), value);
Пример #27
0
 /// <summary>
 /// Initializes a new instance of the <see cref="JwtHeader"/> class.
 /// </summary>
 /// <param name="json"></param>
 public static JwtHeader FromJson(string json)
 {
     return(JwtHeaderParser.ParseHeader(Utf8.GetBytes(json), TokenValidationPolicy.NoValidation));
 }
Пример #28
0
 /// <summary>
 /// Adds a claim.
 /// </summary>
 /// <param name="name"></param>
 /// <param name="value"></param>
 /// <returns></returns>
 public void AddClaim(string name, JwtProperty value)
 => AddClaim(Utf8.GetBytes(name), value);
Пример #29
0
 /// <summary>
 /// Adds a header parameter.
 /// </summary>
 /// <param name="name"></param>
 /// <param name="value"></param>
 /// <returns></returns>
 public JwtDescriptorBuilder AddHeader(string name, JwtArray value)
 => AddHeader(Utf8.GetBytes(name), value);
Пример #30
0
 public static Address FromJson(string json)
 {
     return(FromJson(Utf8.GetBytes(json)));
 }