class Challenge(Message): """ACME "challenge" message. :ivar str nonce: Random data, **not** base64-encoded. :ivar list challenges: List of :class:`~acme.challenges.Challenge` objects. .. todo:: 1. can challenges contain two challenges of the same type? 2. can challenges contain duplicates? 3. check "combinations" indices are in valid range 4. turn "combinations" elements into sets? 5. turn "combinations" into set? """ typ = "challenge" schema = util.load_schema(typ) session_id = jose.Field("sessionID") nonce = jose.Field("nonce", encoder=jose.b64encode, decoder=jose.decode_b64jose) challenges = jose.Field("challenges") combinations = jose.Field("combinations", omitempty=True, default=()) @challenges.decoder def challenges(value): # pylint: disable=missing-docstring,no-self-argument return tuple(challenges.Challenge.from_json(chall) for chall in value) @property def resolved_combinations(self): """Combinations with challenges instead of indices.""" return tuple( tuple(self.challenges[idx] for idx in combo) for combo in self.combinations)
class Certificate(Message): """ACME "certificate" message. :ivar certificate: The certificate (:class:`M2Crypto.X509.X509` wrapped in :class:`acme.util.ComparableX509`). :ivar list chain: Chain of certificates (:class:`M2Crypto.X509.X509` wrapped in :class:`acme.util.ComparableX509` ). """ typ = "certificate" schema = util.load_schema(typ) certificate = jose.Field("certificate", encoder=jose.encode_cert, decoder=jose.decode_cert) chain = jose.Field("chain", omitempty=True, default=()) refresh = jose.Field("refresh", omitempty=True) @chain.decoder def chain(value): # pylint: disable=missing-docstring,no-self-argument return tuple(jose.decode_cert(cert) for cert in value) @chain.encoder def chain(value): # pylint: disable=missing-docstring,no-self-argument return tuple(jose.encode_cert(cert) for cert in value)
class Defer(Message): """ACME "defer" message.""" typ = "defer" schema = util.load_schema(typ) token = jose.Field("token") interval = jose.Field("interval", omitempty=True) message = jose.Field("message", omitempty=True)
class Authorization(Message): """ACME "authorization" message. :ivar jwk: :class:`acme.jose.JWK` """ typ = "authorization" schema = util.load_schema(typ) recovery_token = jose.Field("recoveryToken", omitempty=True) identifier = jose.Field("identifier", omitempty=True) jwk = jose.Field("jwk", decoder=jose.JWK.from_json, omitempty=True)
class RevocationRequest(Message): """ACME "revocationRequest" message. :ivar certificate: Certificate (:class:`M2Crypto.X509.X509` wrapped in :class:`acme.util.ComparableX509`). :ivar signature: Signature (:class:`acme.other.Signature`). """ typ = "revocationRequest" schema = util.load_schema(typ) certificate = jose.Field("certificate", decoder=jose.decode_cert, encoder=jose.encode_cert) signature = jose.Field("signature", decoder=other.Signature.from_json) @classmethod def create(cls, key, sig_nonce=None, **kwargs): """Create signed "revocationRequest". :param key: Key used for signing. :type key: :class:`Crypto.PublicKey.RSA` :param str sig_nonce: Nonce used for signature. Useful for testing. :kwargs: Any other arguments accepted by the class constructor. :returns: Signed "revocationRequest" ACME message. :rtype: :class:`RevocationRequest` """ return cls(signature=other.Signature.from_msg( kwargs["certificate"].as_der(), key, sig_nonce), **kwargs) def verify(self): """Verify signature. .. warning:: Caller must check that the public key encoded in the :attr:`signature`'s :class:`acme.jose.JWK` object is the correct key for a given context. :returns: True iff ``signature`` can be verified, False otherwise. :rtype: bool """ # self.signature is not Field | pylint: disable=no-member return self.signature.verify(self.certificate.as_der())
class Error(Message): """ACME "error" message.""" typ = "error" schema = util.load_schema(typ) error = jose.Field("error") message = jose.Field("message", omitempty=True) more_info = jose.Field("moreInfo", omitempty=True) MESSAGE_CODES = { "malformed": "The request message was malformed", "unauthorized": "The client lacks sufficient authorization", "serverInternal": "The server experienced an internal error", "notSupported": "The request type is not supported", "unknown": "The server does not recognize an ID/token in the request", "badCSR": "The CSR is unacceptable (e.g., due to a short key)", }
class StatusRequest(Message): """ACME "statusRequest" message.""" typ = "statusRequest" schema = util.load_schema(typ) token = jose.Field("token")
class Revocation(Message): """ACME "revocation" message.""" typ = "revocation" schema = util.load_schema(typ)
class AuthorizationRequest(Message): """ACME "authorizationRequest" message. :ivar str nonce: Random data from the corresponding :attr:`Challenge.nonce`, **not** base64-encoded. :ivar list responses: List of completed challenges ( :class:`acme.challenges.ChallengeResponse`). :ivar signature: Signature (:class:`acme.other.Signature`). """ typ = "authorizationRequest" schema = util.load_schema(typ) session_id = jose.Field("sessionID") nonce = jose.Field("nonce", encoder=jose.b64encode, decoder=jose.decode_b64jose) responses = jose.Field("responses") signature = jose.Field("signature", decoder=other.Signature.from_json) contact = jose.Field("contact", omitempty=True, default=()) @responses.decoder def responses(value): # pylint: disable=missing-docstring,no-self-argument return tuple( challenges.ChallengeResponse.from_json(chall) for chall in value) @classmethod def create(cls, name, key, sig_nonce=None, **kwargs): """Create signed "authorizationRequest". :param str name: Hostname :param key: Key used for signing. :type key: :class:`Crypto.PublicKey.RSA` :param str sig_nonce: Nonce used for signature. Useful for testing. :kwargs: Any other arguments accepted by the class constructor. :returns: Signed "authorizationRequest" ACME message. :rtype: :class:`AuthorizationRequest` """ # pylint: disable=too-many-arguments signature = other.Signature.from_msg(name + kwargs["nonce"], key, sig_nonce) return cls(signature=signature, contact=kwargs.pop("contact", ()), **kwargs) def verify(self, name): """Verify signature. .. warning:: Caller must check that the public key encoded in the :attr:`signature`'s :class:`acme.jose.JWK` object is the correct key for a given context. :param str name: Hostname :returns: True iff ``signature`` can be verified, False otherwise. :rtype: bool """ # self.signature is not Field | pylint: disable=no-member return self.signature.verify(name + self.nonce)
class ChallengeRequest(Message): """ACME "challengeRequest" message.""" typ = "challengeRequest" schema = util.load_schema(typ) identifier = jose.Field("identifier")