Skip to content

Instantly share code, notes, and snippets.

@saibotsivad
Last active August 29, 2015 14:16
Show Gist options
  • Save saibotsivad/07f280847a6d6ca83a22 to your computer and use it in GitHub Desktop.
Save saibotsivad/07f280847a6d6ca83a22 to your computer and use it in GitHub Desktop.
Cryptographically strong website applications
<!DOCTYPE html>
<html>
<head>
<title>404</title>
</head>
<body>
<h1>404'd!</h1>
</body>
</html>

site.com

list of versions, paired with signatures of versions, e.g.:
{
	version: 7a5179eecc0fe18760ba615f92603372ae3fe302860098a019e15927551fee3b,
	signatures: [
		{
			signer: 60ba615f92603372ae3fe302860098a019e15927551fee3b7a5179eecc0fe187,
			signature: 3372ae3fe302860098a019e15927551fee3b7a5179eecc0fe18760ba615f9260
		}
	]
}

site.com/app/HASH

the site, running at this version

site.com/doc/HASH

any document

When you go to any URL, e.g. "site.com/doc/HASH", you'll get back a text response.

You would need to extract the HASH from the URL, and then hash the text response and verify that the two hashes are identical.

You might want a static header that gives you a single-group regex that will get you the hash, e.g.:

X-Eternal-Site-Regex: "//site.com/(?:doc|app)/(.*)"

So then, you can verify that the document hash is correct, so you can confirm that you have the exact correct document.

So for example, if you had index.html and it looked like:

<!DOCTYPE html>
<head>
	<script src="//site.com/doc/e302860098a019e15927551fee3b7a5179eecc0fe18760ba615f92603372ae3f"></script>
</head>
</html>

You would be able to confirm that JS file you downloaded was exactly the file the index.html wanted.

Then, you would take that index.html file and store it as a collected app, e.g.:

site.com/app/0098a019e15927551fee3b7a5179eecc0fe18760ba615f92603372ae3fe30286

And then the developer could sign that hash, and publish that as a document as well.

Now on your front page, you have a link to the latest app, and you have these proofs:

  • the developers published it at that version, because you have their signatures
  • the app version you request is exactly the version you receive, because you have the hash
  • every source the app uses is exactly the source you receive, because you have those hashes as well
<!DOCTYPE html>
<html>
<head>
<title>home</title>
</head>
<body>
<h1>hello world</h1>
</body>
</html>
var path = require('path')
var fs = require('fs')
var defaultAllowedMimeTypes = [
'application/json',
'application/javascript',
'image/gif',
'image/jpeg',
'image/png',
'image/svg+xml',
'text/css',
'text/html',
'text/plain',
'text/xml',
'text/x-markdown'
]
module.exports = function SimpleServer(options) {
options = options || {}
options.folder = options.folder || './'
options.allowAllCORS = options.allowAllCORS || false
options.allowedMimeTypes = options.allowedMimeTypes || defaultAllowedMimeTypes
options.urlRegex = options.urlRegex || /^\/[a-zA-Z0-9]{64}$/
options.fallbackHtml = options.fallbackHtml || 'index.html'
options.fileNotFoundHtml = options.fileNotFoundHtml || '404.html'
function loadDefaultHtml(response, status, file) {
response.writeHead(status, {
'Content-Type': 'text/html'
})
fs.createReadStream(file).pipe(response)
}
return function simpleServer(request, response) {
if (options.allowAllCORS && request.headers.origin) {
response.setHeader('Access-Control-Allow-Origin', req.headers.origin)
}
var mimeType = options.allowedMimeTypes.indexOf(request.headers.accept) >= 0 ? request.headers.accept : 'text/plain'
if (request.url === '/') {
loadDefaultHtml(response, 200, options.fallbackHtml)
} else {
if (options.urlRegex.test(request.url)) {
var filename = path.join(options.folder, request.url)
fs.stat(filename, function(error, stat) {
if (error) {
loadDefaultHtml(response, 404, options.fileNotFoundHtml)
} else {
response.writeHead(200, {
'Content-Type' : mimeType,
'Content-Length' : stat.size
})
fs.createReadStream(filename).pipe(response)
}
})
} else {
loadDefaultHtml(response, 404, options.fileNotFoundHtml)
}
}
}
return {
start: function startServer() {
server.listen(options.port)
},
stop: function stopServer(cb) {
server.close(cb)
}
}
}
var http = require('http')
var SimpleServer = require('./index')
var simpleServer = new SimpleServer()
http.createServer(simpleServer).listen(8080)
@saibotsivad
Copy link
Author

One issue might be knowing what the doctype of a site.com/doc/HASH is supposed to be.

Technically, the one creating the document could know what it was for, and submit that information as part of the "create document" call. So that, e.g., the one posting the document would say "this is JS", and then whenever requests were made for that document, the X headers would set the type to JS.

Another option might be to say something like site.com/doc/EXT/HASH, so that you could specify what header type to return. This is possibly open to abuse, but in a similar way that you are trusting the site.com/app/HASH, you would be trusting that the developers are calling the correct header file type.

Perhaps a better way is to simply say site.com/doc/HASH/MIME_TYPE, e.g.:

site.com/doc/e302860098a019e15927551fee3b7a5179eecc0fe18760ba615f92603372ae3f/application/javascript

Then you would need to change the other header to something like:

X-Eternal-Site-Regex: "//site.com/(?:doc|app)/([a-zA-Z0-9]{64})"
Content-Type: "application/javascript"

@saibotsivad
Copy link
Author

Also, obviously, you would set the cache on any document to be never-expire.

@saibotsivad
Copy link
Author

To simplify it even more, another thing to do might just be:

site.com/HASH/MIME_TYPE

So that even the app would reference it like:

site.com/e302860098a019e15927551fee3b7a5179eecc0fe18760ba615f92603372ae3f/text/html

@saibotsivad
Copy link
Author

The CORS setup for all domains is something like:

self.server = http.createServer(function (req, res) {
    if (req.headers.origin) {
        res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
    }
    // etc.
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment