oprfs module
Easy-to-deploy oblivious pseudo-random function (OPRF) service that allows other parties (typically participants in some secure multi-party computation protocol) to maintain a persistent mask which they cannot decrypt but which they can safely apply (via requests to the service) to private data values of their choice.
This module includes an OPRF service request handler (that serves as an endpoint for the service and can be used in conjunction with libraries such as Flask) and client request construction class (to help clients build requests concisely).
- oprfs.oprfs.key() bcl.bcl.secret[source]
Create a
secretkey to be maintained by the service.>>> len(key()) 32 >>> isinstance(key(), bcl.secret) True
- oprfs.oprfs.key_base64() str[source]
Create a
secretkey to be maintained by the service and return its Base64 UTF-8 string representation.>>> len(base64.standard_b64decode(key_base64())) 32
- oprfs.oprfs.mask(k: bcl.bcl.secret, m: Optional[bcl.bcl.cipher] = None, d: Optional[oprf.oprf.data] = None) Union[bcl.bcl.cipher, oprf.oprf.data][source]
Function implementing a masking service. If only a
secretkey is supplied, this function creates amaskobject, encrypts it using the suppliedsecretkey, and returns the resultingcipherobject. If an encryptedmaskobject and adataobject are also supplied, it decrypts the suppliedcipherobject into amaskobject, applies it to thedataobject, and returns the result.>>> k = key() >>> m = mask(k)
The two objects
kandmcan now be used to mask data.>>> d = oprf.data.hash('abc') >>> mask(k, m, d) == oprf.mask(bcl.symmetric.decrypt(k, m))(d) True
If an encrypted
maskobject is supplied, adataobject must also be supplied.>>> mask(k, m) Traceback (most recent call last): ... ValueError: data to be masked must be supplied
- oprfs.oprfs.handler(k: bcl.bcl.secret, request: Union[str, dict]) dict[source]
Wrapper for service function that accepts inputs as a JSON string or a Python
dictinstance (e.g., for use within a route defined using the Flask library).It is possible to request a new encrypted mask. Note that an empty request must be supplied to the handler.
>>> k = key() >>> r = handler(k, {}) >>> r['status'] 'success' >>> r = handler(k, '{}') >>> r['status'] 'success'
The encrypted mask can be used to mask data. Note that it is the responsibility of the service implementation to maintain and supply the
secretkey to the handler.>>> m = oprf.mask.from_base64(r['mask'][0]) >>> d = oprf.data.hash('abc') >>> r = handler(k, {'mask': [m.to_base64()], 'data': [d.to_base64()]}) >>> r['status'] 'success'
The example below reproduces the example above, but submits the request to the handler as a string.
>>> (m_str, d_str) = (str(m.to_base64()), str(d.to_base64())) >>> s = '{"mask": ["' + m_str + '"], "data": ["' + d_str + '"]}' >>> r = handler(k, s) >>> r['status'] 'success'
The example below confirms that the response contains the masked data.
>>> oprf.data.from_base64(r['data'][0]) == ( ... oprf.mask(bcl.symmetric.decrypt(k, bcl.cipher(m)))(d) ... ) True
If the supplied request is not valid (e.g., if the data is missing), then the returned response indicates failure.
>>> r = handler(k, {'mask': [m.to_base64()]}) >>> r['status'] 'failure'