Difference between revisions of "Team:Groningen/Coding"

Line 6: Line 6:
 
<!-- <link rel="stylesheet" type="text/css" href="reset.css" /> -->
 
<!-- <link rel="stylesheet" type="text/css" href="reset.css" /> -->
 
<style>
 
<style>
body{
+
#container{
font-family: sans-serif;
+
display: flex;
font-size: 13pt;
+
flex-flow: row wrap;
line-height: 1.5em;
+
align-items: center;
padding: 0.5em;
+
justify-content: space-between;
margin: 0;
+
 
}
 
}
body,textarea,a{
+
#container > div{
background-color: #222;
+
position: relative;
color: #EEE;
+
margin-right: 5px;
 
}
 
}
textarea,code{
+
#container > div:last-child{
font-family: monospace;
+
margin-right: 0px;
font-size: 12pt;
+
line-height: 1.5em;
+
}
+
textarea{
+
border: 1px solid #444;
+
width: 99%;
+
}
+
h1{
+
font-size: 1.2em;
+
 
}
 
}
 
 
#container{
+
.cnt-desc{
overflow: auto;
+
flex: 1;
width: 100%;
+
margin: 0;
+
padding: 0;
+
 
}
 
}
#sec-left{
+
#cnt-message{
padding: 5px;
+
flex: 4;
width: 58.5%;
+
float: left;
+
 
}
 
}
#sec-right{
+
#cnt-key{
padding: 5px;
+
flex: 2;
width: 38.5%;
+
float: right;
+
 
}
 
}
 
 
#err{
+
textarea{
color: #FF3333;
+
width: 100%;
}
+
height: 6em;
+
.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>
 
</style>
 
</head>
 
</head>
 
<body>
 
<body>
 +
<h1>Encryption</h1>
 +
 +
<hr />
 +
 
<div id="container">
 
<div id="container">
<h1>SpyGEM coding &amp; crypting</h1>
+
<div id="cnt-desc-message" class="cnt-desc">
<hr class="clearfx" />
+
Enter the message you want to secure here
<div id="sec-left">
+
<p><div>
+
<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><button id="stage">Do something</button></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>
<div id="sec-right">
+
<div id="cnt-message">
<p>This page demonstrates the encoding and decoding of text messages
+
<h2>Message</h2>
into DNA, optionally with AES-256 encryption.</p>
+
<p>Enter a message into the Message field to have it encoded, or
+
<textarea id="msg">Hello world</textarea>
enter an encoded message into the Encoded field to have it decoded.
+
</div>
The Key field is used for encryption &amp; decryption and the
+
<div id="cnt-key">
Formatted field shows more details about the message block.</p>
+
<h2>Key</h2>
<p>To counter restriction enzymes a sequence of 'A'-bases is
+
inserted whereever the sequence for a restriction-enzyme occurs.
+
<textarea id="key">secret</textarea>
When decoding the message these sequences are removed. The length
+
</div>
of the substitution sequence is the shortest sequence of
+
<div id="cnt-desc-key" class="cnt-desc">
'A' that does not occur in the encoded message.</p>
+
Enter your secret key/password here
<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>
 
</div>
<div class="clear"></div>
+
 +
<p>
 +
<button id="stage">Transform</button>
 +
</p>
 +
 +
<div id="cnt-transform">
 +
<h2 id="cur">Plain text</h2>
 +
 +
<textarea id="enc"></textarea>
 +
</div>
 +
 
<div>
 
<div>
 
<p>Credits:</p>
 
<p>Credits:</p>
Line 160: Line 104:
 
var elMsg = document.getElementById('msg'),
 
var elMsg = document.getElementById('msg'),
 
elKey = document.getElementById('key'),
 
elKey = document.getElementById('key'),
elFmt = document.getElementById('fmt'),
 
 
elEnc = document.getElementById('enc'),
 
elEnc = document.getElementById('enc'),
 
elErr = document.getElementById('err'),
 
elErr = document.getElementById('err'),
elCrypt = document.getElementById('crypt'),
+
elCur = document.getElementById('cur'),
elCode8 = document.getElementById('code8'),
+
elStage = document.getElementById('stage');
elDoEnc = document.getElementById('doEnc'),
+
elDoDec = document.getElementById('doDec'),
+
elDirs = [elDoEnc, elDoDec],
+
elStage = document.getElementById('stage'),
+
elLen = document.getElementById('len');
+
 
 
 
