nthcommunity module
Python library for the nth.community secure, privacy-preserving data collaboration service platform and API.
An end-to-end example is presented in the documentation for the
recipient class.
- class nthcommunity.nthcommunity.collaboration
Bases:
dictBase class for tree data structure representing a data collaboration. Consult definitions of derived classes such as
intersectionandtablefor more details, and find in-context usage examples in the documentation for therecipientclass.- static from_json(argument: Union[str, dict]) nthcommunity.nthcommunity.collaboration
Parse a dictionary or JSON string into an instance of this class. Find usage examples in the documentation for the
recipientclass.
- class nthcommunity.nthcommunity.recipient
Bases:
objectA collaboration begins with a recipient party represented by a
recipientobject. The recipient defines acollaborationworkflow, generates keys for individual contributors, accepts encrypted contributions, and computes the results in concert with the nth.community service platform.>>> r = recipient()
Individual
contributorobjects represent and uniquely identify individual contributors.>>> c_a = contributor() >>> c_b = contributor()
The
contributorclass is derived fromdictand contains a value under the'identifier'key that corresponds to the unique identifier for that contributor. This value can also be retrieved using thecontributor.identifiermethod.>>> 'identifier' in c_a True >>> c_a.identifier() is not None True
A
collaborationis a tree-like data structure that defines how the overall result of the collaboration is computed. Each leaf node of the data structure must indicate which contributor must supply the encrypted data corresponding to that node. The internal, non-leaf nodes represent data operations such ascount,summation, andintersection.>>> w = count(intersection(table(contributor=c_a), table(contributor=c_b)))
The recipient can use the
recipient.generatemethod (which internally leverages the nth.community service platform) to create a dictionary that maps each contributor identifier to its respective contribution key for that specific collaboration workflow.>>> id_to_key = r.generate(w)
Each of these individual keys
id_to_key[c_a.identifier()]andid_to_key[c_b.identifier()]can be converted to JSON using thecollaboration.to_jsonmethod and delivered to their corresponding contributor.>>> key_a_json = id_to_key[c_a.identifier()].to_json() >>> key_b_json = id_to_key[c_b.identifier()].to_json()
Contributors can parse the JSON strings using
collaboration.from_json.>>> key_a = collaboration.from_json(key_a_json) >>> key_b = collaboration.from_json(key_b_json)
Each contributor can then use the
contributor.encryptmethod to encrypt their data contribution using their key. After validating the contribution key, this method does not perform any external communications and encrypts the input data entirely within the host environment belonging to the contributor. In particular, it does not communicate with the nth.community service platform or the recipient during this process.>>> table_a = [['a'], ['b'], ['c'], ['d']] >>> enc_a = c_a.encrypt(key_a, table_a) >>> table_b = [['b'], ['c'], ['d'], ['e']] >>> enc_b = c_b.encrypt(key_b, table_b)
Because encrypted contributions are also
collaborationobjects, they can be easily converted to and from JSON strings. The recipient can then use therecipient.evaluatemethod (which again internally leverages the nth.community service platform) to evaluate the encrypted contributions and obtain a result.>>> result = r.evaluate({c_a.identifier(): enc_a, c_b.identifier(): enc_b}) >>> result["value"] 3
- generate(collaboration) dict
Submit a collaboration via the nth.community service platform API to receive the set of contributor keys that can be distributed to contributors. Find an in-context usage example in the documentation for the
recipientclass.
- evaluate(collaborations) nthcommunity.nthcommunity.collaboration
Evaluate a collaboration workflow instantiated with encrypted data contributions (represented as a dictionary that maps each contributor’s identifier to that contributor’s encrypted contribution) by submitting it to the nth.community service platform. Find an in-context usage example in the documentation for the
recipientclass.
- class nthcommunity.nthcommunity.contributor(identifier=None)
Bases:
dictData structure and methods for an individual data contributor within a collaboration. A contributor receives a collaboration key from a recipient and encrypts their data contribution using that key.
>>> (r, c_a, c_b) = (recipient(), contributor(), contributor()) >>> w = count(intersection(table(contributor=c_a), table(contributor=c_b))) >>> id_to_key = r.generate(w)
Each of the individual keys in
id_to_key.values()can be delivered to their corresponding contributor. Each contributor can then use the key to encrypt their data contribution via thecontributor.encryptmethod, as shown below.>>> id_a = c_a.identifier() >>> table_a = [['a'], ['b'], ['c'], ['d']] >>> table_a_encrypted = c_a.encrypt(id_to_key[id_a], table_a)
- identifier() str
Return this contributor’s unique identifier.
>>> c = contributor() >>> isinstance(c.identifier(), str) True
- static from_json(argument: Union[str, dict]) nthcommunity.nthcommunity.contributor
Parse a dictionary or JSON string into an instance of this class.
>>> s = '{"type": "contributor", "identifier": "b1a63caf"}' >>> isinstance(contributor.from_json(s), contributor) True
- to_json(*args, **kwargs) str
Convert an instance of this class into a JSON string. This method is a wrapper for the
json.dumpsmethod found in the built-in json library.>>> c = contributor('b1a63caf-a549-429e-8ed0-44cd5fbb0eeb') >>> c.to_json() '{"type": "contributor", "identifier": "b1a63caf-a549-429e-8ed0-44cd5fbb0eeb"}'
- validate(collaboration) bool
Validate the certificate within a contribution key obtained from a recipient by submitting it to the nth.community service platform. The
contributor.encryptmethod automatically invokes this method before encrypting a contribution.>>> (r, c_a, c_b) = (recipient(), contributor(), contributor()) >>> w = count(intersection(table(contributor=c_a), table(contributor=c_b))) >>> key_a = r.generate(w)[c_a.identifier()] >>> c_a.validate(key_a) True
- encrypt(collaboration, contribution) nthcommunity.nthcommunity.collaboration
Encrypt a data set as a contribution to a collaboration. Find an in-context usage example in the documentation for the
recipientclass.>>> (r, c_a, c_b) = (recipient(), contributor(), contributor()) >>> w = count(intersection(table(contributor=c_a), table(contributor=c_b))) >>> key_a = r.generate(w)[c_a.identifier()] >>> table_a = [['a'], ['b'], ['c'], ['d']] >>> enc_a = c_a.encrypt(key_a, table_a)
After validating the contribution key, this method does not perform any external communications and encrypts the input data entirely within the host environment belonging to the contributor. In particular, it does not communicate with the nth.community service platform or the recipient during this process.
- class nthcommunity.nthcommunity.count(*arguments)
Bases:
nthcommunity.nthcommunity.collaborationCollaboration tree node for the count operation. A count operation can be applied to a single intersection collaboration.
>>> (c_a, c_b) = (contributor(), contributor()) >>> w = count(intersection(table(contributor=c_a), table(contributor=c_b)))
Any attempt to apply a count operation to a collaboration workflow that is not compatible with a count operation raises an exception.
>>> count(integer(123)) Traceback (most recent call last): ... TypeError: count operation must be applied to a single intersection collaboration
- class nthcommunity.nthcommunity.summation(*arguments)
Bases:
nthcommunity.nthcommunity.collaborationCollaboration tree node for the summation operation. A summation operation can be applied to two or more contributors’ integer contributions.
>>> (c_a, c_b) = (contributor(), contributor()) >>> w = summation(integer(contributor=c_a), integer(contributor=c_b))
Any attempt to apply a summation operation to a collaboration workflow that is not compatible with a summation operation raises an exception.
>>> summation(integer(123)) Traceback (most recent call last): ... TypeError: summation operation must be applied to two or more integers
- class nthcommunity.nthcommunity.intersection(*arguments)
Bases:
nthcommunity.nthcommunity.collaborationCollaboration tree node for the intersection operation. An intersection operation can be applied to two or more contributors’ table contributions.
>>> (c_a, c_b) = (contributor(), contributor()) >>> w = intersection(table(contributor=c_a), table(contributor=c_b))
Any attempt to apply an intersection operation to a collaboration workflow that is not compatible with an intersection operation raises an exception.
>>> intersection(table()) Traceback (most recent call last): ... TypeError: intersection operation must be applied to two or more tables
- class nthcommunity.nthcommunity.integer(value=None, contributor=None)
Bases:
nthcommunity.nthcommunity.collaborationCollaboration tree leaf node for a contributed integer value within a collaboration tree data structure. Only 32-bit non-negative integers are supported.
>>> c = contributor() >>> w = integer(value=123, contributor=c)
Any attempt to construct an invalid integer contribution raises an exception.
>>> integer(-123) Traceback (most recent call last): ... ValueError: integer value must be a non-negative 32-bit integer
- class nthcommunity.nthcommunity.table(value=None, contributor=None, limit=None)
Bases:
nthcommunity.nthcommunity.collaborationCollaboration tree leaf node for a contributed data table within a collaboration tree data structure. A contributed table must be a list of rows, and each row must a single-element list that contains exactly one string.
>>> c = contributor() >>> w = table(value=[['a'], ['b'], ['c']], contributor=c)
Any attempt to construct a data table contribution that is invalid or that exceeds size limits raises an exception.
>>> table(['a', 'b', 'c']) Traceback (most recent call last): ... ValueError: table value must be a list of single-item lists, each containing a string >>> table([['a']] * 1001) Traceback (most recent call last): ... ValueError: table length exceeds maximum of 1000 >>> table([['a' * 257]]) Traceback (most recent call last): ... ValueError: table field value length exceeds maximum of 256
- exception nthcommunity.nthcommunity.ServiceError
Bases:
RuntimeErrorException indicating that the service platform responded to an API request but indicated an error has occurred service-side (due to either an improperly configured service instance or an improper request).
>>> (c_a, c_b) = (contributor(), contributor()) >>> w = count(intersection(table(contributor=c_a), table(contributor=c_b))) >>> del w["type"] >>> try: ... recipient().generate(w) ... except ServiceError as e: ... print(e) service did not return a valid response