source: raven-j/heron_wsgi/admin_lib/sealing.py @ 418:1c54f87016fb

Revision 418:1c54f87016fb, 3.1 KB checked in by Dan Connolly <dconnolly@…>, 4 months ago (diff)

toward right-side-out capabilities: medcenter.py tests pass

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