Esempio n. 1
0
        /// <summary>
        /// Encodes given binary data to JWT token and sign it using given algorithm.
        /// </summary>
        /// <param name="payload">Binary data to encode (not null)</param>
        /// <param name="key">key for signing, suitable for provided JWS algorithm, can be null.</param>
        /// <param name="algorithm">JWT algorithm to be used.</param>
        /// <param name="extraHeaders">optional extra headers to pass along with the payload.</param>
        /// <param name="settings">optional settings to override global DefaultSettings</param>
        /// <returns>JWT in compact serialization form, digitally signed.</returns>
        public static string EncodeBytes(byte[] payload, object key, JwsAlgorithm algorithm, IDictionary <string, object> extraHeaders = null, JwtSettings settings = null)
        {
            if (payload == null)
            {
                throw new ArgumentNullException(nameof(payload));
            }

            if (extraHeaders == null) //allow overload, but keep backward compatible defaults
            {
                extraHeaders = new Dictionary <string, object> {
                    { "typ", "JWT" }
                };
            }
            var jwtSettings = GetSettings(settings);

            var jwtHeader = new Dictionary <string, object> {
                { "alg", jwtSettings.JwsHeaderValue(algorithm) }
            };

            Dictionaries.Append(jwtHeader, extraHeaders);
            byte[] headerBytes = Encoding.UTF8.GetBytes(jwtSettings.JsonMapper.Serialize(jwtHeader));

            var bytesToSign = Encoding.UTF8.GetBytes(Compact.Serialize(headerBytes, payload));

            var jwsAlgorithm = jwtSettings.Jws(algorithm);

            if (jwsAlgorithm == null)
            {
                throw new JoseException(string.Format("Unsupported JWS algorithm requested: {0}", algorithm));
            }

            byte[] signature = jwsAlgorithm.Sign(bytesToSign, key);

            return(Compact.Serialize(headerBytes, payload, signature));
        }
Esempio n. 2
0
        /// <summary>
        /// Parses signed JWT token, extracts and returns payload part as binary data. This method
        /// is NOT supported for encrypted JWT tokens. This method is NOT performing integrity checking.
        /// </summary>
        /// <param name="token">signed JWT token</param>
        /// <param name="settings">optional settings to override global DefaultSettings</param>
        /// <returns>unmarshalled payload</returns>
        /// <exception cref="JoseException">if encrypted JWT token is provided</exception>
        public static byte[] PayloadBytes(string token, JwtSettings settings = null)
        {
            byte[][] parts = Compact.Parse(token);

            if (parts.Length > 3)
            {
                throw new JoseException(
                          "Getting payload for encrypted tokens is not supported. Please use Jose.JWT.Decode() method instead.");
            }

            return(parts[1]);
        }
Esempio n. 3
0
        private static byte[] DecryptBytes(byte[][] parts, object key, JweAlgorithm?jweAlg, JweEncryption?jweEnc, JwtSettings settings = null)
        {
            byte[]      header       = parts[0];
            byte[]      encryptedCek = parts[1];
            byte[]      iv           = parts[2];
            byte[]      cipherText   = parts[3];
            byte[]      authTag      = parts[4];
            JwtSettings jwtSettings  = GetSettings(settings);
            IDictionary <string, string> jwtHeader = jwtSettings.JsonMapper.Parse(Encoding.UTF8.GetString(header));

            JweAlgorithm  headerAlg = jwtSettings.JwaAlgorithmFromHeader((string)jwtHeader["alg"]);
            JweEncryption headerEnc = jwtSettings.JweAlgorithmFromHeader((string)jwtHeader["enc"]);

            IKeyManagement keys = jwtSettings.Jwa(headerAlg);
            IJweAlgorithm  enc  = jwtSettings.Jwe(headerEnc);

            if (keys == null)
            {
                throw new JoseException(string.Format("Unsupported JWA algorithm requested: {0}", headerAlg));
            }

            if (enc == null)
            {
                throw new JoseException(string.Format("Unsupported JWE algorithm requested: {0}", headerEnc));
            }

            if (jweAlg != null && (JweAlgorithm)jweAlg != headerAlg)
            {
                throw new InvalidAlgorithmException("The algorithm type passed to the Decrypt method did not match the algorithm type in the header.");
            }

            if (jweEnc != null && (JweEncryption)jweEnc != headerEnc)
            {
                throw new InvalidAlgorithmException("The encryption type passed to the Decrypt method did not match the encryption type in the header.");
            }

            byte[] cek = keys.Unwrap(encryptedCek, key, enc.KeySize, jwtHeader);
            byte[] aad = Encoding.UTF8.GetBytes(Compact.Serialize(header));

            byte[] plainText = enc.Decrypt(aad, cek, iv, cipherText, authTag);

            if (jwtHeader.ContainsKey("zip"))
            {
                var compression = jwtSettings.Compression((string)jwtHeader["zip"]);

                plainText = compression.Decompress(plainText);
            }

            return(plainText);
        }
