def sign(cls, payload, key, alg, include_jwk=True, protect=frozenset(), **kwargs): """Sign. :param key: Key for signature. :type key: :class:`letsencrypt.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)
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))
def verify(self, payload, key=None): """Verify. :param key: Key used for verification. :type key: :class:`letsencrypt.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 letsencrypt.acme.jose.jws import JWS self.assertEqual(self.mixed, JWS.from_json(jobj_from))
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'].fully_serialize() self.assertEqual(self.mixed.to_json(flat=True), jobj_to) from letsencrypt.acme.jose.jws import JWS self.assertEqual(self.mixed, JWS.from_json(jobj_from))
def encode_cert(cert): """Encode certificate as JOSE Base-64 DER. :param cert: Certificate. :type cert: :class:`letsencrypt.acme.jose.util.ComparableX509` """ return b64.b64encode(cert.as_der())
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'))))
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].fully_serialize()] self.assertEqual(self.mixed.to_json(flat=False), jobj_to) from letsencrypt.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 letsencrypt.acme.jose.jws import JWS self.assertEqual(self.mixed, JWS.from_json(jobj_from))
def to_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_json() ret['payload'] = payload return ret else: return { 'payload': payload, 'signatures': self.signatures, }
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, }
def _call(cls, data): from letsencrypt.acme.jose.b64 import b64encode return b64encode(data)