Skip to content

Instantly share code, notes, and snippets.

@mcordingley
Last active December 24, 2017 17:50
Show Gist options
  • Save mcordingley/8244698fac2143f74b77fa15a68dd4bf to your computer and use it in GitHub Desktop.
Save mcordingley/8244698fac2143f74b77fa15a68dd4bf to your computer and use it in GitHub Desktop.
Message Commitment
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<div class="mx-auto max-width-4">
<h1>Message Commitment</h1>
<p>
This is the digital equivalent of writing something down onto a slip of paper to reveal it later. Your
commitment is your slip of paper and the committed message is what you wrote inside. Just send the
commitment code to someone or post it on social media to lay down your slip of paper. Later, post the
reveal code to reveal what you had written down. With these two codes in hand, anyone may verify that
you revealed what you had committed to reveal.
</p>
<p>
Under the hood, the slip of paper is actually a
<a href="https://en.wikipedia.org/wiki/Cryptographic_hash_function" target="_blank">cryptographic hash</a>
of your message, padded out with some random data to ensure that your message cannot reasonably be
either guessed ahead of time or altered before being revealed. The calculations are done entirely
within your browser, so no one else is in possession of your message until its time comes.
</p>
<div class="clearfix mxn1">
<div class="col col-12 md-col-6 px1">
<h2>Commit to a Message</h2>
<label for="message">Message</label>
<textarea id="message" class="block border-box col-12 mb2" name="message" rows="4"></textarea>
<label for="post_now">Commitment (Post This Now)</label>
<textarea id="post_now" class="block border-box col-12 mb2" name="post_now" rows="4" readonly></textarea>
<label for="post_later">Committed Message (Post This Later)</label>
<textarea id="post_later" class="block border-box col-12 mb2" name="post_later" rows="4" readonly></textarea>
<input type="button" id="commit" class="bg-white block blue border border-blue col-12 mb2 p1 pointer" value="Commit" />
</div>
<div class="col col-12 md-col-6 px1">
<h2>Verify a Committed Message</h2>
<label for="commitment">Commitment</label>
<textarea id="commitment" class="block border-box col-12 mb2" name="commitment" rows="4"></textarea>
<label for="committed_message">Committed Message</label>
<textarea id="committed_message" class="block border-box col-12 mb2" name="committed_message" rows="4"></textarea>
<input type="button" id="verify" class="bg-white block blue border border-blue col-12 mb2 p1 pointer" value="Verify" />
<p id="verification"></p>
</div>
</div>
<p class="text-muted">Disclaimer: This has not been reviewed by a professional cryptographer. Use it at your own risk and for your own fun.</p>
</div>
<script src="./page.js"></script>
</body>
</html>
(function () {
function sha256(str) {
return window.crypto.subtle.digest("SHA-256", new TextEncoder("utf-8").encode(str)).then(function (hash) {
return base64(hash);
});
}
function base64(buffer) {
var binary = '',
bytes = new Uint8Array(buffer),
len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
document.getElementById('commit').addEventListener('click', function () {
var prefixBuffer = new Uint8Array(6),
suffixBuffer = new Uint8Array(33);
window.crypto.getRandomValues(prefixBuffer);
window.crypto.getRandomValues(suffixBuffer);
var message = document.getElementById('message').value.trim(),
prefix = base64(prefixBuffer),
suffix = base64(suffixBuffer),
post_later = prefix + '|' + message + '|' + suffix;
document.getElementById('post_later').value = post_later;
sha256(post_later).then(function (hash) {
document.getElementById('post_now').value = prefix + '|' + hash;
});
});
document.getElementById('verify').addEventListener('click', function () {
var commitment = document.getElementById('commitment').value.trim(),
commitmentPrefix = commitment.substring(0, commitment.indexOf('|')),
committedMessage = document.getElementById('committed_message').value.trim(),
prefix = committedMessage.substring(0, committedMessage.indexOf('|')),
suffix = committedMessage.substring(committedMessage.lastIndexOf('|') + 1);
if (commitmentPrefix !== prefix) {
document.getElementById('verification').innerText = 'Unable to verify committed message.';
return;
}
sha256(committedMessage).then(function (hash) {
var calculated = prefix + '|' + hash;
document.getElementById('verification').innerText = calculated === commitment ?
'Committed message verified.' :
'Unable to verify committed message.';
});
});
document.getElementById('commitment').addEventListener('input', function () {
document.getElementById('verification').innerText = '';
});
document.getElementById('committed_message').addEventListener('input', function () {
document.getElementById('verification').innerText = '';
});
})();
body {
background-color: #fafafa;
color: #212121;
font-family: "Palatino Linotype", Palatino, Palladio, "URW Palladio L", "Book Antiqua", Baskerville, "Bookman Old Style", "Bitstream Charter", "Nimbus Roman No9 L", Garamond, "Apple Garamond", "ITC Garamond Narrow", "New Century Schoolbook", "Century Schoolbook", "Century Schoolbook L", Georgia, serif;
font-size: 18px;
}
h1,
h2,
a,
.blue {
color: #008;
}
a {
text-decoration: none;
}
h1,
h2,
label,
p {
text-shadow: 1px 1px 0 #fff;
}
input,
textarea {
font-family: monospace;
font-size: 16px;
}
.block {
display: block;
}
.clearfix:before,
.clearfix:after {
content: " ";
display: table;
}
.clearfix:after {
clear: both;
}
.max-width-4 {
max-width: 64rem;
}
.border-box {
box-sizing: border-box;
}
.mb2 {
margin-bottom: 1rem;
}
.mxn1 {
margin-left: -.5rem;
margin-right: -.5rem;
}
.mx-auto {
margin-left: auto;
margin-right: auto;
}
.p1 {
padding: .5rem;
}
.px1 {
padding-left: .5rem;
padding-right: .5rem;
}
.col {
box-sizing: border-box;
float: left;
}
.col-12 {
width: 100%;
}
@media (min-width: 52em) {
.md-col-6 {
width: 50%;
}
}
.border {
border-style: solid;
border-width: 1px;
}
.bg-white {
background-color: #fff;
}
.border-blue {
border-color: #008;
}
.text-muted {
color: #888;
}
.pointer {
cursor: pointer;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment