



Ok bro, kali ini saya upload source code program sederhana untuk similarity machine
Untuk teorinya tentang Similarity Machine bis dibaca :
Cosine similarity is a measure of similarity between two vectors of n dimensions by finding the cosine of the angle between them, often used to compare documents in text mining. Given two vectors of attributes, A and B, the cosine similarity, θ, is represented using a dot product and magnitude as
For text matching, the attribute vectors A and B are usually the term frequency vectors of the documents. The cosine similarity can be seen as a method of normalizing document length during comparison.
The resulting similarity ranges from −1 meaning exactly opposite, to 1 meaning exactly the same, with 0 indicating independence, and in-between values indicating intermediate similarity or dissimilarity.
In the case of information retrieval, the cosine similarity of two documents will range from 0 to 1, since the term frequencies (tf-idf weights) cannot be negative. The angle between two term frequency vectors cannot be greater than 90°.
Maaf maaf, saya belum sempat nulis penjelasan source code nya, belum sempat




Di dalam kriptografi ada berbagai macam algoritma yang dapat digunakan, baik yang termasuk algoritma kriptografi modern maupun algoritma kriptografi klasik. Yang termasuk di dalam algoritma kriptografi modern adalah algoritma cipher block. Chiper block merupakan sebuah algoritma simetri yang mengoperasikan bit-bit yang mempunyai panjang yang sama. Sebagai contoh, ketika melakukan enkripsi, sebuah 128-bit blok plaintext akan menghasilkan sebuah 128-bit blok ciphertext. Begitu pula dengan proses deskripsi. Sebuah 128-bit blok ciphertext akan menghasilkan 128-bit blok plaintext.
Sudah banyak sekali algoritma cipher block yang dikembangkan. Salah satunya adalah LOKI. LOKI dirancang oleh kriptografer Australia yaitu Lawrie Brown, Josef Pieprzyk, dan Jennifer Seberry. LOKI didesain sebagai hasil dari analisis yang dilakukan secara detail terhadap blok cipher yang standar digunakan pada saat itu, yaitu DES (Data Encryption Standar). Dikarenakan ada versi terbaru dari LOKI ini, maka LOKI yang dibuat pertama kali lebih dikenal dengan nama LOKI89 sesuai
dengan tahun pembuatannya, walaupun LOKI pertama kali diperkenalkan pada tahun 1990. LOKI91 dibuat sebagai revisi dari LOKI89. Oleh karena itulah terdapat beberapa kesamaan antara LOKI91 dan LOKI89.
LOKI didesain untuk menggantikan DES sehingga strukturnya pun dibuat hampir sama dengan DES. LOKI menggunakan blok data sepanjang 64 bit dan kunci sepanjang 64 bit pula.
Desain LOKI91
Tambahan-tambahan yang terdapat pada LOKI91 dari LOKI89 adalah sebagai berikut.
Spesifikasi LOKI91
Perubahan-perubahan yang terdapat pada LOKI91 adalah sebagai berikut.
Sfn (r,c) = (c + ((r*17) (+) ff16) & ff16) 31 mod genr
Implementasi LOKI91
Kunci masukan disimpan di dalam array of Unsigned Integer32. Sedangkan subkunci untuk 16 putaran dideklarasikan dengan cara :
|
public class loki_ctx {
public uint[] loki_subkeys ;
public loki_ctx()
{
loki_subkeys = new uint[16];
}
}
|
|
public class LOKI {
// deklarasi variabel di sini loki_ctx lctx;
// deklarasi variabel di sini }
|
Fungsi perputaran didefinisikan sebagai berikut.
|
private uint CircularShift( int bitsCount, UInt32 word )
{
return (word << bitsCount) | (word >> (32 - bitsCount));
}
|
CircularShift( 12, b ); digunakan untuk menggeser 32 bit blok b ke kiri secara sirkular sepanjang 12 bit. Sedangkan CircularShift( 13, b ); digunakan untuk menggeser 32 bit blok b ke kiri secara sirkular sepanjang 13 bit.
Sebelum melakukan proses enkripsi/dekripsi, subkunci sebanyak 16 buah harus dibangkitkan terlebih dahulu. Sebelum pembangkitan kunci dilakukan, kunci masukan harus dibagi
dua bagian yaitu KL dan KR seperti pada pembagian kunci di LOKI89.
Pembangkitan subkunci dilakukan dengan cara :
|
public void SetLokiKey( byte[] key)
{
int i;
uint KL, KR;
KL = Get32BitFrom64Bit( key, 0 );
KR = Get32BitFrom64Bit( key, 1 );
for (i=0; i<ROUNDS; i+=4) { /* Generate the 16 subkeys */ lctx.loki_subkeys[i] = KL;
CircularShift( 12, KL );
lctx.loki_subkeys[i+1] = KL;
CircularShift( 13, KL );
lctx.loki_subkeys[i+2] = KR;
CircularShift( 12, KR );
lctx.loki_subkeys[i+3] = KR;
CircularShift( 13, KR );
}
}
|
Dengan ROUNDS=16.
Proses Enkripsi
Blok masukan dibagian menjadi dua buah bagian yang sama besar, yaitu R dan L.
|
uint L, R; /* left & right data halves */ L = Get32BitFrom64Bit( data8byte, 0 );
R = Get32BitFrom64Bit( data8byte, 1 );
|
Kemudian dilakukan proses enkripsi dengan menggunakan 16 buah subkunci yang telah dibangkitkan sebelumnya. Proses enkripsi dengan menggunakan subkunci ini dilakukan dengan cara sebagai berikut.
|
for (i = 0; i < ROUNDS; i += 2)
{ /* Encrypt with the 16 subkeys */ L ^= f( R, lctx.loki_subkeys[i] );
R ^= f( L, lctx.loki_subkeys[i + 1] );
}
|
Operasi yang terakhir dilakukan dalam proses enkripsi adalah dengan menukar L dan R :
|
byte[] bL = SplitUIntToByte( R );
byte[] bR = SplitUIntToByte( L );
data8byte[0] = bL[0];
data8byte[1] = bL[1];
data8byte[2] = bL[2];
data8byte[3] = bL[3];
data8byte[4] = bR[0];
data8byte[5] = bR[1];
data8byte[6] = bR[2];
data8byte[7] = bR[3];
|
Proses Dekripsi
Pada dasarnya proses dekripsi mirip dengan proses enkripsi, hanya saja putaran dilakukan dengan urutan yang terbalik dari proses enkripsi.
Pertama-tama, blok yang akan didekripsi dibagi menjadi dua buah bagian yang sama, yaitu L dan R.
|
uint L, R; /* left & right data halves */
L = Get32BitFrom64Bit( data8byte, 0 ); R = Get32BitFrom64Bit( data8byte, 1 );
|
Kemudian dilakukan putaran dengan cara sebagai berikut.
|
for (i=ROUNDS; i>0; i-=2) { /* subkeys in reverse order */ L ^= f(R, lctx.loki_subkeys[i-1]);
R ^= f(L, lctx.loki_subkeys[i-2]);
}
|
Proses terakhir yang dilakukan pada dekripsi adalah dengan melakukan penukaran antara L dengan R sebagai berikut
|
byte[] bL = SplitUIntToByte( R );
byte[] bR = SplitUIntToByte( L );
data8byte[0] = bL[0];
data8byte[1] = bL[1];
data8byte[2] = bL[2];
data8byte[3] = bL[3];
data8byte[4] = bR[0];
data8byte[5] = bR[1];
data8byte[6] = bR[2];
data8byte[7] = bR[3];
|
Fungsi f(r,k)
Fungsi didefinisikan dengan private uint f( uint r, uint k )
Fungsi f(r,k) merupakan sebuah fungsi LOKI91yang kompleks dan nonlinier yang menghasilkan keluaran yang merupakan hasil dari fungsi kompleks dari masukan dan subkunci. Hal ini dilakukan dengan cara sebagai berikut:
Operasi XOR dilakukan terhadap data masukan (r) dengan subkunci(k). Setelah itu data diperpanjang menjadi 4×12 bit yang akan dimasukkan ke dalam S-box. Keluaran 4×8 bit dari S-box akan dipermutasikan untuk menghasilkan 32 bit keluaran dari fungsi f ini.
Pertama-tama data masukan r dikenai fungsi XOR dengan subkunci masukan dan hasilnya disimpan dalam a.
a = r ^ k;
Sejauh ini operasi yang dilakukan adalah : A = R(i-1) XOR K(i)
Setelah itu dilakukan ekspansi dan hasilnya dimasukkan ke dalam S-box.
|
b = ((uint) s( (uint)(a & MASK12) )) | ((uint) s( (uint)((a >> 8) & MASK12) ) << 8) |
((uint) s( (uint)((a >> 16) & MASK12) ) << 16) |
((uint) s( (uint)(((a >> 24) | (a << 8)) & MASK12) ) << 24);
|
Dimana MASK12 adalah 0×0fff. Sejauh ini operasi yang telah dilakukan adalah.
B = S(E(R(i-1))^K(i))
Operasi yang terakhir dilakukan pada fungsi f ini adalah melakukan permutasi dengan cara :
|
perm32(ref C, b, P ); |
Dengan P didefinisikan sebagai berikut
|
byte[] P = {
31, 23, 15, 7, 30, 22, 14, 6, 29, 21, 13, 5, 28, 20, 12, 4,
27, 19, 11, 3, 26, 18, 10, 2, 25, 17, 9, 1, 24, 16, 8, 0 };
|
Dengan demikian, keseluruhan proses fungsi f ini adalah :
C=P(S(E(R(i-1)) XOR K(i)))
Dengan C adalah nilai yang dihasilkan oleh fungsi f ini.
S-box
Fungsi ini didefinisikan dengan private short s(uint i)
Proses yang dilakukan dalam S-box ini adalah sebagai berikut.
Pertama-tama penentuan nilai baris.
r = (short)(((i>>8) & 0xc) | (i & 0×3));
Setelah penentuan baris selesai, selanjutnya adalah penentuan kolom
c = (short) ((i >> 2) & 0xff);
Kemudian menentukan nilai basis untuk Sfn.
t = (short)((c + ((r * 17) ^ 0xff)) & 0xff);
Tahapan terakhir yang dilakukan adalah menghitung nilai Sfn[r] = t ^ exp mod gen.
v = exp8(t, sfn[r].exp, sfn[r].gen);
Dengan demikian nilai yang dihasilkan dari fungsi S-box ini adalah v.
Permutasi : perm32(out, in, perm)
Didefinisikan dengan private void perm32(ref uint b_out, uint b_in , byte[] p)
Fungsi permutasi pada LOKI91 sama dengan fungsi permutasi pada LOKI89 dimana melakukan operasi permutasi biasa yang mendapat masukan 32 bit blok in, menghasilkan 32 bit blok out. Setiap elemen dari perm menspesifikasikan bit masukan mana yang harus dipermutasikan menjadi bit keluaran dengan indeks yang sama dengan elemen perm.
Fungsi permutasi ini dilakukan dengan cara :
|
uint mask = 0×80000000; int i, o, b;
b_out = 0; for (o=0; o<32; o++) { i =(int)p[o]; b = (int)(b_in >> i) & 0×1; if (b == 1)
{ b_out |= mask; }
mask >>= 1; }
/*
p = perm
o = indeks bit keluaran i = indeks bit masukan
*/
|
Untuk setiap bit keluaran di posisi o, ambil nilai masukan yang akan dipermutasikan ke bit keluaran o. Hitung nilai dari untuk bit masukan i. Jika i telah diset, lakukan OR pada mask untuk bit keluaran i. Geser mask ke bit selanjutnya.
Eksponensial : exp8(base, exponent, gen)
didefinisikan dengan private short exp8(short expbase, short exponent, short gen)
Fungsi eksponensial LOKI91 sama dengan LOKI89, tidak ada perubahan sama sekali. Fungsi ini tetap melakukan operasi : exp = base ^ exp mod gen
Proses dari fungsi ini adalah sebagai berikut.
|
short accum = expbase; short result = 1;
if ( expbase == 0) { return(0); }
while (exponent != 0) { if (( exponent & 0×0001) == 0×0001) { result = mult8(result, accum, gen);
}
exponent >>= 1; accum = mult8(accum, accum, gen); }
return (result);
|
Jika nilai base adalah 0 maka fungsi akan otomatis mengembalikan nilai 0. Jika tidak 0 maka dilakukan proses perulangan hingga exponent menjadi 0. Eksponen akan dikenai fungsi mult8 jika nilai eksponen adalah 1. Lalu nilai eksponen bergeser ke digit selanjutnya.
Multiply : mult8(a, b, gen)
Fungsi ini didefinisikan dengan private short mult8( short a, short b, short gen )
Fungsi mult8 mengembalikan hasil perkalian dari dua buah string biner a dan b serta menggunakan generator gen sebagai modulus.
mult = a * b mod gen
Proses dari fungsi ini adalah sebagai berikut.
|
short product = 0; /* result of multiplication */
while (b != 0)
{ /* while multiplier is non–zero */ if ((b & 1) == 1)
{
product ^= a; /* add multiplicand if LSB of b set */ }
a <<= 1; /* shift multiplicand one place */ if (a >= SIZE)
{
a ^= gen; /* and modulo reduce if needed */ }
b >>= 1; /* shift multiplier one place */ }
return (product);
|
Selama pengali b tidak 0, lakukan proses berikut ini : jika LSB dari b merupakan 1, tambahkan hasil perkalian dengan a. Geser a sebanyak satu digit. Jika a lebih besar dari 256, maka a dikurangi modulo. Geser a sebanyak satu digit.
ScreenShoot Program
Mengetikkan plain text secara manual, dan mengetikkan hexadecimal password. (Password hanya bisa menerima karakter 0-9 dan A-F
Hasil enkripsi pesan diatas
Pesan juga bisa disimpan ke dalam File.
Jika dilakukan dekrip bisa kempali seperti semula
Tersedia juga fitur Copy, Edit, dan Paste
SOURCE CODE
|
Keterangan
Program dibuat menggunakan bahasa C#.NET dan dikompilasi menggunakan .NET Framework v.2.0. Untuk menjalankan program minimal Microsoft .NET Famework versi 2.0 (Windows) atau Mono versi 2.4 (Linux) sudah terinstall di komputer. Untuk menjalankan program di Windows, jalankan KriptoIlkompLoki91.exe Untuk menjalankan di linux, melalui console jalankan perintah $> mono KriptoIlkompLoki91.exe Jika ingin mengkompilasi ulang source code di Windows, ketikkan $> msbuild KriptoIlkompLoki91.sln Jika ingin mengkompilasi ulang source code di Linux, ketikkan $> xbuild KriptoIlkompLoki91.sln |
|
File : LOKI.cs (Berisi class untuk LOKI) |
|
using System;
using System.Collections.Generic;
using System.Text;
namespace KriptoIlkompLoki91 {
public class LOKI {
const string VER = “LOKI91″;
const byte ROUNDS = 16;
const byte LOKIBLK = 9;
const short MASK12 = 0×0fff ;
const uint MSB = 0×80000000;
const short SIZE = 256;
byte[] P = {
31, 23, 15, 7, 30, 22, 14, 6,
29, 21, 13, 5, 28, 20, 12, 4,
27, 19, 11, 3, 26, 18, 10, 2,
25, 17, 9, 1, 24, 16, 8, 0 };
sfn_desc[] sfn;
loki_ctx lctx;
private uint CircularShift( int bitsCount, UInt32 word )
{
return (word << bitsCount) | (word >> (32 - bitsCount));
}
private void enloki( ref byte[] data8byte )
{
int i;
uint L, R; /* left & right data halves */
L = Get32BitFrom64Bit( data8byte, 0 );
R = Get32BitFrom64Bit( data8byte, 1 );
for (i = 0; i < ROUNDS; i += 2)
{ /* Encrypt with the 16 subkeys */ L ^= f( R, lctx.loki_subkeys[i] );
R ^= f( L, lctx.loki_subkeys[i + 1] );
}
byte[] bL = SplitUIntToByte( R );
byte[] bR = SplitUIntToByte( L );
data8byte[0] = bL[0];
data8byte[1] = bL[1];
data8byte[2] = bL[2];
data8byte[3] = bL[3];
data8byte[4] = bR[0];
data8byte[5] = bR[1];
data8byte[6] = bR[2];
data8byte[7] = bR[3];
return;
}
private void deloki( ref byte[] data8byte )
{
int i;
uint L, R; /* left & right data halves */
L = Get32BitFrom64Bit( data8byte, 0 ); R = Get32BitFrom64Bit( data8byte, 1 );
for (i=ROUNDS; i>0; i-=2) { /* subkeys in reverse order */ L ^= f(R, lctx.loki_subkeys[i-1]);
R ^= f(L, lctx.loki_subkeys[i-2]);
}
byte[] bL = SplitUIntToByte( R );
byte[] bR = SplitUIntToByte( L );
data8byte[0] = bL[0];
data8byte[1] = bL[1];
data8byte[2] = bL[2];
data8byte[3] = bL[3];
data8byte[4] = bR[0];
data8byte[5] = bR[1];
data8byte[6] = bR[2];
data8byte[7] = bR[3];
}
private uint f( uint r, uint k )
{
/* r Data value R(i–1) */ /* k Key K(i) */ uint a, b, C; /* 32 bit S–box output, & P output */ a = r ^ k; /* A = R(i–1) XOR K(i) */ C = 0;
b = ((uint) s( (uint)(a & MASK12) )) | /* B = S(E(R(i–1))^K(i)) */ ((uint) s( (uint)((a >> 8) & MASK12) ) << 8) |
((uint) s( (uint)((a >> 16) & MASK12) ) << 16) |
((uint) s( (uint)(((a >> 24) | (a << 8)) & MASK12) ) << 24);
perm32(ref C, b, P ); /* C = P(S( E(R(i–1)) XOR K(i))) */
return C; /* f returns the result C */ }
private short s(uint i)
{
short r, c, v, t;
r = (short)(((i>>8) & 0xc) | (i & 0×3)); c = (short) ((i >> 2) & 0xff); t = (short)((c + ((r * 17) ^ 0xff)) & 0xff); v = exp8(t, sfn[r].exp, sfn[r].gen); return (v);
}
private void perm32(ref uint b_out, uint b_in , byte[] p)
{
uint mask = MSB; /* mask used to set bit in output */ int i, o, b; /* input bit no, output bit no, value */
b_out = 0; /* clear output block */ for (o=0; o<32; o++) { /* For each output bit position o */ i =(int)p[o]; /* get input bit permuted to output o */ b = (int)(b_in >> i) & 0×1; /* value of input bit i */ if (b == 1)
{ /* If the input bit i is set */ b_out |= mask; /* OR in mask to output i */ }
mask >>= 1; /* Shift mask to next bit */ }
}
private short mult8( short a, short b, short gen )
{
short product = 0; /* result of multiplication */
while (b != 0)
{ /* while multiplier is non–zero */ if ((b & 1) == 1)
{
product ^= a; /* add multiplicand if LSB of b set */ }
a <<= 1; /* shift multiplicand one place */ if (a >= SIZE)
{
a ^= gen; /* and modulo reduce if needed */ }
b >>= 1; /* shift multiplier one place */ }
return (product);
}
private short exp8(short expbase, short exponent, short gen)
{
short accum = expbase; /* superincreasing sequence of base */ short result = 1; /* result of exponentiation */
if ( expbase == 0) { /* if zero base specified then */ return(0); /* the result is “0” if base = 0 */ }
while (exponent != 0) { /* repeat while exponent non–zero */ if (( exponent & 0×0001) == 0×0001) { result = mult8(result, accum, gen);
}
exponent >>= 1; accum = mult8(accum, accum, gen); }
return (result);
}
private uint ConcateByteToUInt( byte[] data )
{
uint a = (data[0] & 0xFFFFFFFF) << 24;
uint b = (data[1] & 0xFFFFFFFF) << 16;
uint c = (data[2] & 0xFFFFFFFF) << 8;
uint d = data[3];
return a | b | c | d;
}
private byte[] SplitUIntToByte( uint data )
{
byte[] b = new byte[4];
b[0] = (byte) ((data & 0xFF000000) >> 24);
b[1] = (byte) ((data & 0×00FF0000) >> 16);
b[2] = (byte) ((data & 0×0000FF00) >> 8);
b[3] = (byte) (data & 0×000000FF) ;
return b;
}
// PUBLIC //
public LOKI()
{
/* initialize */sfn = new sfn_desc[17];
/* 101110111 */ sfn[0] = new sfn_desc(375, 31); /* 101111011 */ sfn[1] = new sfn_desc(379, 31) ;
/* 110000111 */ sfn[2] = new sfn_desc(391, 31) ;
/* 110001011 */ sfn[3] = new sfn_desc(395, 31);
/* 110001101 */ sfn[4] = new sfn_desc(397, 31) ;
/* 110011111 */ sfn[5] = new sfn_desc(415, 31);
/* 110100011 */ sfn[6] = new sfn_desc(419, 31);
/* 110101001 */ sfn[7] = new sfn_desc(425, 31);
/* 110110001 */ sfn[8] = new sfn_desc(433, 31) ;
/* 110111101 */ sfn[9] = new sfn_desc(445, 31);
/* 111000011 */ sfn[10] = new sfn_desc(451, 31) ;
/* 111001111 */ sfn[11] = new sfn_desc(463, 31);
/* 111010111 */ sfn[12] = new sfn_desc(471, 31) ;
/* 111011101 */ sfn[13] = new sfn_desc(477, 31);
/* 111100111 */ sfn[14] = new sfn_desc(487, 31) ;
/* 111110011 */ sfn[15] = new sfn_desc( 499, 31 );
/* 000000000 */ sfn[16] = new sfn_desc(00, 00);
lctx = new loki_ctx();
}
public void SetLokiKey( byte[] key)
{
int i;
uint KL, KR;
KL = Get32BitFrom64Bit( key, 0 );
KR = Get32BitFrom64Bit( key, 1 );
for (i=0; i<ROUNDS; i+=4) { /* Generate the 16 subkeys */ lctx.loki_subkeys[i] = KL;
CircularShift( 12, KL );
lctx.loki_subkeys[i+1] = KL;
CircularShift( 13, KL );
lctx.loki_subkeys[i+2] = KR;
CircularShift( 12, KR );
lctx.loki_subkeys[i+3] = KR;
CircularShift( 13, KR );
}
}
public uint Get32BitFrom64Bit( byte[] data8byte , byte idx)
{
if (idx == 0)
{
byte[] b = new byte[4];
b[0] = data8byte[0];
b[1] = data8byte[1];
b[2] = data8byte[2];
b[3] = data8byte[3];
return ConcateByteToUInt( b );
}
else
{
byte[] b = new byte[4];
b[0] = data8byte[4];
b[1] = data8byte[5];
b[2] = data8byte[6< |