public override PasetoSecurityToken Verify(PasetoToken token, IEnumerable <SecurityKey> signingKeys)
        {
            if (token == null)
            {
                throw new ArgumentNullException(nameof(token));
            }
            if (signingKeys == null || !signingKeys.Any())
            {
                throw new ArgumentNullException(nameof(signingKeys));
            }

            var keys = signingKeys.OfType <EdDsaSecurityKey>().ToList();

            if (!keys.Any())
            {
                throw new SecurityTokenInvalidSigningKeyException($"PASETO v2 requires key of type {typeof(EdDsaSecurityKey)}");
            }

            if (token.Version != PasetoConstants.Versions.V2)
            {
                throw new ArgumentException("Invalid PASETO version");
            }
            if (token.Purpose != PasetoConstants.Purposes.Public)
            {
                throw new ArgumentException("Invalid PASETO purpose");
            }

            // decode payload
            var payload = Base64UrlEncoder.DecodeBytes(token.EncodedPayload);

            if (payload.Length < 64)
            {
                throw new SecurityTokenInvalidSignatureException("Payload does not contain signature");
            }

            // extract signature from payload (rightmost 64 bytes)
            var signature = new byte[64];

            Buffer.BlockCopy(payload, payload.Length - 64, signature, 0, 64);

            // decode payload JSON
            var message = new byte[payload.Length - 64];

            Buffer.BlockCopy(payload, 0, message, 0, payload.Length - 64);
            token.SetPayload(Encoding.UTF8.GetString(message));

            // pack
            var signedMessage = PreAuthEncode(new[]
            {
                Encoding.UTF8.GetBytes(PublicHeader),
                message,
                Base64UrlEncoder.DecodeBytes(token.EncodedFooter ?? string.Empty)
            });

            // verify signature using valid keys
            foreach (var publicKey in keys)
            {
                var signer = new Ed25519Signer();
                signer.Init(false, publicKey.KeyParameters);
                signer.BlockUpdate(signedMessage, 0, signedMessage.Length);

                var isValidSignature = signer.VerifySignature(signature);
                if (isValidSignature)
                {
                    return(new PasetoSecurityToken(token));
                }
            }

            throw new SecurityTokenInvalidSignatureException("Invalid PASETO signature");
        }
 public override PasetoSecurityToken Decrypt(PasetoToken token, IEnumerable <SecurityKey> decryptionKeys)
 {
     throw new NotSupportedException("v2.public not supported");
 }
        public override TokenValidationResult ValidateToken(string token, TokenValidationParameters validationParameters)
        {
            if (string.IsNullOrWhiteSpace(token))
            {
                return new TokenValidationResult {
                           Exception = new ArgumentNullException(nameof(token))
                }
            }
            ;
            if (validationParameters == null)
            {
                return new TokenValidationResult {
                           Exception = new ArgumentNullException(nameof(validationParameters))
                }
            }
            ;
            if (!CanReadToken(token))
            {
                return new TokenValidationResult {
                           Exception = new SecurityTokenException("Unable to read token")
                }
            }
            ;

            var pasetoToken = new PasetoToken(token);

            // get strategy for version + purpose
            if (!SupportedVersions.TryGetValue(pasetoToken.Version, out var strategy))
            {
                return(new TokenValidationResult {
                    Exception = new SecurityTokenException("Unsupported PASETO version")
                });
            }

            PasetoSecurityToken pasetoSecurityToken;

            try
            {
                if (pasetoToken.Purpose == "local")
                {
                    var keys = GetDecryptionKeys(token, validationParameters);
                    pasetoSecurityToken = strategy.Decrypt(pasetoToken, keys);
                }
                else if (pasetoToken.Purpose == "public")
                {
                    var keys = GetSigningKeys(token, validationParameters);

                    // TODO: kid handling (footer?)

                    pasetoSecurityToken = strategy.Verify(pasetoToken, keys);
                }
                else
                {
                    return(new TokenValidationResult {
                        Exception = new SecurityTokenException("Unsupported PASETO purpose")
                    });
                }
            }
            catch (Exception e)
            {
                return(new TokenValidationResult {
                    Exception = e
                });
            }

            var innerValidationResult = ValidateTokenPayload(pasetoSecurityToken, validationParameters);

            if (!innerValidationResult.IsValid)
            {
                return(innerValidationResult);
            }

            var identity = innerValidationResult.ClaimsIdentity;

            if (validationParameters.SaveSigninToken)
            {
                identity.BootstrapContext = token;
            }

            return(new TokenValidationResult
            {
                SecurityToken = pasetoSecurityToken,
                ClaimsIdentity = identity,
                IsValid = true
            });
        }
    }
}
 /// <summary>
 /// Verifies the a public token's signature
 /// </summary>
 public abstract PasetoSecurityToken Verify(PasetoToken token, IEnumerable <SecurityKey> signingKeys);
 /// <summary>
 /// Decrypts a local token
 /// </summary>
 public abstract PasetoSecurityToken Decrypt(PasetoToken token, IEnumerable <SecurityKey> decryptionKeys);
Exemple #6
0
        public override PasetoSecurityToken Verify(PasetoToken token, IEnumerable <SecurityKey> signingKeys)
        {
            if (token == null)
            {
                throw new ArgumentNullException(nameof(token));
            }
            if (signingKeys == null || !signingKeys.Any())
            {
                throw new ArgumentNullException(nameof(signingKeys));
            }

            var keys = signingKeys.OfType <RsaSecurityKey>().ToList();

            if (!keys.Any())
            {
                throw new SecurityTokenInvalidSigningKeyException($"PASETO v1 requires key of type {typeof(RsaSecurityKey)}");
            }

            if (token.Version != PasetoConstants.Versions.V1)
            {
                throw new ArgumentException("Invalid PASETO version");
            }
            if (token.Purpose != PasetoConstants.Purposes.Public)
            {
                throw new ArgumentException("Invalid PASETO purpose");
            }

            // decode payload
            var payload = Base64UrlEncoder.DecodeBytes(token.EncodedPayload);

            if (payload.Length < 256)
            {
                throw new SecurityTokenInvalidSignatureException("Payload does not contain signature");
            }

            // extract signature from payload (rightmost 64 bytes)
            var signature = new byte[256];

            Buffer.BlockCopy(payload, payload.Length - 256, signature, 0, 256);

            // decode payload JSON
            var message = new byte[payload.Length - 256];

            Buffer.BlockCopy(payload, 0, message, 0, payload.Length - 256);
            token.SetPayload(Encoding.UTF8.GetString(message));

            // pack
            var signedMessage = PreAuthEncode(new[]
            {
                Encoding.UTF8.GetBytes(PublicHeader),
                message,
                Base64UrlEncoder.DecodeBytes(token.EncodedFooter ?? string.Empty)
            });

            // verify signature using valid keys
            foreach (var publicKey in keys)
            {
                try
                {
                    var isValidSignature = publicKey.Rsa.VerifyData(signedMessage, signature, HashAlgorithmName.SHA384, RSASignaturePadding.Pss);
                    if (isValidSignature)
                    {
                        return(new PasetoSecurityToken(token));
                    }
                }
                catch (Exception)
                {
                    // ignored
                }
            }

            throw new SecurityTokenInvalidSignatureException("Invalid PASETO signature");
        }