Beispiel #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="KeyWrapper"/> class.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="encryptionAlgorithm"></param>
        /// <param name="algorithm"></param>
        protected KeyWrapper(Jwk key, EncryptionAlgorithm encryptionAlgorithm, KeyManagementAlgorithm algorithm)
        {
            if (key is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
            }

            if (!key.SupportKeyManagement(algorithm))
            {
                ThrowHelper.ThrowNotSupportedException_AlgorithmForKeyWrap(algorithm);
            }

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

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

            Algorithm           = algorithm;
            EncryptionAlgorithm = encryptionAlgorithm;
            Key = key;
        }
        /// <summary>Encrypt the token.</summary>
        protected void EncryptToken(ReadOnlySpan <byte> payload, EncodingContext context)
        {
            var output = context.BufferWriter;
            EncryptionAlgorithm enc = _enc;
            var key = _encryptionKey;

            if (key is null)
            {
                ThrowHelper.ThrowKeyNotFoundException();
                return;
            }

            KeyManagementAlgorithm alg = _alg;

            if (key.TryGetKeyWrapper(enc, alg, out var keyWrapper))
            {
                var header = Header;
                byte[]? wrappedKeyToReturnToPool      = null;
                byte[]? buffer64HeaderToReturnToPool  = null;
                byte[]? arrayCiphertextToReturnToPool = null;
                int         keyWrapSize = keyWrapper.GetKeyWrapSize();
                Span <byte> wrappedKey  = keyWrapSize <= Constants.MaxStackallocBytes ?
                                          stackalloc byte[keyWrapSize] :
                                          new Span <byte>(wrappedKeyToReturnToPool = ArrayPool <byte> .Shared.Rent(keyWrapSize), 0, keyWrapSize);
                var cek = keyWrapper.WrapKey(null, header, wrappedKey);

                try
                {
                    using var bufferWriter = new PooledByteBufferWriter();
                    var writer = new Utf8JsonWriter(bufferWriter, JsonSerializationBehavior.NoJsonValidation);
                    int base64EncodedHeaderLength  = 0;
                    ReadOnlySpan <byte> headerJson = default;
                    var headerCache = context.HeaderCache;
                    if (headerCache.TryGetHeader(header, alg, enc, _kid, _typ, _cty, out byte[]? cachedHeader))
        public bool TryGetHeader(JwtHeader header, KeyManagementAlgorithm alg, EncryptionAlgorithm enc, JsonEncodedText kid, string?typ, string?cty, [NotNullWhen(true)] out byte[]?base64UrlHeader)
        {
#if NET5_0_OR_GREATER
            Unsafe.SkipInit(out base64UrlHeader);
#else
            base64UrlHeader = default;
#endif
            return(false);
        }
Beispiel #4
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));
        }
Beispiel #5
0
            /// <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);
            }
Beispiel #6
0
 internal static void ThrowCryptographicException_CreateSymmetricAlgorithmFailed(Jwk key, KeyManagementAlgorithm algorithm, Exception innerException) => throw CreateCryptographicException_CreateSymmetricAlgorithmFailed(key, algorithm, innerException);
Beispiel #7
0
 /// <inheritsdoc />
 public override bool SupportKeyManagement(KeyManagementAlgorithm algorithm)
 => algorithm.Category == AlgorithmCategory.Pbkdf2;
Beispiel #8
0
 /// <inheritsdoc />
 protected override KeyUnwrapper CreateKeyUnwrapper(EncryptionAlgorithm encryptionAlgorithm, KeyManagementAlgorithm algorithm)
 => new Pbes2KeyUnwrapper(this, encryptionAlgorithm, algorithm);
Beispiel #9
0
 private PasswordBasedJwk(SymmetricJwk key, uint iterationCount, uint saltSizeInBytes, KeyManagementAlgorithm algorithm)
     : base(algorithm)
 {
     Debug.Assert(key != null);
     Debug.Assert(algorithm != null);
     _inner           = key;
     _iterationCount  = iterationCount;
     _saltSizeInBytes = saltSizeInBytes;
     Kid = key.Kid;
 }
Beispiel #10
0
 /// <summary>Initializes a new instance of the <see cref="JweDescriptor"/> class.</summary>
 public JweDescriptor(Jwk encryptionKey, KeyManagementAlgorithm alg, EncryptionAlgorithm enc, CompressionAlgorithm?zip = null, string?typ = null, string?cty = Constants.Jwt)
     : base(encryptionKey, alg, enc, zip, typ, cty)
 {
 }
