source: raven-j/heron_wsgi/admin_lib/sealing.py

Last change on this file was 0:4b7a93ab1a38, checked in by Tamara McMahon <tmcmahon@…>, 9 months ago

KUMC DROC Data Dictionary requested by Mosa

File size: 3.2 KB
Line 
1'''sealing -- Emulate E's Rights Amplification mechanism in Python
2------------------------------------------------------------------
3
4From  `Rights Amplification section of ELib: Inter-Object Semantics`__:
5
6  Sealer/unsealer pairs are similar in concept to public/private key
7  pairs. The sealer is like an encryption key, and the unsealer like a
8  decryption key. The provided primitive, makeBrandPair, makes and
9  returns such a pair. When the sealer is asked to seal an object it
10  returns an envelope which can only be unsealed by the corresponding
11  unsealer.
12
13__ http://www.erights.org/elib/capability/ode/ode-capabilities.html#rights-amp
14
15.. note:: This probably doesn't provide all of the security properties
16          it's supposed to due to python's stack introspection
17          mechanisms.
18
19See also:
20  * `javadoc for org.erights.e.elib.sealing`__
21  * `Sealers and Unsealers on the ERights Wiki`__
22
23__ http://www.erights.org/javadoc/org/erights/e/elib/sealing/package-summary.html
24__ http://wiki.erights.org/wiki/Walnut/Secure_Distributed_Computing/Capability_Patterns#Sealers_and_Unsealers
25
26'''
27
28__author__ = 'Dan Connolly'
29__contact__ = 'http://informatics.kumc.edu/'
30__copyright__ = 'Copyright (c) 2011 Univeristy of Kansas Medical Center'
31__license__ = 'Apache 2'
32__docformat__ = "restructuredtext en"
33
34
35def makeBrandPair(nickname):
36    '''Returns a Sealer/Unsealer pair
37    identified with a new unique brand of the specified (non-unique) name.
38
39      >>> s, u = makeBrandPair('bob')
40      >>> s
41      <bob sealer>
42      >>> u
43      <bob unsealer>
44      >>> x = s.seal('abc')
45      >>> x
46      <bob sealed box>
47      >>> u.unseal(x)
48      'abc'
49
50      >>> ss, uu = makeBrandPair('evil')
51      >>> uu.unseal(x)
52      Traceback (most recent call last):
53      ...
54      TypeError
55
56    '''
57
58    noObject = object()
59    # python closures are read only, so we close over a mutable list.
60    shared = [noObject]
61
62    def makeSealedBox(obj):
63        # python lambda expressions can't contain statements,
64        # so we define an auxiliary function
65        def _shareContent():
66            shared[0] = obj
67        box = EDef(shareContent=_shareContent,
68                   __repr__=lambda: '<%s sealed box>' % nickname
69                   )
70        return box
71
72    sealer = EDef(
73        seal=makeSealedBox,
74        __repr__=lambda: '<%s sealer>' % nickname
75        )
76
77    def _unseal(box):
78        shared[0] = noObject
79        try:
80            box.shareContent()
81        except:
82            raise TypeError
83        if (shared[0] is noObject):
84            raise TypeError
85        contents = shared[0]
86        shared[0] = noObject
87        return contents
88
89    unsealer = EDef(unseal=_unseal,
90                    __repr__=lambda: '<%s unsealer>' % nickname
91                    )
92
93    return (sealer, unsealer)
94
95
96class EDef:
97    '''Imitate e object definition using 'anonymous' python classes.
98
99    ack: `The Python IAQ: Infrequently Answered Questions`__
100    by Peter Norvig
101
102    __ http://norvig.com/python-iaq.html
103
104    Note the use of old-style classes.
105    '''
106    def __init__(self, **entries):
107        self.__dict__.update(entries)
108
109    def __repr__(self):
110        args = ['%s=%s' % (k, repr(v)) for (k, v) in vars(self).items()]
111        return '<%s>' % ', '.join(args)
Note: See TracBrowser for help on using the repository browser.