Skip to content

Commit

Permalink
Update to match latest library, addition of
Browse files Browse the repository at this point in the history
raw signature tester (/rawsignatures)


git-svn-id: http://salmon-protocol.googlecode.com/svn/trunk@76 0c3e17fe-a321-11de-97f0-97815e7b2756
  • Loading branch information
johnrobertpanzer committed Mar 16, 2010
1 parent ce73dd1 commit 5bb21f8
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 37 deletions.
6 changes: 3 additions & 3 deletions salmon-playground/magicsigdemo.html
Expand Up @@ -55,7 +55,7 @@
$.ajax({
type: "POST",
url: "/magicsigdemo?format=magic-envelope",
data: "data="+escape(text),
data: "data="+encodeURIComponent(text),
success: function(response){
$('#envelope').val(response);
$('#output').fadeOut();
Expand All @@ -74,7 +74,7 @@
$.ajax({
type: "POST",
url: "/magicsigdemo?format=atom",
data: "env="+escape(text),
data: "env="+encodeURIComponent(text),
success: function(response){
$('#signedAtom').val(response);
$('#output').fadeIn();
Expand All @@ -92,7 +92,7 @@
$.ajax({
type: "POST",
url: "/magicsigdemoverify",
data: "data="+escape(text),
data: "data="+encodeURIComponent(text),
success: function(response){
if (response == "OK") {
showStatusAndHideAfterFiveSecs("Salmon signature verified!");
Expand Down
61 changes: 28 additions & 33 deletions salmon-playground/magicsigdemo.py
Expand Up @@ -25,6 +25,7 @@
import wsgiref.handlers
import dumper
import cgi
import sys

from string import strip

Expand Down Expand Up @@ -78,69 +79,63 @@ def post(self):
format = self.request.get('format') or 'magic-envelope'
if data:
logging.info('posted Atom data = %s\n',data)
userid = users.get_current_user().email();
userid = magicsig.NormalizeUserIdToUri(
users.get_current_user().email())

# Do an ACL check to see if current user is the author:
if not self.magicenv.CheckAuthorship(data,
magicsig.NormalizeUserIdToUri(userid)):
if not self.magicenv.IsAllowedSigner(data, userid):
logging.info("Authorship check failed for user %s\n",userid)
self.response.set_status(400)
self.response.out.write("User "+userid+" not first author of entry,"
" cannot sign.")
return

# Sign the content on behalf of user:
env = self.magicenv.SignMessage(data, 'application/atom+xml', userid)
envelope = magicsig.Envelope(raw_data_to_sign=data,
data_type='application/atom+xml',
signer_uri=userid,
signer_key='TEST')
#env = self.magicenv.SignMessage(data, 'application/atom+xml', userid)
elif envText:
logging.info('posted Magic envelope env = %s\n',envText)
env = self.magicenv.Parse(envText)
envelope = magicsig.Envelope(document=envText,
mime_type='applicaton/magic-envelope+xml')
#env = self.magicenv.Parse(envText)

# Just to sanity check:
assert self.magicenv.Verify(env)

#logging.info("Created env! data:\n%s\nand signature:\n%s\n",env['data'],env['sig'])
logging.info('Created magic envelope: \n%s\n' % envelope)

self.response.set_status(200) # The default
if format == 'magic-envelope':
self.response.out.write("""<?xml version='1.0' encoding='UTF-8'?>
<me:env xmlns:me='http://salmon-protocol.org/ns/magic-env'>
<me:data type='application/atom+xml' encoding='"""+env['encoding']+"""'>\n"""+
env['data']+"""</me:data>
<me:alg>"""+env['alg']+"""</me:alg>
<me:sig>"""+env['sig']+"""</me:sig>
</me:env>\n
"""
)
self.response.out.write(envelope.ToXML())
elif format == 'atom':
#self.response.out.write("Content-Type: application/atom+xml; charset=utf-8\n\n")
self.response.out.write(self.magicenv.Unfold(env))
self.response.out.write(envelope.ToAtom())
else:
self.response.set_status(400)
raise "Unsupported format: "+format

class VerifyThisHandler(webapp.RequestHandler):
"""Handles request to verify a magic envelope or signed Atom entry.
"""

magicenv = magicsig.MagicEnvelopeProtocol()

def post(self):
""" Intended to be called via XHR from magicsigdemo.html. """

data = self.request.get('data')
logging.info('data = %s\n',data)
logging.error('MagicSigDemoVerify post')
data = self.request.get('data').strip()
logging.info('The data = %s\n',data)
env = self.magicenv.Parse(data)
logging.info('env = %s\n',env)

self.response.set_status(200) # The default
if self.magicenv.Verify(env):
try:
envelope = magicsig.Envelope(document=data,
mime_type='application/magic-envelope+xml')
self.response.set_status(200) # The default
self.response.out.write("OK")
logging.info("Salmon signature verified!")
else:
self.response.set_status(400) # Input error (does not validate)
self.response.out.write("Signature does not validate.")
logging.info("Salmon signature verification FAILED")
logging.info("SPLASH! Salmon signature verified!")
except magicsig.Error:
self.response.set_status(400)
info = "Details: Exception %s:\n%s\nTraceback:\n%s" % sys.exc_info()
logging.info(info)
self.response.out.write('Signature does not validate. Details: %s' % info)

if __name__ == '__main__':
main()
5 changes: 4 additions & 1 deletion salmon-playground/main.py
Expand Up @@ -39,6 +39,7 @@
# Demos
import magicsigdemo
from magicsig import magicsigalg #TODO get rid of this, should not be used
import rawsignatures

#Data model
import model
Expand Down Expand Up @@ -237,6 +238,7 @@ class LatestHandler(webapp.RequestHandler):

@aclRequired
def get(self):
logging.error('ZAWEEBO!')
stuff=[]
for salmon in Entry.gql('ORDER BY updated DESC').fetch(10):
text = cgi.escape(salmon.content if salmon.content else '(no content)')
Expand Down Expand Up @@ -309,7 +311,8 @@ def get(self):
(r'/oauth/(.*)', OAuthDanceHandler),
(r'/blogproxy', bloggerproxy.BlogProxyHandler),
(r'/magicsigdemo', magicsigdemo.SignThisHandler),
(r'/magicsigdemoverify', magicsigdemo.VerifyThisHandler)
(r'/magicsigdemoverify', magicsigdemo.VerifyThisHandler),
(r'/rawsignatures', rawsignatures.RawSignaturesHandler),
],
debug=True)

Expand Down
75 changes: 75 additions & 0 deletions salmon-playground/rawsignatures.html
@@ -0,0 +1,75 @@
<html>
<head>
<title>Raw Signatures Test</title>
<link type="text/css" rel="stylesheet" href="/static/setup_proxy.css"/>
<style type="text/css">
.entry { margin-bottom: .8em; }
.replies { margin-left: 2em; }
.reply { margin-bottom: 0em; }
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
</head>
<body>

<div id="header">
<div class="right"><a href="/oauth/revoke_token">logout</a></div>
<div class="left"><img src="/static/salmon.jpeg" style="float:left"> Raw
Signature Tester</div>
<div id="status" class="hidden"><span class="text">blah blah</span></div>
</div>

<div id="content">
<p>Input a raw string to sign (exact bytes entered will be signed):</p>
<form>
<TEXTAREA id='text' rows=12 cols=120></TEXTAREA>
<a title="Sign" href="javascript:sign_text($('#text').val())">Sign</a>
</form>
</div>
<div>
<p>Output:</p>
<TEXTAREA id='output' rows=6 cols=120></TEXTAREA>
</div>
<script>

// Grab user input and create a signed magic envelope from it:
function sign_text(text) {
showStatus("Signing...");
$('#output').val('working...');
$.ajax({
type: "POST",
url: "/rawsignatures",
data: "data="+encodeURIComponent(text),
success: function(response){
$('#output').val(response);
showStatusAndHideAfterFiveSecs("Signed!");
},
error: function(xhr, statusText, errorThrown){
$('#output').val("Error "+xhr.status+": "+xhr.responseText);
showStatusAndHideAfterFiveSecs("Error!");
},
});
}

function showStatus(msg) {
// Move to visible portion of window
$("#status span").css("position", "relative");
$("#status span").css("top", $("body").scrollTop());
$('#status span.text').text(msg);
$('#status').fadeIn();
}

function hideStatus() {
hideTimer = 0;
$('#status').fadeOut();
}

hideTimoutID = 0;
function showStatusAndHideAfterFiveSecs(msg) {
showStatus(msg);
if (hideTimoutID) {clearTimeout(hideTimoutID);}
hideTimoutID = setTimeout(hideStatus, 5000);
}

</script>
</body>
</html>
82 changes: 82 additions & 0 deletions salmon-playground/rawsignatures.py
@@ -0,0 +1,82 @@
#!/usr/bin/env python
#
# Copyright 2009 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Test out low level signature API."""

import imports

import logging
import random
import datetime
import wsgiref.handlers
import dumper
import cgi
import sys

from string import strip

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import login_required
from google.appengine.ext.webapp import template
from google.appengine.ext import db
from google.appengine.api import users
import feedparser
import userdb

import magicsig.magicsigalg as magicsigalg

from utils import *
import base64

class RawSignaturesHandler(webapp.RequestHandler):
"""Handles request to sign a string with a test keypair.
"""

signing_key = ('RSA.mVgY8RN6URBTstndvmUUPb4UZTdwvwmddSKE5z_jvKUEK6yk1'
'u3rrC9yN8k6FilGj9K0eeUPe2hf4Pj-5CmHww=='
'.AQAB'
'.Lgy_yL3hsLBngkFdDw1Jy9TmSRMiH6yihYetQ8jy-jZXdsZXd8V5'
'ub3kuBHHk4M39i3TduIkcrjcsiWQb77D8Q==')

@aclRequired
def get(self):
"""Handles initial display of page."""
data = dict()
logging.info('Raw signatures')
self.response.out.write(template.render('rawsignatures.html', data))
self.response.set_status(200)

@aclRequired
def post(self):
"""Handles posting back of data and returns a result via XHR.
Just for demo purposes. Accepts a string as data.
"""

data = self.request.get('data')
if data:
logging.info('posted raw string = [%s]', data)
sig = magicsigalg.SignatureAlgRsaSha256(self.signing_key).Sign(data)

logging.info('resulting signature: [%s]', sig)

self.response.set_status(200) # The default
self.response.out.write('Signed [%s]\n' % data)
self.response.out.write('With key [%s]\n' % self.signing_key)
self.response.out.write('Yielding signature [%s]\n' % sig)
else:
self.response.set_status(400)

0 comments on commit 5bb21f8

Please sign in to comment.