-
ClassDatenowKey2.js
The random number generator://ClassDatenowKey2.js //a permutation class function Perm(n){ this.N=n; this.C=new Uint8Array(n); } Perm.prototype.swap=function(i,j){ var a=0; a=this.C[i]; this.C[i]=this.C[j]; this.C[j]=a; };//end swap //Initialize a random permutation Perm.prototype.createPerm=function(){ var i,j; var k=this.N; E.srand(E.hwRand()); for(j=0;j<this.N;j++)this.C[j]=j; for(i=0;i<(this.N-1);i++){ j=parseInt((Math.random()*256)%k,10); this.swap(i,i+j); k--; }//next i };//end createPerm //Use permutation to relocate bits in E to D //dir determines the indirection direction Perm.prototype.doPerm=function(dir,D,E){ var i,j,k,m; for(i=0;i<this.N/8;i++)D[i]=0; for(i=0;i<this.N;i++){ j=this.C[i]; k=i%8; m=j%8; var a=1; var b=1; a=1<<k; b=1<<m; if(dir){ if(E[(i-k)/8]&a) D[(j-m)/8]=D[(j-m)/8]|b; }else{ if(E[(j-m)/8]&b) D[(i-k)/8]=D[(i-k)/8]|a; }//end else }//next i };//end doPerm //Use permutation of length N in E to relocate bytes in C to D Perm.prototype.doPermBytes=function(dir,E,C){ var i,j,k,m; for(i=0;i<this.N;i++)D[i]=0; for(i=0;i<this.N;i++){ j=this.C[i]; if(dir){ D[i]=E[j]; }else{ D[j]=E[i]; }//end else }//next i };//end doPermBytes /////////////////////////// //a oneway class function Oneway(){ this.A=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; } Oneway.prototype.oneway1=function(mode,A,B,C,D,E){ switch(mode){ case 0: return A+B+C+D+E; case 1: return A^B^C^D^E; case 2: return A*B*C*D*E; }//end switch };//end oneway1 Oneway.prototype.modit=function(A){ for(var i=0;i<16;i++)A[i]=this.A[i]%256; };//end modit Oneway.prototype.fillit=function(b){ for(var i=0;i<16;i++)this.A[i]=b; };//end fillit Oneway.prototype.oneway=function(mode,B){ var oneway1=this.oneway1; //rows this.A[0]=oneway1(mode,this.A[0],B[0],B[1],B[2],B[3]); this.A[1]=oneway1(mode,this.A[1],B[4],B[5],B[6],B[7]); this.A[2]=oneway1(mode,this.A[2],B[8],B[9],B[10],B[11]); this.A[3]=oneway1(mode,this.A[3],B[12],B[13],B[14],B[15]); //columns this.A[4]=oneway1(mode,this.A[4],B[0],B[4],B[8],B[12]); this.A[5]=oneway1(mode,this.A[5],B[1],B[5],B[9],B[13]); this.A[6]=oneway1(mode,this.A[6],B[2],B[6],B[10],B[14]); this.A[7]=oneway1(mode,this.A[7],B[3],B[7],B[11],B[15]); //diagonals\ this.A[8]=oneway1(mode,this.A[8],B[0],B[5],B[10],B[15]); this.A[9]=oneway1(mode,this.A[9],B[1],B[6],B[11],B[12]); this.A[10]=oneway1(mode,this.A[10],B[2],B[7],B[8],B[13]); this.A[11]=oneway1(mode,this.A[11],B[3],B[4],B[9],B[14]); //diagonals/ this.A[12]=oneway1(mode,this.A[12],B[3],B[6],B[9],B[12]); this.A[13]=oneway1(mode,this.A[13],B[0],B[7],B[10],B[13]); this.A[14]=oneway1(mode,this.A[14],B[1],B[4],B[11],B[14]); this.A[15]=oneway1(mode,this.A[15],B[2],B[5],B[8],B[15]); };//end oneway // Random object // aes1 0= encrypt, 1=decrypt // aes2 0= encrypt, 1=decrypt // pdir1 permutation direction 0 or 1 // pdir2 permutation direction 0 or 1 // owtype 0= add, 1= xor, 2=multiply function Random(aes1,aes2,pdir1,pdir2,owtype){ this.AES1=aes1; this.AES2=aes2; this.Pdir1=pdir1; this.Pdir2=pdir2; this.Owtype=owtype; this.ow=new Oneway(); this.plain=new Uint8Array(16); this.R=new ArrayBuffer(16); this.perm1=new Perm(128); this.key1=new Uint8Array(16); this.perm2=new Perm(128); this.key2=new Uint8Array(16); } Random.prototype.random=function(){ var a; var tt=Date.now()*1000000; for(var i=0;i<16;i++){ if(i===8)tt=Date.now()*1000000; this.R[i]=tt%256; tt=tt-this.R[i]; tt=tt/256; }//nexti E.srand(E.hwRand()); this.R[0]=(Math.random()*256)%256; this.R[8]=(Math.random()*256)%256; this.R[15]=(Math.random()*256)%256; // printit(R); this.perm1.doPerm(this.Pdir1,this.plain,this.R); //printit(plain); if(this.AES1){this.R=AES.encrypt(this.plain,this.key1); }else{ this.R=AES.decrypt(this.plain,this.key1); } //printit(this.R); this.ow.fillit(1); this.ow.oneway(this.Owtype,this.R); this.ow.modit(this.R); //printit(this.R); this.perm2.doPerm(this.Pdir2,this.plain,this.R); //printit(plain); if(this.AES2){this.R=AES.encrypt(this.plain,this.key2); }else{ this.R=AES.decrypt(this.plain,this.key2); } //printit(this.R); return this.R; };//end random Random.prototype.setup_random=function(){ for(var i=0;i<16;i++){ E.srand(E.hwRand()); this.key1[i]=parseInt((Math.random()*256),10); E.srand(E.hwRand()); this.key2[i]=parseInt((Math.random()*256),10); }//nexti this.perm1.createPerm(); this.perm2.createPerm(); }; /////////////////////////////// function printit(W){ console.log(W[0]+','+W[1]+','+W[2]+','+W[3]+','+ W[4]+','+W[5]+','+W[6]+','+W[7]+','+ W[8]+','+W[9]+','+W[10]+','+W[11]+','+ W[12]+','+W[13]+','+W[14]+','+W[15] ); }//end printit function copy(A,B){for(var i=0;i<16;i++)A[i]=B[i];} function compare(A,B){ for(var i=0;i<16;i++)if(A[i]!=B[i])return 0; return 1; } /////////////////////////////// // Random object // aes1 0= encrypt, 1=decrypt // aes2 0= encrypt, 1=decrypt // pdir1 permutation direction 0 or 1 // pdir2 permutation direction 0 or 1 // owtype 0= add, 1= xor, 2=multiply //function Random(aes1,aes2,pdir1,pdir2,owtype){ var R=new Random(1,1,0,0,0); R.setup_random(); console.log("keys"); printit(R.key1); printit(R.key2); console.log("Enter go(); into left screen, press enter"); function go(){ R.key1=R.random(); R.key2=R.random(); R.key1=R.random(); R.key2=R.random(); console.log("keys"); printit(R.key1); printit(R.key2); console.log("Randoms"); for(var j=0;j<16;j++){ printit(R.random()); } }//end go
The output:
>echo(0); keys 95,199,130,197,32,174,21,94,190,94,212,0,219,24,220,209 127,253,226,16,70,146,185,11,202,192,44,70,83,51,120,177 Enter go(); into left screen, press enter =undefined >go(); keys 37,115,239,249,173,235,105,20,202,187,119,250,173,235,105,187 194,44,127,205,23,115,36,6,237,95,250,210,33,201,23,211 Randoms 142,254,220,240,136,215,19,239,149,77,77,124,190,204,102,97 172,247,225,194,124,184,176,179,201,85,70,33,145,196,50,223 171,173,84,67,240,166,53,84,189,241,190,160,65,126,46,16 240,110,20,89,34,209,82,26,84,141,66,199,178,107,45,129 8,76,198,85,81,141,148,70,243,37,27,18,101,39,53,75 156,154,240,83,125,40,83,111,48,193,73,90,88,52,152,150 132,58,124,16,109,99,134,187,72,139,84,109,254,5,163,173 18,166,184,35,1,188,74,73,75,24,107,129,229,6,203,35 46,71,178,73,32,142,191,110,254,127,233,195,82,219,214,121 219,68,7,110,28,230,173,64,123,179,128,4,232,61,157,244 26,86,10,201,79,18,159,126,178,165,128,213,0,220,233,219 160,45,66,180,92,106,130,148,224,180,18,141,20,194,197,167 116,187,81,184,197,46,64,197,107,157,58,72,70,42,241,205 106,243,200,96,187,42,68,165,111,85,121,61,150,128,81,63 112,139,103,246,27,71,38,240,100,136,250,230,24,145,76,69 96,130,236,218,128,193,47,234,34,3,10,30,130,18,74,154
-
This covers experiments with the espruino board.
http://forum.espruino.com/conversations/287295/#comment13025302Pins that can connect to the timer circuits can generate PWM without running code other that the setup.
On the Espruino board up to 4 pins are on each timer. One frequency but 4 different duty cycles.
Software is used on the pins that can't connect to timers. A timer circuit is used but the pin toggle is handled by software. -
-
Cryptomsg4.js
Some changes made to the hash function.
Add a logoff function.
Noticed that the Rnum in the messages were all the same value.
Fixed it.>setupID(); IDPW_hash 199,118,61,228,125,51,183,83,209,53,107,248,75,23,162,128 In left pane enter connect(); and press return. =undefined >connect(); { "text": [ new Uint8Array([65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), new Uint8Array(16) ], "Rnum": new Uint8Array([106, 252, 92, 219, 97, 146, 133, 70, 139, 53, 121, 170, 154, 73, 162, 119]), "Auth": new Uint8Array(16), "Mhash": new ArrayBuffer([207, 109, 3, 165, 191, 27, 97, 58, 131, 189, 253, 144, 214, 189, 226, 240]) } Client msg 1 hash OK { "text": [ new Uint8Array([65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), new Uint8Array(16) ], "Rnum": new Uint8Array([224, 101, 186, 153, 117, 133, 224, 12, 118, 39, 165, 92, 202, 210, 183, 51]), "Auth": new ArrayBuffer([66, 169, 179, 113, 114, 202, 57, 74, 89, 29, 96, 192, 147, 30, 236, 36]), "Mhash": new ArrayBuffer([22, 187, 159, 26, 112, 116, 187, 148, 127, 211, 158, 113, 40, 126, 194, 165]) } Server msg1 hash OK Server is authentic Enter User ID and password In the left pane enter ID="<user ID>"; In the left pane enter PW="<password>"; In left pane enter login(); and press return.
A Phat phinger mistake in the copy function.
function copy(A,B){for(var i=0;i<16;i++)A[i]=B[1];}
Changed it to:
function copy(A,B){for(var i=0;i<16;i++)A[i]=B[i];}
-
Onewayx.js
Apply addition, exclusive or, or multiplication to a matrix by rows, columns, left diagonals and right diagonals and then take the modulus 256 to create a one way function.
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15//onewayx.js function oneway1(mode,A,B,C,D,E){ switch(mode){ case 0: return A+B+C+D+E; case 1: return A^B^C^D^E; case 2: return A*B*C*D*E; }//end switch }//end oneway1 function modit(A,B){ for(var i=0;i<16;i++)A[i]=B[i]%256; }//end modit function fillit(A,b){ for(var i=0;i<16;i++)A[i]=b; }//end fillit function oneway(mode,A,B){ //rows A[0]=oneway1(mode,A[0],B[0],B[1],B[2],B[3]); A[1]=oneway1(mode,A[1],B[4],B[5],B[6],B[7]); A[2]=oneway1(mode,A[2],B[8],B[9],B[10],B[11]); A[3]=oneway1(mode,A[3],B[12],B[13],B[14],B[15]); //columns A[4]=oneway1(mode,A[4],B[0],B[4],B[8],B[12]); A[5]=oneway1(mode,A[5],B[1],B[5],B[9],B[13]); A[6]=oneway1(mode,A[6],B[2],B[6],B[10],B[14]); A[7]=oneway1(mode,A[7],B[3],B[7],B[11],B[15]); //diagonals\ A[8]=oneway1(mode,A[8],B[0],B[5],B[10],B[15]); A[9]=oneway1(mode,A[9],B[1],B[6],B[11],B[12]); A[10]=oneway1(mode,A[10],B[2],B[7],B[8],B[13]); A[11]=oneway1(mode,A[11],B[3],B[4],B[9],B[14]); //diagonals/ A[12]=oneway1(mode,A[12],B[3],B[6],B[9],B[12]); A[13]=oneway1(mode,A[13],B[0],B[7],B[10],B[13]); A[14]=oneway1(mode,A[14],B[1],B[4],B[11],B[14]); A[15]=oneway1(mode,A[15],B[2],B[5],B[8],B[15]); }//end oneway
The output:
The inital data 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 use mutltiply Data after applying oneway function and modit 24 144 104 160 73 144 137 0 32 136 208 184 56 208 8 32 Do it again using xor The inital data 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Data after applying oneway function and modit 5 13 5 29 1 1 1 17 29 5 13 5 5 13 5 29 Do it again using addition The inital data 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Data after applying oneway function and modit 11 27 43 59 29 33 37 41 35 35 35 35 35 35 35 35
Try it with different initial data.
-
Permutation2.js
A permutation of bits:0 168 0 1 133 1 2 2 2 3 0 3 4 1 4 5 112 5 6 16 6 7 150 7 8 49 8 9 2 9 10 134 10 11 14 11 12 36 12 13 16 13 14 9 14 15 4 15
A permutation of bytes
0 6 0 1 1 1 2 14 2 3 12 3 4 15 4 5 4 5 6 7 6 7 10 7 8 13 8 9 2 9 10 5 10 11 0 11 12 11 12 13 9 13 14 3 14 15 8 15
Links:
http://www.scientificamerican.com/article/nsa-nist-encryption-scandal/https://cpunks.org/pipermail/cypherpunks/2013-September/000984.html
https://www.schneier.com/blog/archives/2013/10/defending_again_1.html
-
Cryptomsg3.js
In this version a user ID and password have been added
The following is the output of one session. The setup function creates the cryptographic keys used in the client and server objects. Note that client and server have different random number keys and permutations. None of the permutation arrays are shown.PICO 1v86 >echo(0); In left pane enter setup(); and press return. =undefined >setup(); Client Random # keys 147,218,39,254,251,124,105,20,249,242,176,254,251,124,105,138 124,171,219,12,155,172,248,197,93,220,85,14,86,211,101,122 Msg Hash keys 183,198,0,48,252,124,105,20,27,113,129,48,252,124,105,170 232,149,224,242,228,159,142,123,127,115,23,205,73,51,112,58 Auth Hash keys 82,25,235,120,252,124,105,20,163,183,112,121,252,124,105,248 90,33,23,232,223,50,115,84,170,190,44,139,113,153,65,249 IDPW Hash keys 179,197,74,194,252,124,105,20,240,89,206,194,252,124,105,142 23,120,142,240,228,46,156,128,54,32,224,158,21,49,50,162 IDPWkey Hash keys 254,143,24,11,253,124,105,20,217,234,155,11,253,124,105,49 255,224,2,245,157,160,44,204,179,206,10,57,236,82,67,23 Server Random # keys 53,87,29,162,253,124,105,20,95,37,162,162,253,124,105,26 78,233,136,63,69,30,248,93,255,66,4,177,179,192,75,192 To setup a User ID and password In the left pane enter ID="<user ID>"; In the left pane enter PW="<password>"; In left pane enter setupID(); and press return. =undefined
The setupID() function performs a hash of the ID and Password and stores it in the server object for later reference.
>ID="sam" ="sam" >PW="a1234"; ="a1234" >setupID(); IDPW_hash 20,198,57,30,198,43,156,233,212,6,187,246,210,28,110,194 In left pane enter connect(); and press return. =undefined
The setup process is completed at this point.
The connect() function sends a command from the client to the server. The message in the text, a random number Rnum, and a MHash of the text and Rnum blocks.
The server calculated the hash1 of the text and Rnum blocks of the received message and performs a comparison.
The server creates a reply message.>connect(); { "text": [ new Uint8Array([65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107]), "Auth": new Uint8Array(16), "Mhash": new ArrayBuffer([67, 224, 209, 99, 57, 134, 239, 227, 82, 141, 121, 73, 1, 34, 87, 53]) } Client msg 1 hash OK
The server creates a reply.
It generates a new random number Rnum.
It calculates the Auth value by hashing the Rnum in the clients message
It calculates the MHash of the text, Rnum, and Auth blocks.{ "text": [ new Uint8Array([65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95]), "Auth": new ArrayBuffer([177, 4, 182, 80, 32, 193, 133, 253, 206, 70, 222, 40, 50, 103, 253, 84]), "Mhash": new ArrayBuffer([174, 166, 145, 239, 250, 142, 29, 89, 132, 47, 94, 235, 3, 148, 16, 180]) }
The client validates the Mhash, and the Auth and asked the user for ID and password.
Server msg1 hash OK Server is authentic Enter User ID and password In the left pane enter ID="<user ID>"; In the left pane enter PW="<password>"; In left pane enter login(); and press return. =undefined >
The user enters the ID and password and the client sends a message to the server using the login() function.
The message contains the text[0] block with the command, the text[1] block, a Rnum random number block, the Auth block and a Mhash of both text blocks, the Rnum and Auth blocks.
An encryption key is created using a hash of the Rnum in the last server message.
The encryption key is used to encrypt the hash of the ID and password.
Text[1]= the permutation of the encrypted hash of ID and password.
Note: the permutation uses an array of 128 values to swap bits in the block thus increasing the difficulty level for a hacker.>ID ="sam" >PW ="a1234" >login(); { "text": [ new Uint8Array([66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), new ArrayBuffer([188, 251, 96, 214, 196, 152, 12, 153, 116, 62, 142, 67, 36, 191, 9, 37]) ], "Rnum": new Uint8Array([231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231]), "Auth": new ArrayBuffer([85, 202, 193, 237, 229, 82, 213, 28, 17, 66, 76, 168, 105, 110, 34, 181]), "Mhash": new ArrayBuffer([246, 246, 153, 109, 110, 234, 46, 198, 250, 173, 197, 70, 46, 130, 198, 8]) } Client msg 2 hash OK Client is authentic User ID and password valid
The server validates the Mhash, and the Auth blocks.
The server reverses the permutation and decrypts the text[1] block and uses the previously saved IDPW hash to validate the user ID and password.
The server replies as follows:{ "text": [ new Uint8Array([66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197]), "Auth": new ArrayBuffer([203, 178, 225, 223, 185, 157, 208, 10, 205, 106, 25, 48, 148, 14, 178, 244]), "Mhash": new ArrayBuffer([136, 235, 215, 192, 46, 125, 93, 102, 232, 66, 154, 94, 254, 96, 125, 171]) }
The client validates the Mhash, and the Auth blocks.
Server msg1 hash OK Server is authentic In left pane enter replay(); or LEDon(); or LEDoff(); and press return. =undefined >
The user enters LEDon() and the client sends a message with text[0][1]=153
>LEDon(); { "text": [ new Uint8Array([67, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245]), "Auth": new ArrayBuffer([84, 61, 229, 17, 188, 93, 153, 84, 8, 11, 141, 163, 234, 109, 215, 22]), "Mhash": new ArrayBuffer([161, 191, 122, 233, 14, 1, 107, 240, 101, 7, 97, 214, 109, 87, 47, 227]) }
The server validates the Mhash and Auth blocks and uses the value on text[0][1] to turn the Green LED on the PICO on or off.
Client msg 3 hash OK Client is authentic { "text": [ new Uint8Array([67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]), "Auth": new ArrayBuffer([25, 138, 122, 203, 160, 27, 197, 203, 83, 67, 94, 253, 166, 101, 177, 61]), "Mhash": new ArrayBuffer([156, 67, 30, 184, 3, 5, 237, 23, 4, 169, 138, 33, 245, 137, 166, 242]) } Server msg hash OK Server is authentic In left pane enter replay(); or LEDon(); or LEDoff(); and press return. =undefined
The user enters LEDoff(), and the client sends the following message to the server.
>LEDoff(); { "text": [ new Uint8Array([67, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32]), "Auth": new ArrayBuffer([173, 227, 7, 74, 231, 212, 57, 149, 211, 167, 182, 168, 50, 163, 100, 136]), "Mhash": new ArrayBuffer([166, 234, 76, 46, 39, 225, 249, 161, 72, 87, 168, 112, 131, 189, 17, 179]) } Client msg 3 hash OK Client is authentic
The server turns the LED off and replies as follows.
{ "text": [ new Uint8Array([67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91]), "Auth": new ArrayBuffer([69, 156, 77, 140, 124, 163, 20, 171, 113, 5, 219, 192, 52, 186, 236, 247]), "Mhash": new ArrayBuffer([58, 187, 167, 69, 103, 61, 35, 28, 56, 158, 186, 83, 30, 230, 152, 10]) } Server msg hash OK Server is authentic In left pane enter replay(); or LEDon(); or LEDoff(); and press return.
Along the way the client and server messages have been saved by Bill the black hat hacker. So Bill tries sending the client’s messages to the server with the following results.
>replay(); Trying to replay Client msg 1 hash OK Client msg 2 hash OK Client not authentic ((the calculated and message Auth values are shown here)) 73,37,138,217,81,69,32,247,92,136,225,154,124,8,83,157 85,202,193,237,229,82,213,28,17,66,76,168,105,110,34,181 =undefined
Try it and have the client enter the wrong ID or password.
The random number generator uses Date.now, and Math.random() as a seed.
A permutation followed by encryption or decryption is applied to the seed.
A one way matrix operation is applied followed by a second permutation and finally a second encryption or decryption. Again this makes life hard for hackers as compared to a simple counter applied to the AES algorithm.
The hash function does a similar process permutation1, encrypt, one way, permutation2, encrypt. For the first block the one way is initialized. For subsequent blocks the one way uses the results from the previous block. -
The output of Cryptomsg2.js
>echo(0); In left pane enter go(); and press return. =undefined >go(); Client Random # keys 245,23,232,200,114,36,105,20,254,96,85,201,114,36,105,4 69,150,99,34,208,230,34,168,128,106,45,199,203,46,28,219 Hash keys 232,65,134,243,114,36,105,20,195,103,245,243,114,36,105,1 188,177,5,173,141,150,119,10,10,7,153,174,225,238,77,145 Hash keys 242,148,162,50,115,36,105,20,180,39,16,51,115,36,105,250 217,67,207,60,54,115,75,227,116,255,243,203,112,230,97,82 Server Random # keys 217,1,45,181,115,36,105,20,79,84,156,181,115,36,105,203 215,180,29,227,242,69,139,118,47,238,145,221,141,226,213,38 { "text": [ new Uint8Array([65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94]), "Auth": new Uint8Array(16), "Mhash": new ArrayBuffer([26, 16, 180, 124, 63, 107, 133, 33, 128, 52, 101, 195, 208, 190, 102, 93]) } Client msg 1 hash OK { "text": [ new Uint8Array([65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60]), "Auth": new ArrayBuffer([3, 170, 20, 135, 37, 121, 216, 99, 141, 128, 79, 223, 167, 46, 246, 123]), "Mhash": new ArrayBuffer([99, 179, 42, 101, 76, 3, 51, 218, 226, 53, 95, 70, 171, 105, 83, 175]) } Server msg1 hash OK Server is authentic { "text": [ new Uint8Array([66, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), "Auth": new ArrayBuffer([34, 224, 5, 131, 161, 65, 136, 88, 134, 75, 54, 238, 99, 203, 160, 179]), "Mhash": new ArrayBuffer([61, 176, 71, 104, 148, 148, 164, 97, 70, 194, 169, 104, 156, 182, 148, 76]) } Client msg 2 hash OK Client is authentic { "text": [ new Uint8Array([66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34]), "Auth": new ArrayBuffer([3, 170, 20, 135, 37, 121, 216, 99, 141, 128, 79, 223, 167, 46, 246, 123]), "Mhash": new ArrayBuffer([74, 248, 250, 163, 194, 76, 103, 238, 169, 3, 248, 117, 159, 233, 64, 220]) } Trying to replay Client msg 1 hash OK Client msg 2 hash OK Client not authentic 167,33,148,163,150,43,129,28,79,255,93,113,35,215,40,72 34,224,5,131,161,65,136,88,134,75,54,238,99,203,160,179 New messages { "text": [ new Uint8Array([65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119]), "Auth": new Uint8Array(16), "Mhash": new ArrayBuffer([79, 10, 74, 218, 32, 96, 55, 0, 116, 245, 80, 95, 54, 76, 54, 114]) } Client msg 1 hash OK { "text": [ new Uint8Array([65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248]), "Auth": new ArrayBuffer([241, 254, 62, 248, 237, 77, 127, 26, 115, 224, 51, 144, 124, 210, 7, 250]), "Mhash": new ArrayBuffer([93, 70, 18, 33, 28, 195, 215, 238, 123, 48, 146, 157, 176, 143, 82, 131]) } Server msg1 hash OK Server is authentic { "text": [ new Uint8Array([66, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]), "Auth": new ArrayBuffer([168, 38, 120, 193, 88, 64, 50, 150, 39, 150, 95, 251, 65, 68, 138, 66]), "Mhash": new ArrayBuffer([184, 131, 13, 136, 192, 234, 14, 184, 72, 113, 231, 145, 199, 149, 231, 150]) } Client msg 2 hash OK Client is authentic { "text": [ new Uint8Array([66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ], "Rnum": new Uint8Array([248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248]), "Auth": new ArrayBuffer([241, 254, 62, 248, 237, 77, 127, 26, 115, 224, 51, 144, 124, 210, 7, 250]), "Mhash": new ArrayBuffer([143, 19, 133, 234, 45, 4, 48, 57, 126, 126, 176, 205, 243, 97, 8, 8]) } =0
-
Bob and Sally communicate over an open channel and Bill can listen in. (the messages are sent as plaintext)
Bob and Sally use the following scheme using cryptographic algorithms, one-way functions, keys, and permutations.
Sally sends the following message S1:
“Hi I’m Sally are you Bob”
Sally adds a 16 byte random number A and a ‘hash’ of the message +random number.
Bill records the message.
Bob receives the message S1, computes the ‘hash’ and compares the computed ‘hash’ to the received ‘hash’.
If the ‘hashes’ are equal, Bob sends the reply comprised of
The message B1:
“Yes I am Bob, are you sure you are Sally”,
A 16 byte random number B,
A 16 byte value C computed from A using a cryptographic function, keys and permutations, and
A 16 byte ‘hash’ of the message +random number B +C
Bill records this message.
Sally receives the message B1 computes and compares the ‘hash’ with the sent ‘hash’
If the ‘hashes’ are equal,
Sally computes C from A and compares the results with sent value of C
If the computed value of C equals the sent value of C then Sally has authenticated Bob.
Sally then sends the following:
The message S2:
“Bob transfer big bucks to my account and turn on the LED”,
A 16 byte random number D
A 16 byte value E computed from B using a cryptographic function, keys and permutations, and
A 16 byte ‘hash’ of the message +random number D +E.
Bill records the message.
Bob receives the message S2 computes and compares the ‘hash’ with the sent ‘hash’
If the ‘hashes’ are equal,
Bob computes E from B and compares the results with sent value of E
If the computed value of E equals the sent value of E then Bob has authenticated Sally.
Bob transfers the big buck and turns on the LED
The message exchange continues until one party terminates the session. Each message contains the message, random number, computed value, and ‘hash’.
Time passes:
Bill connects to Bob and replays the messages sent by Sally.
Will Bob transfer the funds and turn on the LED?
Bob will receive message S1 and it will validate and Bob will reply with a modified message B1 with a different random number B and ‘hash’.
Sally doesn’t receive the message. Bill sends recorded message S2.
Bob doesn’t validate the message because the sent E not equal to the computed E.
Could Bill modify the message? Not without knowing the ‘hash’ algorithm and keys.
If Bill can catch Sally’s messages to Bob, can Bill modify Sally’s message before sending it to Bob? Not without knowing the ‘hash’ algorithm and keys.
Do Bob and Sally really authenticate each other or do their computers authenticate each other?
If Bill steals Sally’s computer could he cause Bob to transfer funds and turn on the LED? How could this be prevented?
Implementation on a PICO is in the attached file. Both client and server are present as I don’t have the WIFI shim. It’s a test of the idea.
To add a user ID and password consider the following:
A user ID, and a password.
Define the cryptographic parameters of a password hash and compute the password hash. The client operator enters the password and the password hash is calculated.
The password hash is maintained in the server and index to the user ID.
Derive two encryption keys EKuserID and EKpassword from a shared random number using two sets of cryptographic ‘hash’ keys.
Message.text[1]=encryption(user ID,key1), and
Message.text[2]=encryption(password hash, key2)
Use a 32 element permutation to scramble the bytes between text[1] and text[2].
Use a 128 element permutation to scramble the bits in text[1] and then in text[2].
Send the message to the server.
The server validates the message hash and authentication hash. A value in text[0][0] informs the server to process the password.
Unscramble the bits and then the bytes and decrypt. Use the user ID to look up the password hash in the server’s table and compare the table password hash value to the decrypted password hash from the message. -
Once you get a prototype working the next step might be to layout a PC board using CAD software such as Eagle.
The following link lets you create a schematic and layout the board.
Some PC houses are tied to the Eagle software and will supply a full blown version tied to their service. For now just download the free version so you can create a schematic.
Lots of tutorials on the Web
https://cadsoft.io/pricing/ -
TTL Cookbook by Don Lancaster an oldie but a goodie. Othe3r cookbooks CMOS, OP-Amp etc.
ftp://apollo.ssl.berkeley.edu/pub/cinema/04.%20Science/TTL%20Cookbook_0672210355.pdfLancaster did the first microcomputer 8008, used 8 track tape to save data and programs.
Famous for TV Typewriter in Popular Electronics magazine.This kind of prototyping board doesn't require solder. But if wired and left for weeks or months the connections oxidize and you have to unplug and replug every connection.
https://commons.wikimedia.org/wiki/File:Protoboard_Unitec.jpgA temperature regulated soldering iron
https://www.sparkfun.com/products/11704A solder vacuum
https://www.sparkfun.com/products/13203Which end of the soldering iron to pick up is left as an exercise for the reader :)
For surface mount there are vendors that provide adapter boards that pin to dual-inline DIP patterns for prototyping. Some will solder the chips to the adapter for a small fee.
http://www.proto-advantage.com/store/product_info.php?products_id=2200069 -
I did some projects a few years back with the Olimex boards with a Nokia display. The ones where the display was double sided taped to the PC board.
They worked fine until I took them outside with a lower temperature. They wouldn't wake up.
The fix that I finally found involved increasing the contrast value in 4 steps with a delay between each step. A one step contrast increase would cause the power to latch up. Four steps allowed the display current draw to adjust and not exceed the latch point. I no longer have access to the code for this. -
**ERROR: Prompt not detected - upload failed. Trying to recover...
...,key,{mode:'ECB'}),j=0;j<16;j++)dcrypt[j]+=crypt[j]/256;for(...
**
Pico v1.85
Trying out AES in ECB mode as a random number generator and got an error.
Did I do something dumb?//AES2.js //How random is it? var plain=new Int8Array(16); var key=new Int8Array(16); var crypt=new Int8Array(16); var dcrypt=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; var i; var j; var k; for(i=0;i<16;i++){ plain[i]=0; key[i]=1; dcrypt[i]=0; }//nexti for(k=0;k<256;k++){ plain[1]=k; for(i=0;i<256;i++){ plain[0]=i; crypt=AES.encrypt(plain,key,{mode:'ECB'}); for(j=0;j<16;j++)dcrypt[j]+=(crypt[j]/256); }//nexti }//nextk for(j=0;j<16;j++)console.log(dcrypt[j]/256);
The Output
>echo(0); ERROR: Prompt not detected - upload failed. Trying to recover... ...,key,{mode:'ECB'}),j=0;j<16;j++)dcrypt[j]+=crypt[j]/256;for(... ^ debug>echo(1); In debug mode: Expected a simple ID, type 'help' for more info. debug>echo(1) In debug mode: Expected a simple ID, type 'help' for more info. debug>c 127.84310913085 127.69502258300 127.16555786132 127.92999267578 127.30929565429 127.41572570800 127.00732421875 127.69149780273 127.79350280761 127.83537292480 127.17370605468 127.31027221679 127.58242797851 127.05628967285
-
Yes you can!
A simple compiled JavaScript function:function foo() { "compiled"; console.log("hello world"); return 0; } foo(); /* Using up arrow several times in left pane one finds the code below var foo=E.nativeCall(1,'JsVar()',atob('Len/QR1IGUt4RJhHBK5G+AQNB0YaSEzy/WN4RJhHFEuARphHBUYTTEBGoEcVSShGeUQAIkz2eTOYRwAhASMqRo3oSAALRk3yDVaARrBHBkZARqBHKEagRzhGoEcwRqBHBUsAIJhHBLC96PCBsbACAHU9AQChqwIAhS8BAHwAAAB2AAAAaAAAAGhlbGxvIHdvcmxkAGNvbnNvbGUAbG9nAA==')); */
Run the program and use the up arrow in the left pane a couple of times to get the native call string.
Using that string one can load it as thumb code in spare memory and call it.fooHelloThmbcode.js
//used foohello.js to get the string /* Using up arrow several times in left pane one finds the code below var foo=E.nativeCall(1,'JsVar()',atob('Len/QR1IGUt4RJhHBK5G+AQNB0YaSEzy/WN4RJhHFEuARphHBUYTTEBGoEcVSShGeUQAIkz2eTOYRwAhASMqRo3oSAALRk3yDVaARrBHBkZARqBHKEagRzhGoEcwRqBHBUsAIJhHBLC96PCBsbACAHU9AQChqwIAhS8BAHwAAAB2AAAAaAAAAGhlbGxvIHdvcmxkAGNvbnNvbGUAbG9nAA==')); */ var data = atob('Len/QR1IGUt4RJhHBK5G+AQNB0YaSEzy/WN4RJhHFEuARphHBUYTTEBGoEcVSShGeUQAIkz2eTOYRwAhASMqRo3oSAALRk3yDVaARrBHBkZARqBHKEagRzhGoEcwRqBHBUsAIJhHBLC96PCBsbACAHU9AQChqwIAhS8BAHwAAAB2AAAAaAAAAGhlbGxvIHdvcmxkAGNvbnNvbGUAbG9nAA=='); //var addr = process.memory().stackEndAddress-data.length; var addr = process.memory().stackEndAddress; for(var i=0;i<data.length;i++){ poke8(addr+i,data.charCodeAt(i)); console.log((addr+i).toString(16)+","+peek8(addr+i).toString(16)); } addr++; var foo= E.nativeCall(addr, 'JsVar()'); foo(); foo();
and the output
20009bda,67 20009bdb,0 hello world =undefined >echo(1) =undefined >foo(); hello world =0 >foo(); hello world =0 >foo(); hello world =0 >foo(); hello world =0 >
-
One last try.
I was looking at the Espruino compiler page:
http://www.espruino.com/CompilationIf a javascript function is compiled, is it possible to call it from assembled code?
-
Adapters for surface mount chips. I've had excellent results with them.
They will even buy and mount the chips, or you can buy chips and send them to be mounted.
Lots of SMT to DIP etc.
http://www.proto-advantage.com/store/ -
Here is a link to help with Thumb code
Introduction to ARM Thumb
https://www.cs.princeton.edu/courses/archive/fall12/cos375/ARMthumb.pdf -
Found it
put code at addr, call at addr+1 for thumb code.var data = atob("AyFAGHBH"); //var addr = process.memory().stackEndAddress-data.length; var addr = process.memory().stackEndAddress; for(var i=0;i<data.length;i++){ poke8(addr+i,data.charCodeAt(i)); console.log((addr+i).toString(16)+","+peek8(addr+i).toString(16)); } addr++; //var adder = E.nativeCall(1, "int(int)", atob("AyFAGHBH")); var adder= E.nativeCall(addr, "int(int)"); console.log(adder(2));
Outputs
>echo(0); 20009b3c,3 20009b3d,21 20009b3e,40 20009b3f,18 20009b40,70 20009b41,47 5 =undefined >
-
Thanks @Wilberforce the up arrow in left pane more than once did the trick.
@Gordon in a previous post suggested this example:
var adder = E.asm("int(int)", "movs r1, #3", "adds r0, r0, r1", // add two 32 bit values "bx lr"); // return
Gives var adder = E.nativeCall(1, "int(int)", atob("AyFAGHBH"))
and you can just use atob("AyFAGHBH"):The "AyFAGHBH" is the 64 bit encoded version of the code.
The atob function converts it to a flat string with escaped characters.
The btoa function creates a 64 bit encoded string.Some confusion about where to poke the string.
@Gordon suggested before the stack end addressvar data = atob("AyFAGHBH"); var addr = process.memory().stackEndAddress-data.length; poke8(addr
The assembler page suggests after the stack end address.
http://www.espruino.com/Assemblervar ASM_BASE=process.memory().stackEndAddress; var ASM_BASE1=ASM_BASE+1/*thumb*/; [0x4a02,0xf44f,0x4360,0x6013,0x6053,0x4770,0x0810,0x4001].forEach(function(v) { poke16((ASM_BASE+=2)-2,v); }); var pulse = E.nativeCall(ASM_BASE1, "void()")
So I’ve tried it both ways and both crash.
var data = atob("AyFAGHBH"); //var addr = process.memory().stackEndAddress-data.length; var addr = process.memory().stackEndAddress+1; for(var i=0;i<data.length;i++){ poke8(addr+i,data.charCodeAt(i)); console.log((addr+i).toString(16)+","+peek8(addr+i).toString(16)); } var adder = E.nativeCall(1, "int(int)", atob("AyFAGHBH")); //var adder= E.nativeCall(addr, "int(int)"); console.log(adder(2));
Which displays
>echo(0); 20009b3d,3 20009b3e,21 20009b3f,40 20009b40,18 20009b41,70 20009b42,47 5 =undefined >
-
Thanks @Gordon. I was just thinking about calling interpreted text like it is machine code really doesn't make sense. Perhaps the best approach other than the pin joining is to have the ISR set a flag and use a setinterval() to check the flag and do the emit.
On a different note, after typing in the asm code and doing the upload you said,
*You best bet is to upload it, then hit up-arrow to see a copy of what was uploaded. *
Nothing happens, no text gets returned? -
Thanks that helps. On the queue problem here's what I've been looking at based on the E.on('IRQ15', function() { ... }) that you've been suggesting.
//an object function IRQ(a){ this.A=a; }//end LogObj //create an instance var a=new IRQ(3); //display the object console.log(a); //create a listener for the object a.on("IRQ1",function(d){ //ISR code goes here //then display the timer results console.log("IRQ1"); console.log(d); }); //Simulate the interrupt a.emit("IRQ1","hello"); IRQ.prototype.setup = function() { // setup asm code in memory // put address in interrupt table }; >echo(0); { "A": 3 } =undefined IRQ1 hello
So either place the call to a.emit in the assembly code or call the assembly code from the a.on() function and place the corresponding address in the interrupt table.
How does one obtain the address of a function such as a.emit to call? -
As far as using timers is concerned, there is a timer method that I've yet to implement, Input Capture. This would allow 4 signals per timer to be measured. In Input Capture mode the timer is clocked by the internal clock. When one of the 4 input channels sees a signal on it's pin the counter value is copied into a separate register that a peek command can access. Hopefully within a week or so I'll get to the input capture modes part of the project.
p382 RM0008 Reference manual 15.3.5 Input capture mode
http://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf -
Thanks for all the good ideas.
It would be nice to be able to use the internal wires between the timers instead of an external wire. This is done by setting up one timer as a master with output TRGO and the second timer as a slave with input on the appropriate line ITR0..ITR3. The problem is telling the Javascript code when the timer process is finished so that the Javascript can peek at the results.
From the interpreter perspective with a finite amount of memory, adding code to cover all possible conditions results in lower memory limits for user code that doesn’t use all the features. It makes sense to have the user add the code to handle the interrupt.
I was looking at the inline assembler page.
http://www.espruino.com/Assembler#line=195,196
For an interrupt service routine (ISR):
Disable interrupts
Clear the interrupt flag
Enable interrupts
Queue something to let Javascript know
Return or is it return from interrupt (as seen in some processors)
So this is placed in spare memory as you outlined and the address written to the interrupt table.
With the code for one such ISR as a pattern, a short function could be written
Function codeISR(InterruptNum,registerAddr,bitnum,value)
The function would then take the example ISR and insert the parameters and console.log the code to be used for the new ISR. These could be pasted into the user program that needs such the ISR function.As far as to which Javascript verb to use do E.on('IRQ15', function() { ... })
or setWatch or some other verb I’ll leave that up to you.Do you have a link to obtain a copy of the assembler?
What is the opcode for disable and enable interrupt?
Does the ARM use a special return from interrupt? If so what is the opcode?
How to queue the Javascript?
myhash1.js
Uses permutations, oneway, and random functions.
var MH=new Myhash(1,1,0,0,0). Try varying the numbers. First 4 can be 0 or 1.
5th number can be 0,1,2 and changes the oneway function operator.
// aes1 0= encrypt, 1=decrypt
// aes2 0= encrypt, 1=decrypt
// pdir1 permutation direction 0 or 1
// pdir2 permutation direction 0 or 1
// owtype 0= add, 1= xor, 2=multiply
The output: