| 1 | '''sealing -- E's Rights Amplification mechanism |
|---|
| 2 | |
|---|
| 3 | From `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 | |
|---|
| 18 | See 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 | |
|---|
| 33 | def 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 | |
|---|
| 90 | class 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) |
|---|