var subCoding = EightBit, doCrypt = false, lastEdit = elMsg,
 
var subCoding = EightBit, doCrypt = false, lastEdit = elMsg,
 
cryptBits = 256, stages = [
 
cryptBits = 256, stages = [
{name: "Plain text", transform: function(prev){
+
{name: "Plain text", transform: function(prev){ // null
 
return elMsg.value;  
 
return elMsg.value;  
 
}
 
}
 
},
 
},
{name: "Encrypted", transform: function(prev){
+
{name: "Encrypted", transform: function(prev){ // plain msg
 
var key = elKey.value;
 
var key = elKey.value;
 
return Aes.Ctr.encrypt(prev, key, cryptBits);
 
return Aes.Ctr.encrypt(prev, key, cryptBits);
Line 184: Line 122:
 
}
 
}
 
},
 
},
{name: "ASCII", display: function(data){
+
{name: "ASCII", display: function(data){ // crypt msg
 
return data.split('').map(function(c){
 
return data.split('').map(function(c){
 
return c.charCodeAt(0).toString(10).padStart(3, '0');
 
return c.charCodeAt(0).toString(10).padStart(3, '0');
Line 190: Line 128:
 
}
 
}
 
},
 
},
{name: "Binary", display: function(data){
+
{name: "Binary", display: function(data){ // crypt msg
 
return data.split('').map(function(c){
 
return data.split('').map(function(c){
 
return c.charCodeAt(0).toString(2).padStart(8, '0');
 
return c.charCodeAt(0).toString(2).padStart(8, '0');
Line 196: Line 134:
 
}
 
}
 
},
 
},
{name: "DNA", display: function(data){
+
{name: "DNA", transform: function(prev){ // crypt msg
return (EightBit.encodeStr(data).match(/.{1,4}/g) || []).join(' ');
+
return EightBit.encodeStr(prev);
 +
}, display: function(data){
 +
return (data.match(/.{1,4}/g) || []).join(' ');
 +
}
 +
},
 +
{name: "Message", transform: function(prev){ // dna msg
 +
return Message.packDNA(prev);
 
}
 
}
 
}
 
}
Line 225: Line 169:
 
return {idx: idx, data: data, display: disp};
 
return {idx: idx, data: data, display: disp};
 
}
 
}
 
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;*/
 
/*elFmt.value = "Total length:  " + hdr.msg.length +
 
"\nMessage length: " + hdr.data.length;*/
 
}
 
 
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;*/
 
/*elFmt.value = "Total length:  " + hdr.msg.length +
 
"\nMessage length: " + hdr.data.length;*/
 
}
 
 
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 decode(dna, err){
 
if(dna.length < Message.minLength){
 
throw err || new Error("Sequence too short to contain a message");
 
}
 
 
var hdr = null;
 
try{
 
hdr = Message.unpackDNA(dna, 1);
 
}catch(e){
 
hdr = null;
 
if(!err || (e.level > err.level)){
 
err = e;
 
}
 
}
 
 
if(hdr){
 
return hdr;
 
}
 
 
var next = Message.findStart(dna, 1);
 
 
if(next === -1){
 
throw err || new Error("No message head found");
 
}
 
 
return decode(dna.substr(next), err);
 
}
 
 
function updateDec(){
 
var dna = elEnc.value, hdr, msg, key;
 
elMsg.value = '';
 
clearEls();
 
updateDir(elEnc);
 
 
try{
 
hdr = decode(dna, null); //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 updateCrypt(){
 
if(this === elKey) if(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);
 
 
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);
 
 
 
 
elStage.onclick = function(evt){
 
elStage.onclick = function(evt){
 
currentStage = advanceStage(currentStage);
 
currentStage = advanceStage(currentStage);
elFmt.value = currentStage.display;
+
elEnc.value = currentStage.display;
 +
elCur.innerHTML = stages[currentStage.idx].name;
 
currentStage.idx = (currentStage.idx + 1) % stages.length;
 
currentStage.idx = (currentStage.idx + 1) % stages.length;
 
};
 
};
 
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>
 
</script>
 
</body>
 
</body>
 
</html>
 
</html>
 
{{Groningen/footer}}
 
{{Groningen/footer}}

Revision as of 13:06, 26 August 2016

CryptoGE®M
Team
Project
Biology
Computing
Human Practice
Acknowledgements

SpyGEM coding

Encryption


Enter the message you want to secure here

Message

Key

Enter your secret key/password here

Plain text

Oop top