Ejemplo n.º 1
0
def postdeserialize_keyinfo(psz_keyinfo):
    """Undo the preprocessing done by preserialize_keyinfo."""
    keyinfo = {}
    for name, sz_data in psz_keyinfo.items():
        if isinstance(sz_data, str):
            sz_bytes = str.encode(sz_data)
            try:
                keydata = base64.decodebytes(sz_bytes)
            except:
                raise EDBError("serialized keydata not b64")
        elif isinstance(sz_data, (bytes, bytearray)):
            try:
                keydata = base64.decodebytes(sz_data)
            except:
                raise EDBError("serialized keydata not b64")
        elif isinstance(sz_data, dict) and 'paillier' in sz_data:
            sz_tuple = sz_data['paillier']
            if not (isinstance(sz_tuple, collections.abc.Iterable)
                    and len(sz_tuple) == 4):
                raise EDBError("invalid paillier keydata")
            keydata = paillier.Key._make(sz_tuple)
        elif isinstance(sz_data, dict) and 'paillier.pub' in sz_data:
            sz_tuple = sz_data['paillier.pub']
            if not (isinstance(sz_tuple, collections.abc.Iterable)
                    and len(sz_tuple) == 2):
                raise EDBError("invalid paillier keydata")
            keydata = paillier.PublicKey._make(sz_tuple)
        else:
            raise EDBError("invalid keydata")
        keyinfo[name] = keydata
    return keyinfo
Ejemplo n.º 2
0
 def request(self, method, *args, **kwargs):
     try:
         resp = requests.request(method, *args, **kwargs)
     except RequestException as err:
         raise EDBError('could not connect to server: ' + str(err))
     try:
         resp = resp.json()
     except:
         raise EDBError('received invalid response from server')
     if 'detail' in resp:
         raise EDBError(detail)
     return resp
Ejemplo n.º 3
0
 def decrypt(self, b64ctxt):
     """Decrypt ciphertext from a given index."""
     if isinstance(b64ctxt, str):
         b64ctxt = str.encode(b64ctxt)
     elif not isinstance(b64ctxt, (bytes, bytearray)):
         raise EDBError("can only decrypt str or bytes")
     try:
         salted_ctxt = base64.decodebytes(b64ctxt)
     except:
         raise EDBError("invalid base64")
     if len(salted_ctxt) != 2 * BLOCK_BYTES:
         raise EDBError("invalid ciphertext -- incorrect length")
     salt, ciphertext = salted_ctxt[:BLOCK_BYTES], salted_ctxt[BLOCK_BYTES:]
     preword = self.stream_decrypt(salt, ciphertext)
     return self.postprocess(preword)
Ejemplo n.º 4
0
 def count(self, **query):
     params = self.encrypt_query(query)
     resp = requests.get(self.count_url, params=params).json()
     try:
         return int(resp['count'])
     except (ValueError, KeyError):
         raise EDBError('received invalid response from server')
Ejemplo n.º 5
0
 def paillier_decrypt(self, ctxt):
     """Decrypt a number using homomorphic methods."""
     try:
         ctxt = int(ctxt)
     except ValueError:
         raise EDBError("can only homomorphic decrypt integers")
     return paillier.decrypt(self.keys['paillier'], ctxt)
Ejemplo n.º 6
0
 def paillier_encrypt(self, ptxt):
     """Encrypt a number using homomorphic methods."""
     try:
         ptxt = int(ptxt)
     except ValueError:
         raise EDBError("can only homomorphic encrypt integers")
     return str(paillier.encrypt(self.keys['paillier'], ptxt))
Ejemplo n.º 7
0
def generate_keyinfo(keyschema):
    """Return a dict of secure randomly-generated keys.

    The provided parameter `keyschema` should be a dict mapping key names to
    descriptions. For example:

        {
            'encrypt': {'type': 'block', 'bits': 256},
            'hmac': {'type': 'block', 'bits': 256},
            'homomorphic': {'type': 'paillier', 'bits': 512}
        }

    Supported types include "block" (random string of bit size) and "paillier"
    (key for the paillier cryptosystem). The default type is "block" if
    unspecified. The default number of bits is 256.

    Example return value:

        {
            'encrypt': b'\xb5c\x1d...',
            'hmac': b'\x7f\xa7\xcd...',
            'homomorphic': paillier.Key(modulus=..., ...)
        }

    """
    keyinfo = {}
    for name, attrs in keyschema.items():
        bad_attrs = set(attrs.keys()) - set(['type', 'bits'])
        if bad_attrs:
            raise EDBError("invalid schema: unexpected attrs: "
                           "{}".format(bad_attrs))
        keytype = attrs.get('type', 'block')
        try:
            keybits = int(attrs.get('bits', 256))
        except ValueError:
            raise EDBError("invalid schema: {}/bits is not int".format(name))
        if keytype == 'block':
            key = get_random_bytes(keybits // 8)
        elif keytype == 'paillier':
            key = paillier.generate_keys(keybits)
        else:
            raise EDBError("invalid schema: bad type: ".format(keytype))
        keyinfo[name] = key
    return keyinfo
Ejemplo n.º 8
0
 def average(self, **query):
     params = self.encrypt_query(query)
     key = self.keys['paillier']
     params.update(modulus=str(key.modulus), generator=str(key.generator))
     resp = self.request('get', self.average_url, params=params)
     if 'count' not in resp or 'sum' not in resp:
         raise EDBError('received invalid response from server')
     count = self.paillier_decrypt(resp['count'])
     total = self.paillier_decrypt(resp['sum'])
     return (total / count) if count != 0 else 0
Ejemplo n.º 9
0
 def correlate(self, source, destination):
     params = self.encrypt_query({
         'source': source,
         'destination': destination
     })
     resp = self.request('get', self.correlate_url, params=params)
     try:
         return float(resp['coefficient'])
     except (ValueError, KeyError):
         raise EDBError('received invalid response from server')
Ejemplo n.º 10
0
def preserialize_keyinfo(keyinfo):
    """Prepare keyinfo for JSON serialization."""
    psz_keyinfo = {}
    for name, keydata in keyinfo.items():
        if isinstance(keydata, str):
            sz_data = base64.encodebytes(str.encode(keydata)).decode()
        elif isinstance(keydata, (bytes, bytearray)):
            sz_data = base64.encodebytes(keydata).decode()
        elif isinstance(keydata, paillier.Key):
            sz_data = {'paillier': list(keydata)}
        elif isinstance(keydata, paillier.PublicKey):
            sz_data = {'paillier.pub': list(keydata)}
        else:
            raise EDBError("unexpected keydata")
        psz_keyinfo[name] = sz_data
    return psz_keyinfo