Difference between revisions of "Team:Groningen/Coding"

(Redirected page to Team:Groningen/Encoding)
 
(39 intermediate revisions by the same user not shown)
Line 1: Line 1:
<!DOCTYPE html>
+
#REDIRECT [[Team:Groningen/Encoding]]
<html>
+
<head>
+
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+
<title>SpyGEM coding</title>
+
<style>
+
body{
+
font-family: sans-serif;
+
font-size: 13pt;
+
line-height: 1.5em;
+
padding: 0.5em;
+
margin: 0;
+
}
+
body,textarea,a{
+
background-color: #222;
+
color: #EEE;
+
}
+
textarea,code{
+
font-family: monospace;
+
font-size: 12pt;
+
line-height: 1.5em;
+
}
+
textarea{
+
border: 1px solid #444;
+
width: 99%;
+
}
+
h1{
+
font-size: 1.2em;
+
}
+
+
#container{
+
overflow: auto;
+
width: 100%;
+
margin: 0;
+
padding: 0;
+
}
+
#sec-left{
+
padding: 5px;
+
width: 58.5%;
+
float: left;
+
}
+
#sec-right{
+
padding: 5px;
+
width: 38.5%;
+
float: right;
+
}
+
+
#err{
+
color: #FF3333;
+
}
+
+
.input{
+
border: 1px solid #EEE;
+
}
+
.strike{
+
text-decoration: line-through;
+
}
+
.vr{
+
border-left: 1px solid #EEE;
+
width: 0;
+
padding: 0;
+
margin: 0;
+
}
+
.clear{
+
clear: both;
+
}
+
</style>
+
</head>
+
<body>
+
<div id="container">
+
<h1>SpyGEM coding &amp; crypting</h1>
+
<hr class="clear" />
+
<div id="sec-left">
+
<p><div><!--Sub-coding:
+
<span>
+
<input class="subcode" type="radio" id="code64" name="subcode" value="64" />
+
<label for="code64">Six-four</label>
+
</span>
+
<span>
+
<input class="subcode" type="radio" id="code8" name="subcode" value="8bit" checked />
+
<label for="code8">8-bit</label>
+
</span>
+
<span>
+
<input class="subcode" type="radio" id="codex4" name="subcode" value="ex4" />
+
<label for="codex4">Ex-four</label>
+
</span>
+
<span class="vr">&#8203;</span>-->
+
<span>
+
<input type="checkbox" id="crypt" />
+
<label for="crypt">Encrypt</label>
+
</span>
+
<span class="vr">&#8203;</span>
+
<span>
+
<input class="dir" type="radio" id="doEnc" name="dir" value="enc" checked />
+
<label for="doEnc">Encode</label>
+
</span>
+
<span>
+
<input class="dir" type="radio" id="doDec" name="dir" value="dec" />
+
<label for="doDec">Decode</label>
+
</span>
+
</div></p>
+
<p><div>Message</div><div><textarea class="input" rows="5" id="msg">Hello world.</textarea></div></p>
+
<p><div>Key</div><div><textarea class="input" rows="5" id="key"></textarea></div></p>
+
<p><div>Formatted</div><textarea rows="5" id="fmt"></textarea></p>
+
<p><div>Encoded</div><div><textarea class="input" rows="5" id="enc"></textarea></div></p>
+
<p><div>Total length: <span id="len"></span> bases</div></p>
+
<p><div id="err"></div></p>
+
</div>
+
<div id="sec-right">
+
<p>This page demonstrates the encoding and decoding of text messages
+
into DNA, optionally with AES-256 encryption.</p>
+
<p>Enter a message into the Message field to have it encoded, or
+
enter an encoded message into the Encoded field to have it decoded.
+
The Key field is used for encryption &amp; decryption and the
+
Formatted field shows more details about the message block.</p>
+
<!--<span class="strike"><p>The encoding uses 6 bits, or 3 bases, per character,
+
so the permitted characters are:</p>
+
<p><ul>
+
<li>digits: <code>'0' - '9'</code>,</li>
+
<li>lower-case letters: <code>'a' - 'z'</code>,</li>
+
<li>upper-case letters: <code>'A' - 'Z'</code>,</li>
+
<li>space: <code>' '</code>, and</li>
+
<li>full-stop: <code>'.'</code>.</li>
+
</ul></p></span>-->
+
<!--<p>Different encodings for the message are possible. Both
+
'Six-four' and 'Ex-four' use 6 bits (3 bases) per character,
+
but are limited in the characters they allow. 'Six-four' allows
+
only upper- and lower-case letters, digits, space and full-stop.
+
'Ex-four' is somewhat experimental and allows more characters
+
(all of ASCII and a few more), but needs 12 bits for some characters,
+
most notably for upper-case.</p>-->
+
<p>To counter restriction enzymes a sequence of 'A'-bases is
+
inserted whereever the sequence for a restriction-enzyme occurs.
+
When decoding the message these sequences are removed. The length
+
of the substitution sequence is the shortest sequence of
+
'A' that does not occur in the encoded message.</p>
+
<p>The encoding requires 4 bases per character.</p>
+
<p>The fully encoded message block is formatted as follows:</p>
+
<p><ol>
+
<li>The letters <code>'Spy'</code>: 3 × 4 bases.</li>
+
<li>Padding: 4 'A' bases.</li>
+
<li>The length of the restriction-substitutes: 8-bit number (4 bases).</li>
+
<li>The length of the encoded message: 16-bit number (8 bases).</li>
+
<li>The checksum of the encoded message: 16-bit number (8 bases).</li>
+
<li>The message: 4 bases per character.</li>
+
<li>The letters <code>'GEM'</code>: 3 × 4 bases.</li>
+
</ol></p>
+
<p>The total overhead is 48 bases and the maximum message
+
length is 65535 characters.</p>
+
<p>Encryption has an additional 8 characters (48 bases) overhead,
+
regardless of key or message length.</p>
+
</div>
+
</div>
+
<div class="clear"></div>
+
<div>
+
<p>Credits:</p>
+
<ul>
+
<li><a href="http://www.movable-type.co.uk/scripts/aes.html">Chris Veness: Javascript implementation of AES</a></li>
+
<li><a href="https://gist.github.com/chitchcock/5112270">'chitchcock': Javascript implementation of CRC16-CCITT</a></li>
+
</ul>
+
</div>
+
+
<script src="crc.js"></script>
+
<script src="dna.js"></script>
+
<script src="eightbit.js"></script>
+
<script src="sixfour.js"></script>
+
<script src="restrict.js"></script>
+
<script src="message.js"></script>
+
<script src="exfour.js"></script>
+
<script src="aes.js"></script>
+
<script src="aes-ctr.js"></script>
+
<script src="splitter.js"></script>
+
<script>
+
if(typeof Array.from !== 'function'){
+
Array.from = function(src){
+
return Array.prototype.slice.call(src);
+
};
+
}
+
 
