def private$instance$key():
return:
def hash$(s):
if is$string(s):
return 'components/services/entropy/sha256'(s)
if is$sequence(s):
kwd = keywords$()
r = []
for x in s:
r.append(kwd[x])
return hash$(''.join(r))
ia = call.assets.Itham
db = ia.components.database.code.db$attach$memory(db.value) <- db:
signature$db:
signatures(table):
- owner: string
- contentId: string
- signature: string
masks(table):
- owner: string
- mask_name: string
def database$():
return db
def sign$content(owner, contentId, content):
sContentId = string(contentId)
chk = hash$(['key', 'owner', 'contentId', 'content'], \
key = private$instance$key(), \
owner = owner, contentId = sContentId, \
content = content)
.db.signatures(owner, sContentId, chk).save()
return mapping(contentId = sContentId, \
signature = chk)
def verify$signature(owner, contentId, chk):
r = false
for s in .db.signatures.query(mapping(owner = owner, contentId = contentId)):
r = s.signature == chk
break
return r
def signature$(s):
return namespace \
(contentId = s.contentId, \
signature = s.signature)
def known$signatures(owner):
return sequence(map(signature$, .db.signatures \
.query(mapping(owner = owner))))
def known$signatures$all():
r = mapping()
for s in .db.signatures.all():
r.setdefault(s.owner, []) \
.append(signature$(s))
return r
def mask$(owner, mask$name):
if is$not$none(unmask$(mask$name)):
raise(value$error, 'Mask name already used')
.db.masks(owner, mask$name).save()
def unmask$(mask$name):
r = none
for m in .db.masks.query(mapping(mask_name = mask$name)):
r = m.owner
break
return r
def generate$contentId(owner):
scatter$args('owner', ['n', '10'], ['tries', 1000])
ns = mapping(n = integer(n))
gen = action(run$python, code, ns) <- code:
from string import ascii_letters
from random import choice
__return = ''.join(choice(ascii_letters) for x in range(n))
contentId = none
for x in range(tries):
contentId = gen()
s = none
for s in .db.signatures.query(mapping(owner = owner, contentId = contentId)):
break
if is$none(s):
break
if is$not$none(contentId):
return contentId
raise(value$error, 'Max tries reached (%s)' % tries)
sign(view):
context(trigger)::
if request.method == 'POST':
post = request.POST
owner = request.user.securityContext(programmer)
contentId = generate$contentId(owner)
r = sign$content(owner, contentId, post['content'])
return 'text/json/dumps'(r)
template::
<form method="POST">
<input type="">
<input type="file" name="content-file">
<br /><input type="submit">
</form>
mask(view):
context(trigger)::
if request.method == 'POST':
owner = request.user.securityContext(programmer)
mask$(owner, request.POST['mask$name'])
verify(view):
context(trigger)::
if is$deep$view(path):
scatter(path, 'mask', 'contentId', 'signature')
else:
if request.method == 'POST':
post = request.POST
else:
post = request.GET
try: mask = ['mask']
except key$error:
owner = post['owner']
else:
owner = unmask$(mask)
contentId = post['contentId']
chk = post['signature']
r = verify$signature(owner, contentId, chk)
return 'text/json/dumps'(r == true)
usage:
function public$sign(mask$name, content)
{
$.post('mask', {mask$name}).then
(() => $.post('sign', {content},
function (chk)
{ $.get(`verify/${mask$name}/${chk.contentId}/{chk.signature}`,
(isVerified) => console.log(`Verified: ${isVerified}`)); }));
}