Example #1
0
    def sign(cls, payload, key, alg, include_jwk=True,
             protect=frozenset(), **kwargs):
        """Sign.

        :param key: Key for signature.
        :type key: :class:`acme.jose.jwk.JWK`

        """
        assert isinstance(key, alg.kty)

        header_params = kwargs
        header_params['alg'] = alg
        if include_jwk:
            header_params['jwk'] = key.public_key()

        assert set(header_params).issubset(cls.header_cls._fields)
        assert protect.issubset(cls.header_cls._fields)

        protected_params = {}
        for header in protect:
            protected_params[header] = header_params.pop(header)
        if protected_params:
            # pylint: disable=star-args
            protected = cls.header_cls(**protected_params).json_dumps()
        else:
            protected = ''

        header = cls.header_cls(**header_params)  # pylint: disable=star-args
        signature = alg.sign(key.key, b64.b64encode(protected)
                             + '.' + b64.b64encode(payload))

        return cls(protected=protected, header=header, signature=signature)
Example #2
0
    def to_compact(self):
        """Compact serialization."""
        assert len(self.signatures) == 1

        assert 'alg' not in self.signature.header.not_omitted()
        # ... it must be in protected

        return '{0}.{1}.{2}'.format(b64.b64encode(self.signature.protected),
                                    b64.b64encode(self.payload),
                                    b64.b64encode(self.signature.signature))
Example #3
0
    def to_compact(self):
        """Compact serialization."""
        assert len(self.signatures) == 1

        assert 'alg' not in self.signature.header.not_omitted()
        # ... it must be in protected

        return '{0}.{1}.{2}'.format(
            b64.b64encode(self.signature.protected),
            b64.b64encode(self.payload),
            b64.b64encode(self.signature.signature))
Example #4
0
    def verify(self, payload, key=None):
        """Verify.

        :param key: Key used for verification.
        :type key: :class:`acme.jose.jwk.JWK`

        """
        key = self.combined.find_key() if key is None else key
        return self.combined.alg.verify(
            key=key.key, sig=self.signature,
            msg=(b64.b64encode(self.protected) + '.' +
                 b64.b64encode(payload)))
Example #5
0
    def verify(self, payload, key=None):
        """Verify.

        :param key: Key used for verification.
        :type key: :class:`acme.jose.jwk.JWK`

        """
        key = self.combined.find_key() if key is None else key
        return self.combined.alg.verify(key=key.key,
                                        sig=self.signature,
                                        msg=(b64.b64encode(self.protected) +
                                             '.' + b64.b64encode(payload)))
    def test_json_flat(self):
        jobj_to = {
            'signature': b64.b64encode(self.mixed.signature.signature),
            'payload': b64.b64encode('foo'),
            'header': self.mixed.signature.header,
            'protected': b64.b64encode(self.mixed.signature.protected),
        }
        jobj_from = jobj_to.copy()
        jobj_from['header'] = jobj_from['header'].to_json()

        self.assertEqual(self.mixed.to_partial_json(flat=True), jobj_to)
        from acme.jose.jws import JWS
        self.assertEqual(self.mixed, JWS.from_json(jobj_from))
Example #7
0
    def test_json_flat(self):
        jobj_to = {
            'signature': b64.b64encode(self.mixed.signature.signature),
            'payload': b64.b64encode('foo'),
            'header': self.mixed.signature.header,
            'protected': b64.b64encode(self.mixed.signature.protected),
        }
        jobj_from = jobj_to.copy()
        jobj_from['header'] = jobj_from['header'].to_json()

        self.assertEqual(self.mixed.to_partial_json(flat=True), jobj_to)
        from acme.jose.jws import JWS
        self.assertEqual(self.mixed, JWS.from_json(jobj_from))
Example #8
0
    def to_compact(self):
        """Compact serialization.

        :rtype: bytes

        """
        assert len(self.signatures) == 1

        assert 'alg' not in self.signature.header.not_omitted()
        # ... it must be in protected

        return (b64.b64encode(self.signature.protected.encode('utf-8')) +
                b'.' + b64.b64encode(self.payload) + b'.' +
                b64.b64encode(self.signature.signature))
Example #9
0
    def to_compact(self):
        """Compact serialization.

        :rtype: bytes

        """
        assert len(self.signatures) == 1

        assert 'alg' not in self.signature.header.not_omitted()
        # ... it must be in protected

        return (
            b64.b64encode(self.signature.protected.encode('utf-8')) +
            b'.' +
            b64.b64encode(self.payload) +
            b'.' +
            b64.b64encode(self.signature.signature))
