SF.net SVN: fclient: [307] trunk/sandbox/fcp2/key.py
Status: Pre-Alpha
Brought to you by:
jurner
|
From: <ju...@us...> - 2008-03-04 17:38:15
|
Revision: 307
http://fclient.svn.sourceforge.net/fclient/?rev=307&view=rev
Author: jurner
Date: 2008-03-04 09:38:18 -0800 (Tue, 04 Mar 2008)
Log Message:
-----------
new key module providing more in depth handling of freenet keys
Added Paths:
-----------
trunk/sandbox/fcp2/key.py
Added: trunk/sandbox/fcp2/key.py
===================================================================
--- trunk/sandbox/fcp2/key.py (rev 0)
+++ trunk/sandbox/fcp2/key.py 2008-03-04 17:38:18 UTC (rev 307)
@@ -0,0 +1,272 @@
+"""Fcp keys"""
+
+import os, sys
+import base64
+import re
+import urlparse
+
+#--> rel import hack
+class _RelImportHack(object):
+ def __init__(self, n):
+ fpath = os.path.abspath(__file__)
+ for i in xrange(n): fpath = os.path.dirname(fpath)
+ sys.path.insert(0, fpath)
+ def __del__(self): sys.path.pop(0)
+hack = _RelImportHack(2)
+
+from fcp2 import consts
+
+
+del hack
+#<-- rel import hack
+#**************************************************************************************
+# consts
+#**************************************************************************************
+ReMatchExact = '\A%s\Z'
+
+#**************************************************************************************
+# freenet base64 for keys
+#**************************************************************************************
+def base64UrlsaveDecode(string):
+ """Decodes a base64 urlsave encoded string as encoded by freenet
+ @param string: string to decode
+ @return: decoded string
+
+ @raise TypeError: if the string can not be decoded
+ @note: this function handles non-standard encoding as used by freenet (see: freenet/src/support/base64.java)
+ """
+ # freenet uses - for + and ~ for /
+ altchars = '-~'
+
+ # padding may be ommitted or not
+ padding = 4 - len(string) % 4
+ if padding:
+ string += '=' * padding
+ return base64.b64decode(string, altchars)
+
+
+def stripKey(key):
+ """Strips all uri stuff from a key
+ @param key: (str) key to strip
+ @return: (str) key
+ """
+ return urlparse.urlsplit(key)[2]
+
+#****************************************************************************************
+# freenet keys
+#
+# KeyType@32 bytes hash, 32 bytes encryption key, 5 bytes extra
+#
+# all byte components are base64 encoded. Freenet uses base64 without padding
+# along with the following altchars for urlsave encode: - for + and ~ for /
+# see: freenet/support/base64.java
+#
+# so a key as the user gets it to see is:
+# KeyType@43 bytes, 43 bytes, 7 bytes ..of [A-Za-z0-9\-~]
+#
+# see: [freenet/src/support/base64.java]
+#
+#***************************************************************************************
+class KeyBase(object):
+ """
+ >>> key = KeyBase.fcpToPython('CHK@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,AAAAAAA/foo')
+ >>> key.pythonToFcp()
+ 'CHK@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,AAAAAAA/foo/'
+ >>> key = KeyBase.fcpToPython('CHK@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,AAAAAAA/foo/')
+ >>> key.pythonToFcp()
+ 'CHK@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,AAAAAAA/foo/'
+
+ >>> key = KeyBase.fcpToPython('SSK@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,AAAAAAA/foo')
+ >>> key.pythonToFcp()
+ 'SSK@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,AAAAAAA/foo/'
+ >>> key = KeyBase.fcpToPython('SSK@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,AAAAAAA/foo/')
+ >>> key.pythonToFcp()
+ 'SSK@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,AAAAAAA/foo/'
+
+ >>> key = KeyBase.fcpToPython('USK@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,AAAAAAA/foo/0')
+ >>> key.pythonToFcp()
+ 'USK@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,AAAAAAA/foo/0/'
+ >>> key = KeyBase.fcpToPython('USK@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,AAAAAAA/foo/0/')
+ >>> key.pythonToFcp()
+ 'USK@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,AAAAAAA/foo/0/'
+
+ >>> key = KeyBase.fcpToPython('KSK@abcde')
+ >>> key.pythonToFcp()
+ 'KSK@abcde/'
+ >>> key = KeyBase.fcpToPython('KSK@abcde/')
+ >>> key.pythonToFcp()
+ 'KSK@abcde/'
+
+ """
+
+ KeyTypesAll = {}
+
+ @classmethod
+ def fcpToPython(clss, string):
+ key = stripKey(string)
+ for clssKeyType in clss.KeyTypesAll.values():
+ result = clssKeyType.fromString(key)
+ if result is not None:
+ return result
+
+
+
+class CHK(KeyBase):
+ """"""
+ _key_pattern_ = '''
+ (?P<keyType>CHK@)
+ (?P<keyData>
+ (?P<hash>[a-z0-9\-~]{43}),
+ (?P<cryptoKey>[a-z0-9\-~]{43}),
+ (?P<extra>[a-z0-9\-~]{7})
+ )
+ (?: / (?P<filename>[^/]+?) (?: /)?)?
+ '''
+ KeyType = consts.KeyType.CHK
+ KeyPattern = re.compile(_key_pattern_, re.I | re.X)
+ ExactKeyPattern = re.compile(ReMatchExact % _key_pattern_, re.I | re.X)
+
+ def __init__(self, filename=None):
+ """Creates a CHK key
+
+ @param filename: (str) filename to add to the key or None
+ """
+ self.keyData = None
+ self.filename = filename
+
+ def pythonToFcp(self):
+ out = self.KeyType
+ if self.keyData is not None:
+ out += self.keyData + '/'
+ if self.filename is not None:
+ out += self.filename + '/'
+ return out
+
+ @classmethod
+ def fromString(clss, string):
+ result = clss.ExactKeyPattern.match(string)
+ if result is not None:
+ d = result.groupdict()
+ clss = clss(filename=d['filename'])
+ clss.keyData = d['keyData']
+ return clss
+
+
+KeyBase.KeyTypesAll[CHK.KeyType] = CHK
+
+
+class SSK(KeyBase):
+ _key_pattern_ = '''
+ (?P<keyType>SSK@)
+ (?P<keyData>
+ (?P<hash>[a-z0-9\-~]{43}),
+ (?P<cryptoKey>[a-z0-9\-~]{43}),
+ (?P<extra>[a-z0-9\-~]{7})
+ )
+ (?: / (?P<filename>[^/]+?))
+ (?: /)?
+ '''
+ KeyType = consts.KeyType.SSK
+ KeyPattern = re.compile(_key_pattern_, re.I | re.X)
+ ExactKeyPattern = re.compile(ReMatchExact % _key_pattern_, re.I | re.X)
+
+ def __init__(self, keyData, filename):
+ self.filename = filename
+ self.keyData = keyData
+
+ def pythonToFcp(self):
+ out = self.KeyType
+ if self.keyData is not None:
+ out += self.keyData + '/'
+ if self.filename is not None:
+ out += self.filename + '/'
+ return out
+
+ @classmethod
+ def fromString(clss, string):
+ result = clss.ExactKeyPattern.match(string)
+ if result is not None:
+ d = result.groupdict()
+ return clss(d['keyData'], d['filename'])
+
+KeyBase.KeyTypesAll[SSK.KeyType] = SSK
+
+
+class KSK(KeyBase):
+ _key_pattern_ = '''
+ (?P<keyType>KSK@)
+ (?P<filename>[^/]+?)
+ (?: /)?
+ '''
+ KeyType = consts.KeyType.KSK
+ KeyPattern = re.compile(_key_pattern_, re.I | re.X)
+ ExactKeyPattern = re.compile(ReMatchExact % _key_pattern_, re.I | re.X)
+
+
+ def __init__(self, filename):
+ self.filename = filename
+
+ def pythonToFcp(self):
+ out = self.KeyType
+ if self.filename is not None:
+ out += self.filename + '/'
+ return out
+
+ @classmethod
+ def fromString(clss, string):
+ result = clss.ExactKeyPattern.match(string)
+ if result is not None:
+ d = result.groupdict()
+ clss = clss(filename=d['filename'])
+ return clss
+
+
+KeyBase.KeyTypesAll[KSK.KeyType] = KSK
+
+
+class USK(KeyBase):
+ _key_pattern_ = '''
+ (?P<keyType>USK@)
+ (?P<keyData>
+ (?P<hash>[a-z0-9\-~]{43}),
+ (?P<cryptoKey>[a-z0-9\-~]{43}),
+ (?P<extra>[a-z0-9\-~]{7})
+ )
+ (?: / (?P<filename>[^/]+?) )
+ (?: / (?P<edition>[\d]+))
+ (?: /)?
+ '''
+
+ KeyType = consts.KeyType.USK
+ KeyPattern = re.compile(_key_pattern_, re.I | re.X)
+ ExactKeyPattern = re.compile(ReMatchExact % _key_pattern_, re.I | re.X)
+
+ def __init__(self, keyData, filename, edition=0):
+ self.edition = edition
+ self.filename = filename
+ self.keyData = keyData
+
+ def pythonToFcp(self):
+ out = self.KeyType
+ if self.keyData is not None:
+ out += self.keyData + '/'
+ if self.filename is not None:
+ out += self.filename + '/'
+ if self.edition is not None:
+ out += self.edition + '/'
+ return out
+
+ @classmethod
+ def fromString(clss, string):
+ result = clss.ExactKeyPattern.match(string)
+ if result is not None:
+ d = result.groupdict()
+ return clss(d['keyData'], d['filename'], edition=d['edition'])
+
+KeyBase.KeyTypesAll[USK.KeyType] = USK
+#*****************************************************************************
+#
+#*****************************************************************************
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|