Beispiel #11
0
 /// <summary>Initializes a new instance of the <see cref="BinaryJweDescriptor"/> class.</summary>
 public BinaryJweDescriptor(Jwk encryptionKey, KeyManagementAlgorithm alg, EncryptionAlgorithm enc, CompressionAlgorithm?zip = null, string?typ = JwtMediaTypeValues.OctetStream, string?cty = null)
     : base(encryptionKey, alg, enc, zip, typ, cty)
 {
     _payload = Array.Empty <byte>();
 }
 /// <summary>Initializes a new instance of <see cref="PlaintextJweDescriptor"/>.</summary>
 public PlaintextJweDescriptor(Jwk encryptionKey, KeyManagementAlgorithm alg, EncryptionAlgorithm enc, CompressionAlgorithm?zip = null, string?typ = JwtMediaTypeValues.Plain, string?cty = null)
     : base(encryptionKey, alg, enc, zip, typ, cty)
 {
 }
Beispiel #13
0
 public void AddHeader(JwtHeader header, KeyManagementAlgorithm alg, EncryptionAlgorithm enc, JsonEncodedText kid, string?typ, string?cty, ReadOnlySpan <byte> base64UrlHeader)
 {
     _jweCache.AddHeader(header, alg, enc, kid, typ, cty, base64UrlHeader);
 }
Beispiel #14
0
 /// <summary>Initializes a new instance of the <see cref="JwksJweDescriptor"/> class.</summary>
 public JwksJweDescriptor(Jwk encryptionKey, KeyManagementAlgorithm alg, EncryptionAlgorithm enc, CompressionAlgorithm?zip = null, string?typ = null, string?cty = JwtContentTypeValues.Jwks)
     : base(encryptionKey, alg, enc, zip, typ, cty)
 {
     _payload = new Jwks();
 }
Beispiel #15
0
 private static Exception CreateCryptographicException_CreateSymmetricAlgorithmFailed(Jwk key, KeyManagementAlgorithm algorithm, Exception innerException) => new CryptographicException($"Failed to create symmetric algorithm for key wrap with key: '{key.Kid}', algorithm: '{algorithm}'.", innerException);
Beispiel #16
0
 private static Exception CreateArgumentOutOfRangeException_KeyWrapKeySizeIncorrect(KeyManagementAlgorithm algorithm, int requiredValue, Jwk key, int currentKeySize) => new ArgumentOutOfRangeException(nameof(key), $"The key '{key.Kid}' for key wrapping with algorithm '{algorithm}' must be of '{requiredValue}' bits. Key size: '{currentKeySize}'.");
Beispiel #17
0
 internal static void ThrowArgumentOutOfRangeException_KeyWrapKeySizeIncorrect(KeyManagementAlgorithm algorithm, int requiredValue, Jwk key, int currentKeySize) => throw CreateArgumentOutOfRangeException_KeyWrapKeySizeIncorrect(algorithm, requiredValue, key, currentKeySize);
Beispiel #18
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Jwk"/> class.
 /// </summary>
 /// <param name="alg"></param>
 protected Jwk(KeyManagementAlgorithm alg)
 {
     Alg = alg.Utf8Name;
     _keyManagementAlgorithm = alg;
 }
Beispiel #19
0
            /// <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();
                        }
                    }
                }
            }
Beispiel #20
0
 private static Exception CreateNotSupportedException_Algorithm(KeyManagementAlgorithm algorithm) => new NotSupportedException($"The algorithm '{algorithm}' is not supported for this kind of JWK.");
Beispiel #21
0
 public bool TryGetHeader(JwtHeader header, KeyManagementAlgorithm alg, EncryptionAlgorithm enc, JsonEncodedText kid, string?typ, string?cty, [NotNullWhen(true)] out byte[]?base64UrlHeader)
 {
     return(_jweCache.TryGetHeader(header, alg, enc, kid, typ, cty, out base64UrlHeader));
 }
Beispiel #22
0
 /// <inheritsdoc />
 protected override KeyWrapper CreateKeyWrapper(EncryptionAlgorithm encryptionAlgorithm, KeyManagementAlgorithm algorithm) => throw new NotImplementedException();
 public void AddHeader(JwtHeader header, KeyManagementAlgorithm alg, EncryptionAlgorithm enc, JsonEncodedText kid, string?typ, string?cty, ReadOnlySpan <byte> base6UrlHeader)
 {
 }