Example #10
0
def encode_cert(cert):
    """Encode certificate as JOSE Base-64 DER.

    :param cert: Certificate.
    :type cert: :class:`acme.jose.util.ComparableX509`

    """
    return b64.b64encode(cert.as_der())
Example #11
0
    def _encode_param(cls, data):
        def _leading_zeros(arg):
            if len(arg) % 2:
                return '0' + arg
            return arg

        return b64.b64encode(binascii.unhexlify(
            _leading_zeros(hex(data)[2:].rstrip('L'))))
Example #12
0
def encode_cert(cert):
    """Encode certificate as JOSE Base-64 DER.

    :param cert: Certificate.
    :type cert: :class:`acme.jose.util.ComparableX509`

    """
    return b64.b64encode(cert.as_der())
Example #13
0
    def _encode_param(cls, data):
        def _leading_zeros(arg):
            if len(arg) % 2:
                return '0' + arg
            return arg

        return b64.b64encode(binascii.unhexlify(
            _leading_zeros(hex(data)[2:].rstrip('L'))))
Example #14
0
    def _perform_tlssni01_challenge(self, achall):
        tls_help = self._get_tls_sni_help(achall)
        response = tls_help._setup_challenge_cert(achall)

        json_data = OrderedDict()
        json_data[FIELD_CMD] = COMMAND_PERFORM
        json_data[FIELD_TYPE] = achall.chall.typ
        json_data[FIELD_DOMAIN] = achall.domain
        json_data[FIELD_TOKEN] = b64.b64encode(achall.chall.token)
        json_data[FIELD_Z_DOMAIN] = achall.response(
            achall.account_key).z_domain
        json_data[FIELD_VALIDATION] = json_data[FIELD_Z_DOMAIN]
        json_data[FIELD_CERT_PATH] = tls_help.get_cert_path(achall)
        json_data[FIELD_KEY_PATH] = tls_help.get_key_path(achall)
        json_data[FIELD_PORT] = str(self.config.tls_sni_01_port)
        json_data[FIELD_KEY_AUTH] = response.key_authorization
        json_data[FIELD_CERT_PEM] = None
        json_data[FIELD_KEY_PEM] = None
        try:
            with open(json_data[FIELD_CERT_PATH], 'r') as fh:
                json_data[FIELD_CERT_PEM] = fh.read()
        except:
            pass
        try:
            with open(json_data[FIELD_KEY_PATH], 'r') as fh:
                json_data[FIELD_KEY_PEM] = fh.read()
        except:
            pass

        if self._is_text_mode():
            self._notify_and_wait(
                self._get_message(achall).format(
                    domain=json_data[FIELD_DOMAIN],
                    z_domain=json_data[FIELD_Z_DOMAIN],
                    cert_path=json_data[FIELD_CERT_PATH],
                    key_path=json_data[FIELD_KEY_PATH],
                    port=json_data[FIELD_PORT]))

        elif self._is_json_mode():
            self._json_out_and_wait(json_data)

        elif self._is_handler_mode():
            self._json_out(json_data, True)
            if self._call_handler(
                    "perform",
                    **(self._get_json_to_kwargs(json_data))) is None:
                raise errors.PluginError(
                    "Error in calling the handler to do the perform (challenge) stage"
                )

        else:
            raise errors.PluginError("Unknown plugin mode selected")

        if not response.simple_verify(achall.chall, achall.domain,
                                      achall.account_key.public_key(), None):
            logger.warning("Self-verify of challenge failed.")

        return response
Example #15
0
def encode_cert(cert):
    """Encode certificate as JOSE Base-64 DER.

    :param cert: Certificate.
    :type cert: :class:`acme.jose.util.ComparableX509`

    """
    return b64.b64encode(OpenSSL.crypto.dump_certificate(
        OpenSSL.crypto.FILETYPE_ASN1, cert))
Example #16
0
def encode_b64jose(data):
    """Encode JOSE Base-64 field.

    :param bytes data:
    :rtype: `unicode`

    """
    # b64encode produces ASCII characters only
    return b64.b64encode(data).decode('ascii')
Example #17
0
    def test_json_not_flat(self):
        jobj_to = {
            'signatures': (self.mixed.signature, ),
            'payload': b64.b64encode('foo'),
        }
        jobj_from = jobj_to.copy()
        jobj_from['signatures'] = [jobj_to['signatures'][0].to_json()]

        self.assertEqual(self.mixed.to_partial_json(flat=False), jobj_to)
        from acme.jose.jws import JWS
        self.assertEqual(self.mixed, JWS.from_json(jobj_from))
    def test_json_not_flat(self):
        jobj_to = {
            'signatures': (self.mixed.signature,),
            'payload': b64.b64encode('foo'),
        }
        jobj_from = jobj_to.copy()
        jobj_from['signatures'] = [jobj_to['signatures'][0].to_json()]

        self.assertEqual(self.mixed.to_partial_json(flat=False), jobj_to)
        from acme.jose.jws import JWS
        self.assertEqual(self.mixed, JWS.from_json(jobj_from))
