forked from linkeddata/swap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcwm_crypto.py
executable file
·210 lines (171 loc) · 6.94 KB
/
cwm_crypto.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#!/usr/bin/python
"""
Cryptographic Built-Ins for CWM/Llyn
The continuing story of cryptographic builtins.
cf. http://www.w3.org/2000/10/swap/cwm.py
& http://www.amk.ca/python/writing/pycrypt/node16.html
2010-11-01 TimBL Updated to use hashlib and added more SHA variants.
"""
__author__ = 'Sean B. Palmer'
__cvsid__ = '$Id$'
__version__ = '$Revision$'
# 2010: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
import hashlib # http://pydoc.org/2.5.1/hashlib.html
# import, binascii, quopri, base64
from term import Function, ReverseFunction, LightBuiltIn
USE_PKC = 1
if USE_PKC:
try:
import Crypto.Util.randpool as randpool
import Crypto.PublicKey.RSA as RSA
except ImportError:
USE_PKC = 0
# 'we failed' -- Fail silently now unless --crypto asked for
# Note that Public Key stuff is not available but hashes still work.
# Some stuff that we need to know about
CRYPTO_NS_URI = 'http://www.w3.org/2000/10/swap/crypto#'
# A debugging function...
def formatObject(obj):
"""Print the various bits found within a key (works on any object)."""
if ' ' in repr(obj): result = repr(obj)[1:].split(' ')[0]+'\n'
else: result = '\n'
for n in dir(obj): result += str(n)+' '+str(getattr(obj, n))+'\n'
return '[[[%s]]]' % result
# Functions for constructing keys, and formatting them for use in text
def newKey(e, n, d=None, p=None, q=None):
"""Create a new key."""
key = RSA.RSAobj() # Create a new empty RSA Key
key.e, key.n = e, n # Feed it the ee and modulus
if d is not None:
key.d, key.p, key.q = d, p, q
return key
else: return key.publickey() # Return the public key variant
def keyToQuo(key, joi='\n\n'):
"""Returns a quoted printable version of a key - ee then m.
Leading and trailing whitespace is allowed; stripped by quoToKey."""
e, n = str(key.e), str(key.n) # Convert the ee and mod to strings
if key.has_private():
d, p, q = str(key.d), str(key.p), str(key.q)
strkey = base64.encodestring(joi.join([e, n, d, p, q]))
else:
strkey = base64.encodestring('%s%s%s' % (e, joi, n))
return '\n'+quopri.encodestring(strkey).strip()+'\n'
def quoToKey(strkey, spl='\n\n'):
"""Returns a key from quopri (ee then m) version of a key."""
bunc = base64.decodestring(quopri.decodestring(strkey.strip()))
bits = bunc.split(spl)
if len(bits) == 2: return newKey(long(bits[0]), long(bits[1]))
else:
e, n, d, p, q = bits
return newKey(long(e), long(n), long(d), long(p), long(q))
# Signature encoding and decoding
def baseEncode(s):
s = base64.encodestring(s)
return '\n'+quopri.encodestring(s).strip()+'\n'
def baseDecode(s):
s = quopri.decodestring(s.strip())
return base64.decodestring(s)
# Decimal to binary
def decToBin(i): # int to string
result = ''
while i > 0:
d = i % 2
result = str(d)+result
i /= 2
return result
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# C R Y P T O G R A H P I C B U I L T - I N s
#
# At the moment, we only have built-ins that can gauge the hash values of
# strings. It may be cool to have built ins that can give the hash value
# of the content of a work, too, although you can do that with log:content.
#
# Light Built-in classes
# Hash Constructors - light built-ins
class BI_md5(LightBuiltIn, Function):
def evaluateObject(self, subj_py):
return hashlib.md5(subj_py).hexdigest();
return binascii.hexlify(m)
class BI_sha(LightBuiltIn, Function):
def evaluateObject(self, subj_py):
return hashlib.sha1(subj_py).hexdigest();
class BI_sha224(LightBuiltIn, Function):
def evaluateObject(self, subj_py):
return hashlib.sha224(subj_py).hexdigest();
class BI_sha256(LightBuiltIn, Function):
def evaluateObject(self, subj_py):
return hashlib.sha256(subj_py).hexdigest();
class BI_sha384(LightBuiltIn, Function):
def evaluateObject(self, subj_py):
return hashlib.sha384(subj_py).hexdigest();
class BI_sha512(LightBuiltIn, Function):
def evaluateObject(self, subj_py):
return hashlib.sha512(subj_py).hexdigest();
# Create a new RSA key
class BI_keyLength(LightBuiltIn, Function, ReverseFunction):
def __init__(self, resource, fragid):
LightBuiltIn.__init__(self, resource, fragid)
Function.__init__(self)
ReverseFunction.__init__(self)
self.do = 1
def evaluateSubject(self, obj_py):
"""Generates an RSA keypair, and spews it out as plain text.
Has the limitation that it will *only* ever let you generate
one key pair (per iteration), in order to work around a bug."""
if self.do:
randfunc, self.do = randpool.RandomPool(int(obj_py)), 0
RSAKey = RSA.generate(int(obj_py), randfunc.get_bytes)
TextKey = keyToQuo(RSAKey)
if TextKey != 'N.': return TextKey
def evaluateObject(self, subj_py):
RSAKey = quoToKey(subj_py)
return str(len(decToBin(RSAKey.n))) # @@ not integer?
class BI_sign(LightBuiltIn, Function):
def evaluateObject(self, subj_py):
"""Sign a hash with a key, and get a signature back."""
import time
hash, keypair = subj_py
RSAKey = quoToKey(keypair)
signature = RSAKey.sign(hash, str(time.time())) # sign the hash with the key
return baseEncode(str(signature[0]))
class BI_verify(LightBuiltIn):
def evaluate(self, subj_py, obj_py):
"""Verify a hash/signature."""
keypair, (hash, signature) = subj_py, obj_py
hash = hash.encode('ascii')
RSAKey = quoToKey(keypair) # Dequote the key
signature = (long(baseDecode(signature)),) # convert the signature back
return RSAKey.verify(hash, signature)
class BI_verifyBoolean(LightBuiltIn, Function):
def evaluateObject(self, subj_py):
"""Verify a hash/signature."""
keypair, hash, signature = subj_py
hash = hash.encode('ascii')
RSAKey = quoToKey(keypair) # Dequote the key
signature = (long(baseDecode(signature)),)
result = RSAKey.verify(hash, signature)
return str(result)
class BI_publicKey(LightBuiltIn, Function):
def evaluateObject(self, subj_py):
"""Generate a quopri public key from a keypair."""
keypair = quoToKey(subj_py) # Dequote the key
publickey = keypair.publickey() # Get the public key
return keyToQuo(publickey)
# Register the string built-ins with the store
def register(store):
str = store.symbol(CRYPTO_NS_URI[:-1])
str.internFrag('md5', BI_md5)
str.internFrag('sha', BI_sha)
str.internFrag('sha224', BI_sha224)
str.internFrag('sha256', BI_sha256)
str.internFrag('sha384', BI_sha384)
str.internFrag('sha512', BI_sha512)
if USE_PKC:
str.internFrag('keyLength', BI_keyLength)
str.internFrag('sign', BI_sign)
str.internFrag('verify', BI_verify)
str.internFrag('verifyBoolean', BI_verifyBoolean)
str.internFrag('publicKey', BI_publicKey)
if __name__=="__main__":
print __doc__.strip()