Beispiel #24
0
        /// <summary>Initializes a new instance of the <see cref="JweDescriptor{TPayload}"/> class.</summary>
        protected JweDescriptor(Jwk encryptionKey, KeyManagementAlgorithm alg, EncryptionAlgorithm enc, CompressionAlgorithm?zip = null, string?typ = null, string?cty = null)
        {
            _encryptionKey = encryptionKey ?? throw new ArgumentNullException(nameof(encryptionKey));
            _alg           = alg ?? throw new ArgumentNullException(nameof(alg));
            _enc           = enc ?? throw new ArgumentNullException(nameof(enc));
            _zip           = zip ?? CompressionAlgorithm.NoCompression;

            var kid = encryptionKey.Kid;

            if (!kid.EncodedUtf8Bytes.IsEmpty)
            {
                _kid = kid;
                if (zip != null)
                {
                    if (cty != null)
                    {
                        _cty = cty;
                        Header.FastAdd(
                            new JwtMember(JwtHeaderParameterNames.Alg, alg.Name),
                            new JwtMember(JwtHeaderParameterNames.Enc, enc.Name),
                            new JwtMember(JwtHeaderParameterNames.Kid, kid),
                            new JwtMember(JwtHeaderParameterNames.Zip, zip.Name),
                            new JwtMember(JwtHeaderParameterNames.Cty, cty));
                    }
                    else
                    {
                        Header.FastAdd(
                            new JwtMember(JwtHeaderParameterNames.Alg, alg.Name),
                            new JwtMember(JwtHeaderParameterNames.Enc, enc.Name),
                            new JwtMember(JwtHeaderParameterNames.Kid, kid),
                            new JwtMember(JwtHeaderParameterNames.Zip, zip.Name));
                    }
                }
                else
                {
                    if (cty != null)
                    {
                        _cty = cty;
                        Header.FastAdd(
                            new JwtMember(JwtHeaderParameterNames.Alg, alg.Name),
                            new JwtMember(JwtHeaderParameterNames.Enc, enc.Name),
                            new JwtMember(JwtHeaderParameterNames.Kid, kid),
                            new JwtMember(JwtHeaderParameterNames.Cty, cty));
                    }
                    else
                    {
                        Header.FastAdd(
                            new JwtMember(JwtHeaderParameterNames.Alg, alg.Name),
                            new JwtMember(JwtHeaderParameterNames.Enc, enc.Name),
                            new JwtMember(JwtHeaderParameterNames.Kid, kid));
                    }
                }
            }
            else
            {
                if (zip != null)
                {
                    if (cty != null)
                    {
                        _cty = cty;
                        Header.FastAdd(
                            new JwtMember(JwtHeaderParameterNames.Alg, alg.Name),
                            new JwtMember(JwtHeaderParameterNames.Enc, enc.Name),
                            new JwtMember(JwtHeaderParameterNames.Zip, zip.Name),
                            new JwtMember(JwtHeaderParameterNames.Cty, cty));
                    }
                    else
                    {
                        Header.FastAdd(
                            new JwtMember(JwtHeaderParameterNames.Alg, alg.Name),
                            new JwtMember(JwtHeaderParameterNames.Enc, enc.Name),
                            new JwtMember(JwtHeaderParameterNames.Zip, zip.Name));
                    }
                }
                else
                {
                    if (cty != null)
                    {
                        _cty = cty;
                        Header.FastAdd(
                            new JwtMember(JwtHeaderParameterNames.Alg, alg.Name),
                            new JwtMember(JwtHeaderParameterNames.Enc, enc.Name),
                            new JwtMember(JwtHeaderParameterNames.Cty, cty));
                    }
                    else
                    {
                        Header.FastAdd(
                            new JwtMember(JwtHeaderParameterNames.Alg, alg.Name),
                            new JwtMember(JwtHeaderParameterNames.Enc, enc.Name));
                    }
                }
            }

            if (typ != null)
            {
                _typ = typ;
                Header.Add(JwtHeaderParameterNames.Typ, typ);
            }
        }
Beispiel #25
0
 internal static void ThrowNotSupportedException_Algorithm(KeyManagementAlgorithm algorithm) => throw CreateNotSupportedException_Algorithm(algorithm);
 public bool TryGetHeader(JwtHeader header, KeyManagementAlgorithm alg, EncryptionAlgorithm enc, JsonEncodedText kid, string?typ, string?cty, [NotNullWhen(true)] out byte[]?base64UrlHeader)
 {
     base64UrlHeader = null;
     return(false);
 }
Beispiel #27
0
 /// <inheritsdoc />
 public override bool SupportKeyManagement(KeyManagementAlgorithm algorithm) => throw new NotImplementedException();
Beispiel #28
0
 /// <summary>
 /// Computes a unique key for the combinaison of the <see cref="EncryptionAlgorithm"/> and the <see cref="KeyManagementAlgorithm"/>.
 /// </summary>
 /// <param name="algorithm"></param>
 /// <returns></returns>
 public int ComputeKey(KeyManagementAlgorithm algorithm)
 {
     return((_id << 8) | (byte)algorithm.Id);
 }
Beispiel #29
0
 /// <summary>
 /// Initializes a new instance of the <see cref="AsymmetricJwk"/> class.
 /// </summary>
 protected AsymmetricJwk(KeyManagementAlgorithm alg)
     : base(alg)
 {
 }
Beispiel #30
0
 /// <inheritsdoc />
 protected override KeyWrapper CreateKeyWrapper(EncryptionAlgorithm encryptionAlgorithm, KeyManagementAlgorithm algorithm)
 => new Pbes2KeyWrapper(this, encryptionAlgorithm, algorithm, _iterationCount, _saltSizeInBytes, _saltGenerator);