+
var elMsg = document.getElementById('msg'),
+
elKey = document.getElementById('key'),
+
elFmt = document.getElementById('fmt'),
+
elEnc = document.getElementById('enc'),
+
elErr = document.getElementById('err'),
+
elCrypt = document.getElementById('crypt'),
+
elCode8 = document.getElementById('code8'),
+
elDoEnc = document.getElementById('doEnc'),
+
elDoDec = document.getElementById('doDec'),
+
elDirs = [elDoEnc, elDoDec],
+
elSubs = Array.from(document.getElementsByClassName('subcode')),
+
elLen = document.getElementById('len');
+
+
var subCoding = EightBit, doCrypt = false, lastEdit = elMsg, cryptBits = 256;
+
+
function showEncHdr(hdr, data){
+
elFmt.value = 'Start: Spy = '+hdr.dnaStart+', End: GEM = '+hdr.dnaEnd+
+
'\nSubst:  '+hdr.subst+' = '+hdr.dnaSubst+
+
'\nLength: '+hdr.len+' = '+hdr.dnaLen+
+
'\nCRC16:  '+hdr.crc+' = '+hdr.dnaCrc+'\nData: '+data;
+
}
+
+
function showDecHdr(hdr){
+
elFmt.value = 'Start:  '+hdr.dnaStart+' = Spy, End: '+hdr.dnaEnd+' = GEM'+
+
'\nSubst:  '+hdr.dnaSubst+' = '+hdr.subst+
+
'\nLength: '+hdr.dnaLen+' = '+hdr.len+
+
'\nCRC16:  '+hdr.dnaCrc+' = '+hdr.crc+'\nData: '+hdr.data;
+
}
+
+
function clearEls(){
+
elErr.innerHTML = '';
+
//elMsg.value = '';
+
elFmt.value = '';
+
//elEnc.value = '';
+
}
+
+
function updateEnc(){
+
var msg = elMsg.value, data, key;
+
elEnc.value = '';
+
clearEls();
+
updateDir(elMsg);
+
+
if(doCrypt){
+
key = elKey.value;
+
msg = Aes.Ctr.encrypt(msg, key, cryptBits);
+
}
+
data = subCoding.encodeStr(msg);
+
+
if(data === null){
+
elErr.innerHTML = 'Illegal character in input message';
+
return;
+
}
+
+
var hdr, dna;
+
+
try{
+
hdr = Message.packDNA(data, 1);
+
dna = hdr.msg;
+
}catch(e){
+
elErr.innerHTML = e.message;
+
console.error(e);
+
return;
+
}
+
+
showEncHdr(hdr, data);
+
elEnc.value = dna;
+
elLen.innerHTML = dna.length;
+
}
+
+
function updateDec(){
+
var dna = elEnc.value, hdr, msg, key;
+
elMsg.value = '';
+
clearEls();
+
updateDir(elEnc);
+
+
try{
+
hdr = Message.unpackDNA(dna, 1);
+
msg = subCoding.decodeStr(hdr.data);
+
}catch(e){
+
elErr.innerHTML = e.message;
+
console.error(e);
+
return;
+
}
+
+
if(msg === null){
+
elErr.innerHTML = 'Message data cannot be decoded';
+
return;
+
}
+
+
if(doCrypt){
+
key = elKey.value;
+
msg = Aes.Ctr.decrypt(msg, key, cryptBits);
+
}
+
+
showDecHdr(hdr);
+
elMsg.value = msg;
+
elLen.innerHTML = dna.length;
+
}
+
+
function updateLast(){
+
if(lastEdit === elMsg){
+
updateEnc();
+
}else{
+
updateDec();
+
}
+
}
+
+
function updateSubCode(){
+
if(!this.checked){
+
return;
+
}
+
+
switch(this.value){
+
case '64': subCoding = SixFour; break;
+
case '8bit': subCoding = EightBit; break;
+
case 'ex4': subCoding = ExFour; break;
+
}
+
+
updateLast();
+
}
+
+
function updateCrypt(){
+
if(this === elKey && this.value.length > 0){
+
elCrypt.checked = true;
+
}
+
+
if(elCrypt.checked){
+
doCrypt = true;
+
subCoding = EightBit;
+
}else{
+
doCrypt = false;
+
}
+
+
updateLast();
+
}
+
+
function updateDir(last){
+
if(last){
+
lastEdit = last;
+
+
elDoEnc.checked = last === elMsg;
+
elDoDec.checked = last === elEnc;
+
+
return;
+
}
+
}
+
+
elMsg.onchange = updateEnc;
+
elMsg.onkeyup = updateEnc;
+
+
elEnc.onchange = updateDec;
+
elEnc.onkeyup = updateDec;
+
+
elKey.onchange = updateCrypt.bind(elKey);
+
elKey.onkeyup = updateCrypt.bind(elKey);
+
+
elSubs.forEach(function(el){
+
el.onchange = updateSubCode.bind(el);
+
});
+
elDirs.forEach(function(el){
+
el.onchange = function(){
+
if(!this.checked){
+
return;
+
}
+
+
if(this.value === 'enc'){
+
lastEdit = elMsg;
+
}else{
+
lastEdit = elEnc;
+
}
+
+
updateLast();
+
};
+
});
+
+
elCrypt.onchange = updateCrypt.bind(elCrypt);
+
+
if(window.location.hash.length > 1){
+
var h = window.location.hash;
+
if(h[1] == 'e'){
+
elMsg.value = h.substr(2);
+
updateEnc();
+
}else{
+
elEnc.value = h.substr(2);
+
updateDec();
+
}
+
}else{
+
updateEnc();
+
}
+
</script>
+
</body>
+
</html>
+

Latest revision as of 10:04, 17 October 2016