initial commit for GitHub
This commit is contained in:
BIN
demo/alpha-arrow.png
Normal file
BIN
demo/alpha-arrow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 669 B |
179
demo/example.css
Normal file
179
demo/example.css
Normal file
@@ -0,0 +1,179 @@
|
||||
* {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
font-family: Arial, Helvetica, FreeSans, sans;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
background: #eee;
|
||||
padding: 5px;
|
||||
margin-bottom: 0.6em;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.header {
|
||||
width: 650px;
|
||||
margin: 0px auto 1em;
|
||||
}
|
||||
|
||||
p+p {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.explanation {
|
||||
color: #555;
|
||||
margin-top: 0.3em;
|
||||
}
|
||||
|
||||
.section+.section, .explanation+.section {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
.hex {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.hex, .base64, #ciphertext {
|
||||
font-family: 'Courier', mono;
|
||||
}
|
||||
|
||||
.wide, textarea {
|
||||
width: 100%;
|
||||
margin: 0px -4px;
|
||||
font-size: inherit;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
textarea+*, .wide+* {
|
||||
margin-top: 0.3em;
|
||||
}
|
||||
|
||||
/* bulk object placement */
|
||||
#theForm {
|
||||
position: relative;
|
||||
width: 940px;
|
||||
margin: 0px auto;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.column {
|
||||
top: 0px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.box {
|
||||
border: 2px solid #999;
|
||||
padding: 7px;
|
||||
margin-bottom: 20px;
|
||||
-moz-border-radius: 7px;
|
||||
-webkit-border-radius: 7px;
|
||||
}
|
||||
|
||||
#cmode { position: absolute; left: 640px; }
|
||||
#ctexts { position: absolute; left: 320px; }
|
||||
|
||||
.floatright {
|
||||
float: right;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
color: #282;
|
||||
}
|
||||
|
||||
a.random, #buttons a { text-decoration: none; }
|
||||
a.random:hover, a.random:focus { text-decoration: underline; }
|
||||
|
||||
h2 {
|
||||
margin: -7px -7px 3px -7px;
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
color: white;
|
||||
background: #999;
|
||||
}
|
||||
|
||||
#pplaintext { border-color: #f65; }
|
||||
#pplaintext h2 { background: #f65; }
|
||||
|
||||
#ppassword { border-color: #4a4; }
|
||||
#ppassword h2 { background: #4a4; }
|
||||
|
||||
#pciphertext { border-color: #78f; }
|
||||
#pciphertext h2 { background: #78f; }
|
||||
|
||||
#buttons { text-align: center; margin-top: -20px; }
|
||||
|
||||
a#doPbkdf2, a#encrypt, a#decrypt {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
height: 43px;
|
||||
padding-top: 20px;
|
||||
width: 50px;
|
||||
background: url('alpha-arrow.png') no-repeat bottom center;
|
||||
vertical-align: middle;
|
||||
border: none;
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.turnDown {
|
||||
display: inline-block;
|
||||
padding-bottom: 3px;
|
||||
-moz-transform: rotate(90deg);
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.turnUp {
|
||||
display: inline-block;
|
||||
padding-bottom: 3px;
|
||||
-moz-transform: rotate(-90deg);
|
||||
-webkit-transform: rotate(-90deg);
|
||||
transform: rotate(-90deg);
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.buttons a.disabled {
|
||||
background-color: #ccc ! important;
|
||||
cursor: inherit ! important;
|
||||
}
|
||||
|
||||
a#encrypt { background-color: #f65; margin-bottom: 2px; }
|
||||
a#encrypt:hover, a#encrypt:focus { background-color: #f76; }
|
||||
a#encrypt:active { background-color: #f87; }
|
||||
|
||||
a#decrypt {
|
||||
height: 36px;
|
||||
padding-top: 27px;
|
||||
background: url('alpha-arrow.png') no-repeat top center;
|
||||
background-color: #78f;
|
||||
margin-top: 2px;
|
||||
}
|
||||
a#decrypt:hover { background-color: #89f; }
|
||||
a#decrypt:focus { background-color: #89f; }
|
||||
a#decrypt:active { background-color: #9af; }
|
||||
|
||||
#ppassword, #pkey, #pmode, #pplaintext, #pciphertext {
|
||||
-moz-border-radius: 7px;
|
||||
-webkit-border-radius: 7px;
|
||||
}
|
||||
input[type='text'], input[type='password'], textarea {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
font-size: inherit;
|
||||
border: 1px solid #444;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
input[type='text']:focus, input[type='password']:focus, textarea:focus {
|
||||
border-color: red;
|
||||
}
|
||||
|
||||
input[type="radio"], input[type="checkbox"] {
|
||||
position: relative;
|
||||
top: 0.15em;
|
||||
margin-right: -0.15em;
|
||||
}
|
||||
153
demo/example.js
Normal file
153
demo/example.js
Normal file
@@ -0,0 +1,153 @@
|
||||
/* keep track of which salts have been used. */
|
||||
var form, usedIvs = {'':1}, usedSalts = {'':1};
|
||||
|
||||
/* enter actions */
|
||||
var enterActions = {
|
||||
password: doPbkdf2,
|
||||
salt: doPbkdf2,
|
||||
iter: doPbkdf2
|
||||
};
|
||||
|
||||
function loaded() {
|
||||
form = new formHandler('theForm', enterActions);
|
||||
form._extendedKey = [];
|
||||
sjcl.random.startCollectors();
|
||||
document.getElementById("password").focus();
|
||||
}
|
||||
|
||||
/* there's probaby a better way to tell the user something, but oh well */
|
||||
function error(x) {
|
||||
alert(x);
|
||||
}
|
||||
|
||||
/* compute PBKDF2 on the password. */
|
||||
function doPbkdf2(decrypting) {
|
||||
var v = form.get(), salt=v.salt, key, hex = sjcl.codec.hex.fromBits, p={},
|
||||
password = v.password;
|
||||
|
||||
p.iter = v.iter;
|
||||
|
||||
if (password.length == 0) {
|
||||
if (decrypting) { error("Can't decrypt: need a password!"); }
|
||||
return;
|
||||
}
|
||||
|
||||
if (salt.length === 0 && decrypting) {
|
||||
error("Can't decrypt: need a salt for PBKDF2!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (decrypting || !v.freshsalt || !usedSalts[v.salt]) {
|
||||
p.salt = v.salt;
|
||||
}
|
||||
|
||||
p = sjcl.misc.cachedPbkdf2(password, p);
|
||||
form._extendedKey = p.key;
|
||||
v.key = p.key.slice(0, v.keysize/32);
|
||||
v.salt = p.salt;
|
||||
|
||||
form.set(v);
|
||||
form.plaintext.el.select();
|
||||
}
|
||||
/* Encrypt a message */
|
||||
function doEncrypt() {
|
||||
var v = form.get(), iv = v.iv, password = v.password, key = v.key, adata = v.adata, aes, plaintext=v.plaintext, rp = {}, ct, p;
|
||||
|
||||
if (plaintext === '' && v.ciphertext.length) { return; }
|
||||
if (key.length == 0 && password.length == 0) {
|
||||
error("need a password or key!");
|
||||
return;
|
||||
}
|
||||
|
||||
p = { adata:v.adata,
|
||||
iter:v.iter,
|
||||
mode:v.mode,
|
||||
ts:parseInt(v.tag),
|
||||
ks:parseInt(v.keysize) };
|
||||
if (!v.freshiv || !usedIvs[v.iv]) { iv:v.iv; }
|
||||
if (!v.freshsalt || !usedSalts[v.salt]) { p.salt = v.salt; }
|
||||
ct = sjcl.encrypt(password || key, plaintext, p, rp).replace(/,/g,",\n");
|
||||
|
||||
v.iv = rp.iv;
|
||||
usedIvs[rp.iv] = 1;
|
||||
if (rp.salt) {
|
||||
v.salt = rp.salt;
|
||||
usedSalts[rp.salt] = 1;
|
||||
}
|
||||
v.key = rp.key;
|
||||
|
||||
if (v.json) {
|
||||
v.ciphertext = ct;
|
||||
v.adata = '';
|
||||
} else {
|
||||
v.ciphertext = ct.match(/ct:"([^"]*)"/)[1]; //"
|
||||
}
|
||||
|
||||
v.plaintext = '';
|
||||
|
||||
form.set(v);
|
||||
form.ciphertext.el.select();
|
||||
}
|
||||
|
||||
/* Decrypt a message */
|
||||
function doDecrypt() {
|
||||
var v = form.get(), iv = v.iv, key = v.key, adata = v.adata, aes, ciphertext=v.ciphertext, rp = {};
|
||||
|
||||
if (ciphertext.length === 0) { return; }
|
||||
if (!v.password && !v.key.length) {
|
||||
error("Can't decrypt: need a password or key!"); return;
|
||||
}
|
||||
|
||||
if (ciphertext.match("{")) {
|
||||
/* it's jsonized */
|
||||
try {
|
||||
v.plaintext = sjcl.decrypt(v.password || v.key, ciphertext, {}, rp);
|
||||
} catch(e) {
|
||||
error("Can't decrypt: "+e);
|
||||
return;
|
||||
}
|
||||
v.mode = rp.mode;
|
||||
v.iv = rp.iv;
|
||||
v.adata = rp.adata;
|
||||
if (v.password) {
|
||||
v.salt = rp.salt;
|
||||
v.iter = rp.iter;
|
||||
v.keysize = rp.ks;
|
||||
v.tag = rp.ts;
|
||||
}
|
||||
v.key = rp.key;
|
||||
v.ciphertext = "";
|
||||
document.getElementById('plaintext').select();
|
||||
} else {
|
||||
/* it's raw */
|
||||
ciphertext = sjcl.codec.base64.toBits(ciphertext);
|
||||
if (iv.length === 0) {
|
||||
error("Can't decrypt: need an IV!"); return;
|
||||
}
|
||||
if (key.length === 0) {
|
||||
if (v.password.length) {
|
||||
doPbkdf2(true);
|
||||
key = v.key;
|
||||
}
|
||||
}
|
||||
aes = new sjcl.cipher.aes(key);
|
||||
|
||||
try {
|
||||
v.plaintext = sjcl.codec.utf8String.fromBits(sjcl.mode[v.mode].decrypt(aes, ciphertext, iv, v.adata, v.tag));
|
||||
v.ciphertext = "";
|
||||
document.getElementById('plaintext').select();
|
||||
} catch (e) {
|
||||
error("Can't decrypt: " + e);
|
||||
}
|
||||
}
|
||||
form.set(v);
|
||||
}
|
||||
|
||||
function extendKey(size) {
|
||||
form.key.set(form._extendedKey.slice(0,size));
|
||||
}
|
||||
|
||||
function randomize(field, words, paranoia) {
|
||||
form[field].set(sjcl.random.randomWords(words, paranoia));
|
||||
if (field == 'salt') { form.key.set([]); }
|
||||
}
|
||||
137
demo/form.js
Normal file
137
demo/form.js
Normal file
@@ -0,0 +1,137 @@
|
||||
/* Hackish form handling system. */
|
||||
function hasClass(e, cl) {
|
||||
return (" "+e.className+" ").match(" "+cl+" ");
|
||||
}
|
||||
|
||||
function stopPropagation(e) {
|
||||
e.preventDefault && e.preventDefault();
|
||||
e.cancelBubble = true;
|
||||
}
|
||||
|
||||
/* proxy for a form object, with appropriate encoder/decoder */
|
||||
function formElement(el) {
|
||||
this.el = el;
|
||||
}
|
||||
formElement.prototype = {
|
||||
get: function() {
|
||||
var el = this.el;
|
||||
if (el.type == "checkbox") {
|
||||
return el.checked;
|
||||
} else if (hasClass(el, "numeric")) {
|
||||
return parseInt(el.value);
|
||||
} else if (hasClass(el, "hex")) {
|
||||
return sjcl.codec.hex.toBits(el.value);
|
||||
} else if (hasClass(el, "base64")) {
|
||||
return sjcl.codec.base64.toBits(el.value);
|
||||
} else {
|
||||
return el.value;
|
||||
}
|
||||
},
|
||||
|
||||
set: function(x) {
|
||||
var el = this.el;
|
||||
if (el.type == "checkbox") {
|
||||
el.checked = x; return;
|
||||
} else if (hasClass(el, "hex")) {
|
||||
if (typeof x !== 'string') {
|
||||
x = sjcl.codec.hex.fromBits(x);
|
||||
}
|
||||
x = x.toUpperCase().replace(/ /g,'').replace(/(.{8})/g, "$1 ").replace(/ $/, '');
|
||||
} else if (hasClass(el, "base64")) {
|
||||
if (typeof x !== 'string') {
|
||||
x = sjcl.codec.base64.fromBits(x);
|
||||
}
|
||||
x = x.replace(/\s/g,'').replace(/(.{32})/g, "$1\n").replace(/\n$/, '');
|
||||
}
|
||||
el.value = x;
|
||||
}
|
||||
}
|
||||
|
||||
function radioGroup(name) {
|
||||
this.name = name;
|
||||
}
|
||||
radioGroup.prototype = {
|
||||
get: function() {
|
||||
var els = document.getElementsByName(this.name), i;
|
||||
for (i=0; i<els.length; i++) {
|
||||
if (els[i].checked) {
|
||||
return els[i].value;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
set: function(x) {
|
||||
var els = document.getElementsByName(this.name), i;
|
||||
for (i=0; i<els.length; i++) {
|
||||
els[i].checked = (els[i].value == x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function formHandler(formName, enterActions) {
|
||||
var i, els = [], tmp, name;
|
||||
this._elNames = [];
|
||||
|
||||
tmp = document.getElementById(formName).getElementsByTagName('input');
|
||||
for (i=0; i<tmp.length; i++) { els.push(tmp[i]); }
|
||||
|
||||
tmp = document.getElementById(formName).getElementsByTagName('textarea');
|
||||
for (i=0; i<tmp.length; i++) { els.push(tmp[i]); }
|
||||
|
||||
for (i=0; i<els.length; i++) {
|
||||
name = els[i].name || els[i].id;
|
||||
|
||||
/* enforce numeric properties of element */
|
||||
els[i].onkeypress = (function(e) {
|
||||
return function(ev) {
|
||||
ev = ev || window.event;
|
||||
var key = ev.keyCode || ev.which,
|
||||
keyst = String.fromCharCode(ev.charCode || ev.keyCode),
|
||||
ente = enterActions[e.name||e.id];
|
||||
|
||||
if (ev.ctrlKey || ev.metaKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
(key == 13) && ente && ente();
|
||||
|
||||
if (hasClass(e, 'numeric') && ev.charCode && !keyst.match(/[0-9]/)) {
|
||||
stopPropagation(ev); return false;
|
||||
} else if (hasClass(e, 'hex') && ev.charCode && !keyst.match(/[0-9a-fA-F ]/)) {
|
||||
stopPropagation(ev); return false;
|
||||
}
|
||||
}
|
||||
})(els[i]);
|
||||
|
||||
if (els[i].type == 'radio') {
|
||||
if (this[name] === undefined) {
|
||||
this[name] = new radioGroup(name);
|
||||
this._elNames.push(name);
|
||||
}
|
||||
} else {
|
||||
/* code to get the value of an element */
|
||||
this[name] = new formElement(els[i]);
|
||||
this._elNames.push(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
formHandler.prototype = {
|
||||
get:function() {
|
||||
var i, out = {}, en = this._elNames;
|
||||
for (i=0; i<en.length; i++) {
|
||||
out[en[i]] = this[en[i]].get();
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
set:function(o) {
|
||||
var i;
|
||||
for (i in o) {
|
||||
if (o.hasOwnProperty(i) && this.hasOwnProperty(i)) {
|
||||
this[i].set(o[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
208
demo/index.html
Normal file
208
demo/index.html
Normal file
@@ -0,0 +1,208 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>SJCL demo</title>
|
||||
<link rel="stylesheet" type="text/css" href="example.css"/>
|
||||
<script type="text/javascript" src="../sjcl.js"></script>
|
||||
<script type="text/javascript" src="form.js"></script>
|
||||
<script type="text/javascript" src="example.js"></script>
|
||||
</head>
|
||||
<body onload="loaded()">
|
||||
<h1>SJCL demo</h1>
|
||||
|
||||
<div class="header">
|
||||
<p>This page is a demo of the Stanford Javascript Crypto Library. To get started, just type in a password in the left pane and a secret message in the middle pane, then click "encrypt". Encryption takes place in your browser and we never see the plaintext.</p>
|
||||
|
||||
<p>SJCL has lots of other options, many of which are shown in the grey boxes.</p>
|
||||
</div>
|
||||
|
||||
<form id="theForm" onsubmit="return false;">
|
||||
<div class="column" id="ckey">
|
||||
<!-- Password and pbkdf2 parameters -->
|
||||
<div class="box" id="ppassword">
|
||||
<h2>Password</h2>
|
||||
<div class="section">
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" class="wide" name="password" id="password" autocomplete="off" tabindex="1"/>
|
||||
<p class="explanation">
|
||||
Choose a strong, random password.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box" id="pkey">
|
||||
<h2>Key Derivation</h2>
|
||||
<div class="section">
|
||||
<div>
|
||||
<label for="salt"">Salt:</label>
|
||||
<a class="random floatright" href="javascript:randomize('salt',2,0)">random</a>
|
||||
</div>
|
||||
<input type="text" id="salt" class="wide hex" autocomplete="off" size="17" maxlength="35"/>
|
||||
<input type="checkbox" name="freshsalt" id="freshsalt" autocomplete="off" checked="checked"/>
|
||||
<label for="freshsalt">Use fresh random salt for each new password</label>
|
||||
<p class="explanation">
|
||||
Salt adds more variability to your key, and prevents attackers
|
||||
from using <a href="http://en.wikipedia.org/wiki/Rainbow_table">rainbow tables</a> to attack it.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<label for="iter">Strengthen by a factor of:</label>
|
||||
<input type="text" name="iter" id="iter" value="1000" class="numeric" size="5" maxlength="5" autocomplete="off"/>
|
||||
<p class="explanation">
|
||||
Strengthening makes it slower to compute the key corresponding to your
|
||||
password. This makes it take much longer for an attacker to guess it.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
Key size:
|
||||
<input type="radio" name="keysize" value="128" id="key128" checked="checked" autocomplete="off" onclick="extendKey(4)"/>
|
||||
<label for="key128">128</label>
|
||||
<input type="radio" name="keysize" value="192" id="key192" autocomplete="off" onclick="extendKey(6)"/>
|
||||
<label for="key192">192</label>
|
||||
<input type="radio" name="keysize" value="256" id="key256" autocomplete="off" onclick="extendKey(8)"/>
|
||||
<label for="key256">256</label>
|
||||
<p class="explanation">
|
||||
128 bits should be secure enough, but you can generate a longer
|
||||
key if you wish.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- cipher key -->
|
||||
<div class="section">
|
||||
<div>
|
||||
<label for="key">Key:</label>
|
||||
<!--
|
||||
<a class="random floatright" href="javascript:randomizeKey()">random</a>
|
||||
-->
|
||||
</div>
|
||||
<textarea id="key" name="key" class="hex" rows="2" autocomplete="off"></textarea>
|
||||
<p class="explanation">
|
||||
This key is computed from your password, salt and strengthening factor. It
|
||||
will be used internally by the cipher. Instead of using a password, you can
|
||||
enter a key here directly. If you do, it should be 32, 48 or 64 hexadecimal
|
||||
digits (128, 192 or 256 bits).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- mode controls -->
|
||||
<div class="column" id="cmode">
|
||||
<div class="box">
|
||||
<h2>Cipher Parameters</h2>
|
||||
<p class="explanation">
|
||||
SJCL encrypts your data with the <a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard"><acronym title="Advanced Encryption Standard">AES</acronym></a> block cipher.
|
||||
</p>
|
||||
<div class="section">
|
||||
Cipher mode:
|
||||
<input type="radio" name="mode" value="ccm" id="ccm" checked="checked" autocomplete="off"/>
|
||||
<label for="ccm"><acronym title="Counter mode with Cipher block chaining Message authentication code">CCM</acronym></label>
|
||||
<input type="radio" name="mode" value="ocb2" id="ocb2" autocomplete="off"/>
|
||||
<label for="ocb2"><acronym title="Offset CodeBook mode, version 2.0">OCB2</acronym></label>
|
||||
<p class="explanation">
|
||||
The cipher mode is a standard for how to use AES and other
|
||||
algorithms to encrypt and authenticate your message.
|
||||
<a href="http://en.wikipedia.org/wiki/OCB_mode">OCB2 mode</a>
|
||||
is slightly faster and has more features, but
|
||||
<a href="http://en.wikipedia.org/wiki/CCM_mode">CCM mode</a> has wider
|
||||
support because it is not patented.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div>
|
||||
<label for="iv">Initialization vector:</label>
|
||||
<a class="random floatright" href="javascript:randomize('iv',4,0)">random</a>
|
||||
</div>
|
||||
<input type="text" name="iv" id="iv" class="wide hex" size="32" maxlength="35" autocomplete="off"/>
|
||||
<input type="checkbox" id="freshiv" autocomplete="off" checked="checked"/>
|
||||
<label for="freshiv">Choose a new random IV for every message.</label>
|
||||
<p class="explanation">
|
||||
The IV needs to be different for every message you send. It adds
|
||||
randomness to your message, so that the same message will look
|
||||
different each time you send it.
|
||||
</p>
|
||||
<p class="explanation">
|
||||
Be careful: CCM mode doesn't use
|
||||
the whole IV, so changing just part of it isn't enough.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
Authentication strength:
|
||||
<input type="radio" name="tag" value="64" id="tag64" autocomplete="off" checked="checked"/>
|
||||
<label for="tag64">64</label>
|
||||
<input type="radio" name="tag" value="96" id="tag96" autocomplete="off"/>
|
||||
<label for="tag96">96</label>
|
||||
<input type="radio" name="tag" value="128" id="tag128" autocomplete="off"/>
|
||||
<label for="tag128">128</label>
|
||||
<p class="explanation">
|
||||
SJCL adds a an authentication tag to your message to make sure
|
||||
nobody changes it. The longer the authentication tag, the harder it is
|
||||
for somebody to change your encrypted message without you noticing. 64
|
||||
bits is probably enough.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<input type="checkbox" name="json" id="json" autocomplete="off" checked="checked"/>
|
||||
<label for="json">Send the parameters and authenticated data along
|
||||
with the message.</label>
|
||||
<p class="explanation">
|
||||
These parameters are required to decrypt your message later. If the
|
||||
person you're sending the message to knows them, you don't need to send
|
||||
them so your message will be shorter.
|
||||
</p>
|
||||
<p class="explanation">
|
||||
Default parameters won't be sent. Your password won't be sent, either.
|
||||
The salt and iv will be encoded in base64 instead of hex, so they'll
|
||||
look different from what's in the box.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column" id="ctexts">
|
||||
<div id="pplaintext" class="box">
|
||||
<h2>Plaintext</h2>
|
||||
<div class="section">
|
||||
<label for="plaintext">Secret message:</label>
|
||||
<textarea id="plaintext" autocomplete="off" rows="5" tabindex="2"></textarea>
|
||||
<div class="explanation">
|
||||
This message will be encrypted, so that nobody can read it or change it
|
||||
without your password.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<label for="adata">Authenticated data:</label>
|
||||
<textarea id="adata" autocomplete="off" tabindex="3"></textarea>
|
||||
<div class="explanation">
|
||||
This auxilliary message isn't secret, but its integrity will be checked
|
||||
along with the integrity of the message.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="buttons">
|
||||
<a href="javascript:doEncrypt()" id="encrypt" tabindex="4"><span class="turnDown">encrypt</span></a>
|
||||
<a href="javascript:doDecrypt()" id="decrypt" tabindex="6"><span class="turnUp">decrypt</span></a>
|
||||
</div>
|
||||
|
||||
<div id="pciphertext" class="box">
|
||||
<h2>Ciphertext</h2>
|
||||
<label for="ciphertext">Ciphertext:</label>
|
||||
<textarea id="ciphertext" autocomplete="off" rows="7" tabindex="5"></textarea>
|
||||
<div class="explanation">
|
||||
Your message, encrypted and authenticated so that nobody can read it
|
||||
or change it without your password.
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user