Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Replace this comment with the content of https://tweetnacl.js.org/nacl.min.js
- // Replace this comment with the content of https://tweetnacl.js.org/nacl-util.min.js
- +function() {
- function traverseHtml(node, v) {
- if (node.nodeType == 3) {
- v.ontext(node.textContent);
- } else {
- var tagName = node.tagName.toLowerCase();
- v.onopentag(tagName, node);
- for (var i = 0; i < node.childNodes.length; ++i) {
- traverseHtml(node.childNodes[i], v);
- }
- v.onclosetag(tagName);
- }
- }
- function reverseFormatNode(node) {
- let chunks = [];
- function append(str) {
- chunks.push(str);
- }
- let eolStack = [];
- let spanStack = [];
- traverseHtml(node, {
- onopentag: function(tagName, node) {
- if (tagName === 'span' && node.className === 'heading') {
- append("==");
- eolStack.unshift("==");
- } else if (tagName === 'span' && node.className === 'spoiler') {
- append("**");
- spanStack.push("**")
- } else if (tagName === 'em') {
- append("''");
- } else if (tagName === 'strong') {
- append("'''");
- } else if (tagName === 'u') {
- append("__");
- } else if (tagName === 's') {
- append("~~");
- }
- },
- onclosetag: function(tagName) {
- if (tagName === 'p') {
- for (var i = 0; i < eolStack.length; ++i) {
- append(eolStack[i]);
- }
- eolStack = [];
- append("\n");
- } else if (tagName === 'span') {
- append(spanStack.pop());
- } else if (tagName === 'em') {
- append("''");
- } else if (tagName === 'strong') {
- append("'''");
- } else if (tagName === 'u') {
- append("__");
- } else if (tagName === 's') {
- append("~~");
- }
- },
- ontext: function (text) {
- text = text.replace(/—/g, '---');
- text = text.replace(/–/g, '--');
- append(text);
- },
- });
- return chunks.join('');
- }
- function getThread() {
- var ps = document.location.pathname.split('/');
- var opNode = document.querySelector('.post .body');
- var opHash = nacl.util.encodeBase64(nacl.hash(nacl.util.decodeUTF8(reverseFormatNode(opNode))));
- var board = ps[1];
- var threadId = ps[3].split('.')[0];
- return {board: board, id: threadId, opHash: opHash};
- }
- function encodeMessage(thread, ts, msg) {
- var text = [
- "Board: " + thread.board,
- "ThreadId: " + thread.id,
- "OP: " + thread.opHash,
- "TS: " + ts,
- msg
- ].join('\n');
- console.log(text);
- return nacl.util.decodeUTF8(text);
- }
- function checkPost(thread, node) {
- var ranges = [], range, msg;
- var cs = node.childNodes;
- for (var i = 0; i < cs.length; ++i) {
- var line = reverseFormatNode(cs[i]);
- if (range) {
- md = /^\*\*END SIG ([0-9A-Za-z+/]+=*)\*\*/.exec(line);
- if (md) {
- range.last = i;
- range.sig = md[1];
- range.msg = msg;
- ranges.push(range);
- range = undefined;
- } else {
- msg.push(line);
- }
- } else {
- md = /^\*\*BEGIN SIG ([0-9]+) ([0-9A-Za-z+/]+=*)\*\*/.exec(line);
- if (md) {
- range = {first: i, ts: md[1], pub: md[2]};
- msg = [];
- }
- }
- }
- for (var i = ranges.length - 1; i >= 0; i--) {
- var range = ranges[i];
- var text = encodeMessage(thread, range.ts, range.msg.join(''));
- var sigOk = nacl.sign.detached.verify(
- text,
- nacl.util.decodeBase64(range.sig),
- nacl.util.decodeBase64(range.pub));
- // Remove the END line
- node.removeChild(cs[range.last]);
- // Replace the BEGIN line with a DIV
- var div = document.createElement("div");
- if (sigOk) {
- div.className = "signed-message signature-good";
- $(div).append("<p class='body-line ltr'>Good signature by <span class='public-key'>"
- + range.pub + "</span></p>");
- } else {
- div.className = "signed-message signature-bad";
- $(div).append("<p class='body-line ltr'>Signature could not be verified.</p>");
- }
- node.replaceChild(div, cs[range.first]);
- // Move the message lines into the DIV
- for (var j = range.first + 1; j < range.last; j++) {
- div.appendChild(cs[range.first + 1]);
- }
- }
- }
- function checkSignatures() {
- var thread = getThread();
- $('.post .body').each(function (i, el) { checkPost(thread, el); });
- }
- function signPostBody() {
- var ts = new Date().getTime().toString();
- var msg = $('#body').val() + "\n";
- var text = encodeMessage(getThread(), ts, msg);
- var sig = nacl.util.encodeBase64(nacl.sign.detached(text, nacl.util.decodeBase64(window.localStorage.secretKey)));
- $('#body').val(`**BEGIN SIG ${ts} ${window.localStorage.publicKey}**\n${msg}**END SIG ${sig}**\n`);
- }
- $(function(){
- if (!window.localStorage.secretKey) {
- var keys = nacl.sign.keyPair();
- window.localStorage.secretKey = nacl.util.encodeBase64(keys.secretKey);
- window.localStorage.publicKey = nacl.util.encodeBase64(keys.publicKey);
- }
- $(document.head).append(`<style>
- .signed-message { padding: 2px; }
- .signed-message.signature-good { border: 2px solid green; }
- .signed-message.signature-bad { border: 2px solid red; }
- span.public-key { font-family: monospace; font-size: 80%; color: #181; }
- </style>`);
- $('#post-form-inner tr:nth(2) td').append('<input id="sign-button" accesskey="i" style="margin-left:2px;" type="button" name="sign" value="Sign">');
- $('#sign-button').on('click', signPostBody);
- $(document).on('new_post', checkSignatures);
- checkSignatures();
- });
- }();
Advertisement
Add Comment
Please, Sign In to add comment