Example #19
0
    def to_partial_json(self, flat=True):  # pylint: disable=arguments-differ
        assert self.signatures
        payload = b64.b64encode(self.payload)

        if flat and len(self.signatures) == 1:
            ret = self.signatures[0].to_partial_json()
            ret['payload'] = payload
            return ret
        else:
            return {
                'payload': payload,
                'signatures': self.signatures,
            }
Example #20
0
    def to_partial_json(self, flat=True):  # pylint: disable=arguments-differ
        assert self.signatures
        payload = b64.b64encode(self.payload)

        if flat and len(self.signatures) == 1:
            ret = self.signatures[0].to_partial_json()
            ret['payload'] = payload
            return ret
        else:
            return {
                'payload': payload,
                'signatures': self.signatures,
            }
Example #21
0
    def sign(cls,
             payload,
             key,
             alg,
             include_jwk=True,
             protect=frozenset(),
             **kwargs):
        """Sign.

        :param key: Key for signature.
        :type key: :class:`acme.jose.jwk.JWK`

        """
        assert isinstance(key, alg.kty)

        header_params = kwargs
        header_params['alg'] = alg
        if include_jwk:
            header_params['jwk'] = key.public()

        assert set(header_params).issubset(cls.header_cls._fields)
        assert protect.issubset(cls.header_cls._fields)

        protected_params = {}
        for header in protect:
            protected_params[header] = header_params.pop(header)
        if protected_params:
            # pylint: disable=star-args
            protected = cls.header_cls(**protected_params).json_dumps()
        else:
            protected = ''

        header = cls.header_cls(**header_params)  # pylint: disable=star-args
        signature = alg.sign(
            key.key,
            b64.b64encode(protected) + '.' + b64.b64encode(payload))

        return cls(protected=protected, header=header, signature=signature)
Example #22
0
    def _perform_dns01_challenge(self, achall):
        response, validation = achall.response_and_validation()

        json_data = OrderedDict()
        json_data[FIELD_CMD] = COMMAND_PERFORM
        json_data[FIELD_TYPE] = achall.chall.typ
        json_data[FIELD_DOMAIN] = achall.domain
        json_data[FIELD_TOKEN] = b64.b64encode(achall.chall.token)
        json_data[FIELD_VALIDATION] = validation
        json_data[FIELD_TXT_DOMAIN] = achall.validation_domain_name(
            achall.domain)
        json_data[FIELD_KEY_AUTH] = response.key_authorization

        json_data = self._json_sanitize_dict(json_data)

        if not self.conf("test-mode"):
            if self._is_text_mode():
                self._notify_and_wait(
                    self._get_message(achall).format(
                        validation=json_data[FIELD_VALIDATION],
                        domain=json_data[FIELD_DOMAIN],
                        response=response))

            elif self._is_json_mode():
                self._json_out_and_wait(json_data)

            elif self._is_handler_mode():
                self._json_out(json_data, True)
                if self._call_handler(
                        "perform",
                        **(self._get_json_to_kwargs(json_data))) is None:
                    raise errors.PluginError(
                        "Error in calling the handler to do the perform (challenge) stage"
                    )

            else:
                raise errors.PluginError("Unknown plugin mode selected")

        try:
            verification_status = response.simple_verify(
                achall.chall, achall.domain, achall.account_key.public_key())
        except acme_errors.DependencyError:
            logger.warning("Self verification requires optional "
                           "dependency `dnspython` to be installed.")
        else:
            if not verification_status:
                logger.warning("Self-verify of challenge failed.")

        return response