Esempio n. 4
0
        /// <summary>
        /// Decodes JWT token by performing necessary decompression/decryption and signature
        /// verification as defined in JWT token header. Resulting json string will be parsed and
        /// mapped to desired type via configured IJsonMapper implementation.
        /// </summary>
        /// <typeparam name="T">Deserid object type after json mapping</typeparam>
        /// <param name="token">JWT token in compact serialization form.</param>
        /// <param name="key">key for decoding suitable for JWT algorithm used.</param>
        /// <param name="alg">The algorithm type that we expect to receive in the header.</param>
        /// <param name="enc">The encryption type that we expect to receive in the header.</param>
        /// <param name="settings">optional settings to override global DefaultSettings</param>
        /// <returns>object of provided T, result of decoded json mapping</returns>
        /// <exception cref="IntegrityException">if signature validation failed</exception>
        /// <exception cref="EncryptionException">if JWT token can't be decrypted</exception>
        /// <exception cref="InvalidAlgorithmException">
        /// if JWT signature, encryption or compression algorithm is not supported
        /// </exception>
        //public static T Decode<T>(string token, object key, JweAlgorithm alg, JweEncryption enc, JwtSettings settings = null)
        //{
        //    return GetSettings(settings).JsonMapper.Parse<T>(Decode(token, key, alg, enc, settings));
        //}

        /// <summary>
        /// Decodes JWT token by performing necessary decompression/decryption and signature
        /// verification as defined in JWT token header. Resulting json string will be parsed and
        /// mapped to desired type via configured IJsonMapper implementation.
        /// </summary>
        /// <typeparam name="T">Deserid object type after json mapping</typeparam>
        /// <param name="token">JWT token in compact serialization form.</param>
        /// <param name="key">key for decoding suitable for JWT algorithm used.</param>
        /// <param name="alg">The algorithm type that we expect to receive in the header.</param>
        /// <param name="settings">optional settings to override global DefaultSettings</param>
        /// <returns>object of provided T, result of decoded json mapping</returns>
        /// <exception cref="IntegrityException">if signature validation failed</exception>
        /// <exception cref="EncryptionException">if JWT token can't be decrypted</exception>
        /// <exception cref="InvalidAlgorithmException">
        /// if JWT signature, encryption or compression algorithm is not supported
        /// </exception>
        //public static T Decode<T>(string token, object key, JwsAlgorithm alg, JwtSettings settings = null)
        //{
        //    return GetSettings(settings).JsonMapper.Parse<T>(Decode(token, key, alg, settings));
        //}

        /// <summary>
        /// Decodes JWT token by performing necessary decompression/decryption and signature
        /// verification as defined in JWT token header. Resulting json string will be parsed and
        /// mapped to desired type via configured IJsonMapper implementation.
        /// </summary>
        /// <typeparam name="T">Deserid object type after json mapping</typeparam>
        /// <param name="token">JWT token in compact serialization form.</param>
        /// <param name="key">key for decoding suitable for JWT algorithm used, can be null.</param>
        /// <param name="settings">optional settings to override global DefaultSettings</param>
        /// <returns>object of provided T, result of decoded json mapping</returns>
        /// <exception cref="IntegrityException">if signature validation failed</exception>
        /// <exception cref="EncryptionException">if JWT token can't be decrypted</exception>
        /// <exception cref="InvalidAlgorithmException">
        /// if JWT signature, encryption or compression algorithm is not supported
        /// </exception>
        //public static T Decode<T>(string token, object key = null, JwtSettings settings = null)
        //{
        //    return GetSettings(settings).JsonMapper.Parse<T>(Decode(token, key, settings));
        //}

        private static byte[] DecodeBytes(string token, object key = null, JwsAlgorithm?expectedJwsAlg = null, JweAlgorithm?expectedJweAlg = null, JweEncryption?expectedJweEnc = null, JwtSettings settings = null)
        {
            Ensure.IsNotEmpty(token, "Incoming token expected to be in compact serialization form, not empty, whitespace or null.");

            byte[][] parts = Compact.Parse(token);

            if (parts.Length == 5) //encrypted JWT
            {
                return(DecryptBytes(parts, key, expectedJweAlg, expectedJweEnc, settings));
            }
            else
            {
                //signed or plain JWT
                byte[] header    = parts[0];
                byte[] payload   = parts[1];
                byte[] signature = parts[2];

                byte[] securedInput = Encoding.UTF8.GetBytes(Compact.Serialize(header, payload));

                var jwtSettings = GetSettings(settings);

                var headerData   = jwtSettings.JsonMapper.Parse(Encoding.UTF8.GetString(header));
                var algorithm    = (string)headerData["alg"];
                var jwsAlgorithm = jwtSettings.JwsAlgorithmFromHeader(algorithm);
                if (expectedJwsAlg != null && expectedJwsAlg != jwsAlgorithm)
                {
                    throw new InvalidAlgorithmException(
                              "The algorithm type passed to the Decode method did not match the algorithm type in the header.");
                }

                var jwsAlgorithmImpl = jwtSettings.Jws(jwsAlgorithm);

                if (jwsAlgorithmImpl == null)
                {
                    throw new JoseException(string.Format("Unsupported JWS algorithm requested: {0}", algorithm));
                }

                if (!jwsAlgorithmImpl.Verify(signature, securedInput, key))
                {
                    throw new IntegrityException("Invalid signature.");
                }

                return(payload);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Encodes given binary data to JWT token and applies requested encryption/compression algorithms.
        /// </summary>
        /// <param name="payload">Binary data to encode (not null)</param>
        /// <param name="key">key for encryption, suitable for provided JWS algorithm, can be null.</param>
        /// <param name="alg">JWT algorithm to be used.</param>
        /// <param name="enc">encryption algorithm to be used.</param>
        /// <param name="compression">optional compression type to use.</param>
        /// <param name="extraHeaders">optional extra headers to pass along with the payload.</param>
        /// <param name="settings">optional settings to override global DefaultSettings</param>
        /// <returns>JWT in compact serialization form, encrypted and/or compressed.</returns>
        public static string EncodeBytes(byte[] payload, object key, JweAlgorithm alg, JweEncryption enc, JweCompression?compression = null, IDictionary <string, string> extraHeaders = null, JwtSettings settings = null)
        {
            if (payload == null)
            {
                throw new ArgumentNullException(nameof(payload));
            }
            JwtSettings    jwtSettings = GetSettings(settings);
            IKeyManagement keys        = jwtSettings.Jwa(alg);
            IJweAlgorithm  _enc        = jwtSettings.Jwe(enc);

            if (keys == null)
            {
                throw new JoseException(string.Format("Unsupported JWA algorithm requested: {0}", alg));
            }

            if (_enc == null)
            {
                throw new JoseException(string.Format("Unsupported JWE algorithm requested: {0}", enc));
            }

            IDictionary <string, string> jwtHeader = new Dictionary <string, string> {
                { "alg", jwtSettings.JwaHeaderValue(alg) }, { "enc", jwtSettings.JweHeaderValue(enc) }
            };

            Dictionaries.Append(jwtHeader, extraHeaders);

            byte[][] contentKeys  = keys.WrapNewKey(_enc.KeySize, key, jwtHeader);
            byte[]   cek          = contentKeys[0];
            byte[]   encryptedCek = contentKeys[1];

            if (compression.HasValue)
            {
                jwtHeader["zip"] = jwtSettings.CompressionHeader(compression.Value);
                payload          = jwtSettings.Compression(compression.Value).Compress(payload);
            }

            byte[]   header   = Encoding.UTF8.GetBytes(jwtSettings.JsonMapper.Serialize(jwtHeader));
            byte[]   aad      = Encoding.UTF8.GetBytes(Compact.Serialize(header));
            byte[][] encParts = _enc.Encrypt(aad, payload, cek);

            return(Compact.Serialize(header, encryptedCek, encParts[0], encParts[1], encParts[2]));
        }