Source code for aries_cloudagent.messaging.valid

"""Validators for schema fields."""

from datetime import datetime

from base58 import alphabet
from marshmallow.validate import OneOf, Range, Regexp

from .util import epoch_to_str

B58 = alphabet if isinstance(alphabet, str) else alphabet.decode("ascii")


[docs]class IntEpoch(Range): """Validate value against (integer) epoch format.""" EXAMPLE = int(datetime.now().timestamp()) def __init__(self): """Initializer.""" super().__init__( # use 64-bit for Aries RFC compatibility min=-9223372036854775808, max=9223372036854775807, error="Value {input} is not a valid integer epoch time", )
[docs]class JWSHeaderKid(Regexp): """Validate value against JWS header kid.""" EXAMPLE = "did:sov:LjgpST2rjsoxYegQDRm7EL#keys-4" PATTERN = rf"^did:(?:key:z[{B58}]+|sov:[{B58}]{{21,22}}(;.*)?(\?.*)?#.+)$" def __init__(self): """Initializer.""" super().__init__( JWSHeaderKid.PATTERN, error="Value {input} is neither in W3C did:key nor DID URL format", )
[docs]class JSONWebToken(Regexp): """Validate JSON Web Token.""" EXAMPLE = ( "eyJhbGciOiJFZERTQSJ9." "eyJhIjogIjAifQ." "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" ) PATTERN = r"^[-_a-zA-Z0-9]*\.[-_a-zA-Z0-9]*\.[-_a-zA-Z0-9]*$" def __init__(self): """Initializer.""" super().__init__( JSONWebToken.PATTERN, error="Value {input} is not a valid JSON Web token", )
[docs]class DIDKey(Regexp): """Validate value against DID key specification.""" EXAMPLE = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" PATTERN = rf"^did:key:z[{B58}]+$" def __init__(self): """Initializer.""" super().__init__( DIDKey.PATTERN, error="Value {input} is not in W3C did:key format" )
[docs]class IndyDID(Regexp): """Validate value against indy DID.""" EXAMPLE = "WgWxqztrNooG92RXvxSTWv" PATTERN = rf"^(did:sov:)?[{B58}]{{21,22}}$" def __init__(self): """Initializer.""" super().__init__( IndyDID.PATTERN, error="Value {input} is not an indy decentralized identifier (DID)", )
[docs]class IndyRawPublicKey(Regexp): """Validate value against indy (Ed25519VerificationKey2018) raw public key.""" EXAMPLE = "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" PATTERN = rf"^[{B58}]{{43,44}}$" def __init__(self): """Initializer.""" super().__init__( IndyRawPublicKey.PATTERN, error="Value {input} is not a raw Ed25519VerificationKey2018 key", )
[docs]class IndyCredDefId(Regexp): """Validate value against indy credential definition identifier specification.""" EXAMPLE = "WgWxqztrNooG92RXvxSTWv:3:CL:20:tag" PATTERN = ( rf"^([{B58}]{{21,22}})" # issuer DID f":3" # cred def id marker f":CL" # sig alg rf":(([1-9][0-9]*)|([{B58}]{{21,22}}:2:.+:[0-9.]+))" # schema txn / id f":(.+)?$" # tag ) def __init__(self): """Initializer.""" super().__init__( IndyCredDefId.PATTERN, error="Value {input} is not an indy credential definition identifier", )
[docs]class IndyVersion(Regexp): """Validate value against indy version specification.""" EXAMPLE = "1.0" PATTERN = rf"^[0-9.]+$" def __init__(self): """Initializer.""" super().__init__( IndyVersion.PATTERN, error="Value {input} is not an indy version (use only digits and '.')", )
[docs]class IndySchemaId(Regexp): """Validate value against indy schema identifier specification.""" EXAMPLE = "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0" PATTERN = rf"^[{B58}]{{21,22}}:2:.+:[0-9.]+$" def __init__(self): """Initializer.""" super().__init__( IndySchemaId.PATTERN, error="Value {input} is not an indy schema identifier", )
[docs]class IndyRevRegId(Regexp): """Validate value against indy revocation registry identifier specification.""" EXAMPLE = f"WgWxqztrNooG92RXvxSTWv:4:WgWxqztrNooG92RXvxSTWv:3:CL:20:tag:CL_ACCUM:0" PATTERN = ( rf"^([{B58}]{{21,22}}):4:" rf"([{B58}]{{21,22}}):3:" rf"CL:(([1-9][0-9]*)|([{B58}]{{21,22}}:2:.+:[0-9.]+))(:.+)?:" rf"CL_ACCUM:(.+$)" ) def __init__(self): """Initializer.""" super().__init__( IndyRevRegId.PATTERN, error="Value {input} is not an indy revocation registry identifier", )
[docs]class IndyPredicate(OneOf): """Validate value against indy predicate.""" EXAMPLE = ">=" def __init__(self): """Initializer.""" super().__init__( choices=["<", "<=", ">=", ">"], error="Value {input} must be one of {choices}", )
[docs]class IndyISO8601DateTime(Regexp): """Validate value against ISO 8601 datetime format, indy profile.""" EXAMPLE = epoch_to_str(int(datetime.now().timestamp())) PATTERN = ( r"^\d{4}-\d\d-\d\d[T ]\d\d:\d\d" r"(?:\:(?:\d\d(?:\.\d{1,6})?))?(?:[+-]\d\d:?\d\d|Z|)$" ) def __init__(self): """Initializer.""" super().__init__( IndyISO8601DateTime.PATTERN, error="Value {input} is not a date in valid format", )
[docs]class Base64(Regexp): """Validate base64 value.""" EXAMPLE = "ey4uLn0=" PATTERN = r"^[a-zA-Z0-9+/]*={0,2}$" def __init__(self): """Initializer.""" super().__init__( Base64.PATTERN, error="Value {input} is not a valid base64 encoding", )
[docs]class Base64URL(Regexp): """Validate base64 value.""" EXAMPLE = "ey4uLn0=" PATTERN = r"^[-_a-zA-Z0-9]*={0,2}$" def __init__(self): """Initializer.""" super().__init__( Base64URL.PATTERN, error="Value {input} is not a valid base64url encoding", )
[docs]class Base64URLNoPad(Regexp): """Validate base64 value.""" EXAMPLE = "ey4uLn0" PATTERN = r"^[-_a-zA-Z0-9]*$" def __init__(self): """Initializer.""" super().__init__( Base64URLNoPad.PATTERN, error="Value {input} is not a valid unpadded base64url encoding", )
[docs]class SHA256Hash(Regexp): """Validate (binhex-encoded) SHA256 value.""" EXAMPLE = "617a48c7c8afe0521efdc03e5bb0ad9e655893e6b4b51f0e794d70fba132aacb" PATTERN = r"^[a-fA-F0-9+/]{64}$" def __init__(self): """Initializer.""" super().__init__( SHA256Hash.PATTERN, error="Value {input} is not a valid (binhex-encoded) SHA-256 hash", )
[docs]class Base58SHA256Hash(Regexp): """Validate value against base58 encoding of SHA-256 hash.""" EXAMPLE = "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" PATTERN = rf"^[{B58}]{{43,44}}$" def __init__(self): """Initializer.""" super().__init__( Base58SHA256Hash.PATTERN, error="Value {input} is not a base58 encoding of a SHA-256 hash", )
[docs]class UUIDFour(Regexp): """Validate UUID4: 8-4-4-4-12 hex digits, the 13th of which being 4.""" EXAMPLE = "3fa85f64-5717-4562-b3fc-2c963f66afa6" PATTERN = ( r"[a-fA-F0-9]{8}-" r"[a-fA-F0-9]{4}-" r"4[a-fA-F0-9]{3}-" r"[a-fA-F0-9]{4}-" r"[a-fA-F0-9]{12}" ) def __init__(self): """Initializer.""" super().__init__( UUIDFour.PATTERN, error="Value {input} is not UUID4 (8-4-4-4-12 hex digits with digit#13=4)", )
# Instances for marshmallow schema specification INT_EPOCH = {"validate": IntEpoch(), "example": IntEpoch.EXAMPLE} JWS_HEADER_KID = {"validate": JWSHeaderKid(), "example": JWSHeaderKid.EXAMPLE} JWT = {"validate": JSONWebToken(), "example": JSONWebToken.EXAMPLE} DID_KEY = {"validate": DIDKey(), "example": DIDKey.EXAMPLE} INDY_DID = {"validate": IndyDID(), "example": IndyDID.EXAMPLE} INDY_RAW_PUBLIC_KEY = { "validate": IndyRawPublicKey(), "example": IndyRawPublicKey.EXAMPLE, } INDY_SCHEMA_ID = {"validate": IndySchemaId(), "example": IndySchemaId.EXAMPLE} INDY_CRED_DEF_ID = {"validate": IndyCredDefId(), "example": IndyCredDefId.EXAMPLE} INDY_REV_REG_ID = {"validate": IndyRevRegId(), "example": IndyRevRegId.EXAMPLE} INDY_VERSION = {"validate": IndyVersion(), "example": IndyVersion.EXAMPLE} INDY_PREDICATE = {"validate": IndyPredicate(), "example": IndyPredicate.EXAMPLE} INDY_ISO8601_DATETIME = { "validate": IndyISO8601DateTime(), "example": IndyISO8601DateTime.EXAMPLE, } BASE64 = {"validate": Base64(), "example": Base64.EXAMPLE} BASE64URL = {"validate": Base64URL(), "example": Base64URL.EXAMPLE} BASE64URL_NO_PAD = {"validate": Base64URLNoPad(), "example": Base64URLNoPad.EXAMPLE} SHA256 = {"validate": SHA256Hash(), "example": SHA256Hash.EXAMPLE} BASE58_SHA256_HASH = { "validate": Base58SHA256Hash(), "example": Base58SHA256Hash.EXAMPLE, } UUID4 = {"validate": UUIDFour(), "example": UUIDFour.EXAMPLE}