Example #23
0
    def _get_cleanup_json(self, achall):
        response, validation = achall.response_and_validation()

        cur_record = OrderedDict()
        cur_record[FIELD_CMD] = COMMAND_CLEANUP
        cur_record[FIELD_TYPE] = achall.chall.typ

        if isinstance(achall.chall, challenges.HTTP01):
            pass
        elif isinstance(achall.chall, challenges.DNS01):
            pass

        cur_record[FIELD_STATUS] = None
        cur_record[FIELD_DOMAIN] = achall.domain
        cur_record[FIELD_TOKEN] = b64.b64encode(achall.chall.token)
        if type(cur_record[FIELD_TOKEN]) == bytes:
            cur_record[FIELD_TOKEN] = cur_record[FIELD_TOKEN].decode('UTF-8')
        cur_record[FIELD_VALIDATION] = validation if isinstance(
            validation, basestring) else ''
        cur_record[FIELD_KEY_AUTH] = response.key_authorization.decode(
            'UTF-8') if isinstance(response.key_authorization,
                                   bytes) else response.key_authorization
        cur_record[FIELD_VALIDATED] = None
        cur_record[FIELD_ERROR] = None

        if achall.status is not None:
            try:
                cur_record[FIELD_STATUS] = achall.status.name
            except:
                pass

        if achall.error is not None:
            try:
                cur_record[FIELD_ERROR] = str(achall.error)
            except:
                cur_record[FIELD_ERROR] = 'ERROR'

        if achall.validated is not None:
            try:
                cur_record[FIELD_VALIDATED] = str(achall.validated)
            except:
                cur_record[FIELD_VALIDATED] = 'ERROR'

        return cur_record
Example #24
0
 def _call(cls, data):
     from acme.jose.b64 import b64encode
     return b64encode(data)
Example #25
0
 def _msg(cls, protected, payload):
     return (b64.b64encode(protected.encode('utf-8')) + b'.' +
             b64.b64encode(payload))
Example #26
0
 def _call(cls, data):
     from acme.jose.b64 import b64encode
     return b64encode(data)
Example #27
0
def encode_csr(csr):
    """Encode CSR as JOSE Base-64 DER."""
    return b64.b64encode(OpenSSL.crypto.dump_certificate_request(
        OpenSSL.crypto.FILETYPE_ASN1, csr))
Example #28
0
    def _perform_http01_challenge(self, achall):
        # same path for each challenge response would be easier for
        # users, but will not work if multiple domains point at the
        # same server: default command doesn't support virtual hosts
        response, validation = achall.response_and_validation()
        port = (response.port if self.config.http01_port is None else int(
            self.config.http01_port))

        command = self.CMD_TEMPLATE.format(
            root=self._root,
            achall=achall,
            response=response,
            validation=pipes.quote(validation),
            encoded_token=achall.chall.encode("token"),
            port=port)

        json_data = OrderedDict()
        json_data[FIELD_CMD] = COMMAND_PERFORM
        json_data[FIELD_TYPE] = achall.chall.typ
        json_data[FIELD_DOMAIN] = achall.domain
        json_data[FIELD_TOKEN] = b64.b64encode(achall.chall.token)
        json_data[FIELD_VALIDATION] = validation
        json_data[FIELD_URI] = achall.chall.uri(achall.domain)
        json_data['command'] = command
        json_data[FIELD_KEY_AUTH] = response.key_authorization

        json_data = self._json_sanitize_dict(json_data)

        if self.conf("test-mode"):
            logger.debug("Test mode. Executing the manual command: %s",
                         command)
            # sh shipped with OS X does't support echo -n, but supports printf
            try:
                self._httpd = subprocess.Popen(
                    command,
                    # don't care about setting stdout and stderr,
                    # we're in test mode anyway
                    shell=True,
                    executable=None,
                    # "preexec_fn" is UNIX specific, but so is "command"
                    preexec_fn=os.setsid)
            except OSError as error:  # ValueError should not happen!
                logger.debug("Couldn't execute manual command: %s",
                             error,
                             exc_info=True)
                return False
            logger.debug("Manual command running as PID %s.", self._httpd.pid)
            # give it some time to bootstrap, before we try to verify
            # (cert generation in case of simpleHttpS might take time)
            self._test_mode_busy_wait(port)

            if self._httpd.poll() is not None:
                raise errors.Error("Couldn't execute manual command")
        else:
            if self._is_text_mode():
                self._notify_and_wait(
                    self._get_message(achall).format(validation=validation,
                                                     response=response,
                                                     uri=achall.chall.uri(
                                                         achall.domain),
                                                     command=command))

            elif self._is_json_mode():
                self._json_out_and_wait(json_data)

            elif self._is_handler_mode():
                self._json_out(json_data, True)
                if self._call_handler(
                        "perform",
                        **(self._get_json_to_kwargs(json_data))) is None:
                    raise errors.PluginError(
                        "Error in calling the handler to do the perform (challenge) stage"
                    )

            else:
                raise errors.PluginError("Unknown plugin mode selected")

        if not response.simple_verify(achall.chall, achall.domain,
                                      achall.account_key.public_key(),
                                      self.config.http01_port):
            logger.warning("Self-verify of challenge failed.")

        return response
Example #29
0
 def _msg(cls, protected, payload):
     return (b64.b64encode(protected.encode('utf-8')) + b'.' +
             b64.b64encode(payload))