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);
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"); }