Penggunaan Base64 pada Kriptografi


Ketika kita menggunakan atau mendesain kriptografi dalam java kita dihadapkan salah satu problem yaitu key atau kunci. Problem kunci ini termasuk kompleks seperti pertukaran/pengiriman kunci, generator kunci, padding, salt dan lain lain. Salah satu problem yang akan kita coba kupas adalah generator kunci:

Didalam library JCE, dan JCA kita bisa membangkitkan kunci untuk algoritma yang kita gunakan, kunci disini bersifat random namun tidak dideterministik, yang dimaksud tidak deterministik adalah kita tidak dapat membangkitkan kembali kunci dipenerima jadi kunci harus dikirim melalui kanal secure atau hanya yang pihak yang berwenang mengetahui kunci.

Kunci juga bisa kita input secara manual, seperti layaknya password yang kita gunakan. Namun algoritma kriptografi hanya mengenal inputan berupa deretan bit atau byte seperti DES menggunakan panjang bit sebanyak 56 bit atau 8 byte. Oleh sebab itu perlu metode bagaimana algoritma dapat mengenali inputan berupa huruf layaknya password. Namun kali ini kita tidak membahas itu.

Kali ini kita mencoba membahas tentang kunci inputan yang berupa byte dapat diterjemahkan atau dibaca kedalam bentuk huruf-huruf latin, hal ini bermanfaat agar user dapat membaca, mengcopy, menyimpan, ataupun mengingat.Untuk mengatasi hal tersebut salah satu solusinya dalah menggunakan java.util.Base64.Encoder, cara kerja BASE64 di class tersebut menggunakan standart RFC 4648 and RFC 2045

Sebagai contoh kita mempunyai deretan kunci dalam bentuk byte untuk algoritma DES

byte[] keyBytes = new byte[] {(byte) 0x00 , 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

kita akan rubah kedalam bentuk SecretKeySpec agar dapat digunakan pada algoritma DES

SecretKeySpec key64 = new SecretKeySpec(keyBytes, "DES");

setelah itu kita akan mencoba mengkonversikan kedalam BASE64 sebagai berikut:

String encodedKey = Base64.getEncoder().encodeToString(key64.getEncoded());
System.out.println(encodedKey);

maka akan kita akan medapatkan hasil AAECAwQFBgc=, darimana bentuk tersebut? berikut step-step nya

Nilai Byte {0x00 , 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

Nilai byte diatas dikonversikan kedalam bit dan bagi kedalam 24 bit blok, jika diblok bit terakhir tidak sepanjang 24 maka tambakhkan bit 0 sebagai padding
{0000 0000 0000 0001 0000 0010} {0000 0011 0000 0100 0000 0101} {0000 0110 0000 0111 [00000000]}

Kumpulkan setiap bit kedalam blok bit sepanjang 6 bit
000000 000000 000100 000010 000000 110000 010000 000101 000001 100000 011100 000000

dalam decimal: 0 0 4 2 0 48 16 5 1 32 28 (padding)

terjemahkan setiap 6 bit tersebut kedalam seperti tabel berikut:

Value Char Value Char Value Char Value Char
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31 f 47 v 63 /

jika terdapat 1 blok bit padding maka terjemahan blok tersebut menjadi character “=”, maka hasil yang kita dapatkan seperti berikut AAECAwQFBgc= deretan huruf itu kita bisa gunakan sebagai kunci pada saat dekripsi dengan menggunakan

byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "DES");
Advertisements

Caesar Cipher bagian 3, [language detection]


Ada beberapa translate online yang popular saat ini, sebut saja google translate, bing translator, yandex translator, dan lain lain. Google sangat populer memang dalam penggunaan translatornya padahal masih banyak translator translotor lainya baik yang berbayar maupun gratis, detailnya dapat dilihat dilaman berikut https://en.wikipedia.org/wiki/Comparison_of_machine_translation_applications

Namun kali ini kita tidak membahas mengenai translator sebagai alat penerjemah, namun pada postingan sebelumnya perihal bruteforce attack pada caesar cipher yang masih harus secara manual kita melihat mana plaintext yang benar.

Idenya sangat sederhana, hasil dekripsi dengan bruteforce dilakukan language detection jika hasil tersebut terdeteksi makan kemungkinan hasil dekripsi tersebut adalah dengan kunci yang benar. Kali ini kita menggunakan yandex translator, mengapa? jawabanya gratis 😀 , namun beberapa keterbatasan yang akan kita temukan

sebelumnya penggunaan yandex java api dapat diunduh disini: https://github.com/rmtheis/yandex-translator-java-api
dan untuk API key nya dapat digenerate melalui https://tech.yandex.com/translate/

setelah itu kita dapat membuat program sederhana dengan java sebagai berikut:

 
package detectLang;

import com.rmtheis.yandtran.detect.Detect;
import com.rmtheis.yandtran.language.Language;
import com.rmtheis.yandtran.translate.Translate;


public class DetectL {	
	public static void main(String[] args) throws  Exception{	
		  Translate.setKey(["API Key"]);
		  Language lang1 = Language.ENGLISH;
		  Language lang2 = Language.GERMAN;
		  String translatedText = Translate.execute("when you saw him call me", lang1, lang2);
		  System.out.println(translatedText);
		  Language detectText = Detect.execute(translatedText);
	          System.out.println(detectText);
	}
}

hasil yang akan didapatkan adalah sebagai berikut:

wenn du ihn sehen rufen Sie mich
de

de adalah kode untuk bahasa jerman, kode selengkapnya dapat dilihat https://tech.yandex.com/translate/doc/dg/concepts/langs-docpage/

Script diatas adalah salah satu cara untuk mendeteksi bahasa apa yang digunakan dan juga mentraslate bahasa tersebut. Mengapa kita perlu mentranslate juga, apakah tidak cukup hanya dengan mendeteksi? bukannya dengan mendeteksi kita sudah dapat menentukan plaintext mana yang benar pada bruteforce attack. Secara teoritical memang begitu, namu pada kenyataan nya Translator pada kalimat-kalimat yang tidak dapat ditranslate sering kali sembarangan dalam mendeteksi kalimat tersebut, seperti kalimat berikut “Vxubojky g Pgbg cxgvvkx gxuatj znk Egtjkd sginotk zxgtyrgzout ckh ykxboik GVO” dideteksi sebagai bahasa inggris. Oleh sebab itu kita bisa sedikit tricky untuk mengatasi itu kurang lebih step step nya sebagai berikut

CipherText > Bruteforce attack > Detect language (1) > Translate language > Detect Language (2) > Plaintext

Solusi diatas adalah salah satu cara meningkatkan efisiensi bruteforce attack pada caesar cipher. Kita dapat menggunakan bahasa Indonesia, tetapi kita harus menambahkan di Language.java INDONESIAN(“id”),

berikut adalah contoh script modifikasi dari script sebelum nya http://wp.me/prw8r-1ei dengan mengunakan detect dan translate sebagai deteksi plaintext:

 
package encryptdecrypt;

import com.rmtheis.yandtran.detect.Detect;
import com.rmtheis.yandtran.language.Language;
import com.rmtheis.yandtran.translate.Translate;



public class CaesarCipher {
	
	public static String bacaString(){
        int karakter;
        String str = "";
        boolean selesai =false;
         
        while(!selesai){
            try{
                karakter =System.in.read();
                if (karakter <0 || (char) karakter == '\n')
                    selesai=true;
                else if ((char) karakter != '\r')
                    str = str + (char) karakter;
                }
            catch(java.io.IOException e) {
                System.err.println("ada kesalahan");
                selesai = true;
            }
        }
      return str;
    }
	    
	private static String encrypting(String st, int rtint){
        int pjgstr=st.length();
        char [] ciphertext = new char [pjgstr];
       
        int[] ascist;
        ascist = new int [pjgstr];
 
        int[] cipherasci1;
        cipherasci1 = new int [pjgstr];
        int[] cipherasci2;
        cipherasci2 = new int [pjgstr];
        int salah = 0;
 
        if (rtint >= 26)
            rtint = rtint%25;
      

        for (int a=0; a < pjgstr; a++) {
        ascist[a] = String.valueOf(st).codePointAt(a);

        if (ascist[a] >= 97 && ascist[a] <= 122 ){
            cipherasci1 [a] = ascist[a]+rtint;
            if (cipherasci1 [a] >= 123)
                cipherasci2 [a] = 97 + (cipherasci1 [a] % 123);
            else
                cipherasci2 [a] = cipherasci1 [a];   
        }
        else if (ascist[a] >= 65 && ascist[a] <= 90 ) {
            cipherasci1 [a] = ascist[a]+rtint;
            if (cipherasci1 [a] >= 91)
                cipherasci2 [a] = 65 + (cipherasci1 [a] % 91);
            else
                cipherasci2 [a] = cipherasci1 [a];
        }
        else if (ascist[a] == 32 ) {
            cipherasci2 [a] = 32;
        }
 
        else {
            salah = 1;
        }
        
        ciphertext [a] = (char) cipherasci2 [a];
            }
        
        String Ct = String.valueOf(ciphertext);
     
        if (salah == 1)
            System.out.println("==error== (masukan hanya huruf besar / kecil dan spasi)"); 
        return Ct;
	}
	
	private static String decrypting(String st, int rtint){
        int pjgstr=st.length();
        char [] ciphertext = new char [pjgstr];
      
        int[] ascist;
        ascist = new int [pjgstr];
 
        int[] cipherasci1;
        cipherasci1 = new int [pjgstr];
        int[] cipherasci2;
        cipherasci2 = new int [pjgstr];
        int salah = 0;
 
        if (rtint >= 26)
            rtint = rtint%25;
     
        
        for (int a=0; a < pjgstr; a++) {
        ascist[a] = String.valueOf(st).codePointAt(a);
  
        if (ascist[a] >= 97 && ascist[a] <= 122 ){
        	
            
            cipherasci1 [a] = ascist[a]-rtint;
            if (cipherasci1 [a] <= 96)
                cipherasci2 [a] = -96 + 122 + (cipherasci1 [a] % 97);
            else
                cipherasci2 [a] = cipherasci1 [a]; 
          
        }
       
        else if (ascist[a] >= 65 && ascist[a] <= 90 ) {
            cipherasci1 [a] = ascist[a]-rtint;
            if (cipherasci1 [a] <= 64)
                cipherasci2 [a] = -64 + 90 + (cipherasci1 [a] % 65);
            else
                cipherasci2 [a] = cipherasci1 [a];
        }
        else if (ascist[a] == 32 ) {
            cipherasci2 [a] = 32;
        }
 
        else {
            salah = 1;
        }
        
        ciphertext [a] = (char) cipherasci2 [a];
            }
        
        if (salah == 1)
            System.out.println("==error== (masukan hanya huruf besar / kecil dan spasi)");

        String pt = String.valueOf(ciphertext);
        return pt;
		
	}
	
	private static Language detect (String st) throws Exception{
		Translate.setKey("[Your API Key]");
		 Language detectText2 = Detect.execute(st);
		// Boolean status = detectText2!=null;
		 return detectText2;
	}
	
	private static Boolean detect2 (String st, Language lang) throws Exception{
		  Translate.setKey("[Your API Key]");
		  
		  Language lang2 = Language.GERMAN;
		  Language lang1 = Language.INDONESIAN;
		  String translatedText;
		  if (lang != lang2) {
			  translatedText = Translate.execute(st, lang, lang2);
		  }
		  else {
			  translatedText = Translate.execute(st, lang, lang1);
		  }
		  Language detectText = Detect.execute(translatedText);
		  Boolean status = detectText==lang2;
		  return status;
	}
	
	private static String [] BruteForce (String st){
		String plainAr [] = new String [26];
		for (int i=0; i < 26; i++){
			String plain = decrypting (st, i);
			plainAr [i]=plain;
		}
		return plainAr;
	}
	
	
	public static void main(String[] args) throws Exception{
	        System.out.print("Plaintext: ");
	        String st = bacaString();
	        System.out.print("ROT: ");
	        String rt = bacaString();
	        int rtint = Integer.parseInt(rt);
	        String cipher = encrypting (st, rtint);
	        System.out.print("Ciphertext: ");
	        System.out.println( cipher);
	        String plain = decrypting (cipher, rtint);
	        System.out.print("Plaintext: ");
	        System.out.println( plain );
	        System.out.println();
	        String [] plainAr = BruteForce (cipher);
	        
	       for (int i =0; i <26; i++){
	    	   Language Lang =  detect (plainAr[i]);
	    	    if (Lang!=null) {
	    	    	Boolean status2 =  detect2 (plainAr[i],Lang);
	    	    	if (status2 == true) {
	    	    		 System.out.print("Brute Force attack ke " + i + " : ");
	 		        	 System.out.println( plainAr[i]);
	    	    	}
	    	    }
	       }
	        	      
	    }
	 }

hasil yang didapatkan dari console adalah sebagai beriktu (contoh plaintext: Provides a Java wrapper around the Yandex machine translation web service API)

Plaintext: Provides a Java wrapper around the Yandex machine translation web service API
ROT: 13
Ciphertext: Cebivqrf n Wnin jenccre nebhaq gur Lnaqrk znpuvar genafyngvba jro freivpr NCV
Plaintext: Provides a Java wrapper around the Yandex machine translation web service API

Brute Force attack ke 13 : Provides a Java wrapper around the Yandex machine translation web service API

sebagai perbandingan jika kita hanya menggunakan deteksi bahasa saja, maka hasil yang didapatkan sebagai berikut:

Plaintext: Provides a Java wrapper around the Yandex machine translation web service API
ROT: 13
Ciphertext: Cebivqrf n Wnin jenccre nebhaq gur Lnaqrk znpuvar genafyngvba jro freivpr NCV
Plaintext: Provides a Java wrapper around the Yandex machine translation web service API

Brute Force attack ke 7 : Vxubojky g Pgbg cxgvvkx gxuatj znk Egtjkd sginotk zxgtyrgzout ckh ykxboik GVO
Brute Force attack ke 13 : Provides a Java wrapper around the Yandex machine translation web service API
Brute Force attack ke 18 : Kmjqdyzn v Evqv rmvkkzm vmjpiy ocz Tviyzs hvxcdiz omvingvodji rzw nzmqdxz VKD

Oleh sebab itu kombinasi antara deteksi bahasa dengan translate bahasa dapat meningkatkan ketepatan dalam penggunaan bruteforce attack pada caesar cipher.

Selanjutnya kita akan mencoba cara yang lebih mengasyikan yaitu menggunakan frekuensi analisis yang sebagai mana dijelaskan oleh ilmuan Abu Yūsuf Yaʻqūb ibn ʼIsḥāq aṣ-Ṣabbāḥ al-Kindī yang dijelaskan dalam bukunya Istikhraj al-Kotob Al-Mu’amah رسالة في استخراج الكتب المعماة (On Extracting Obscured Correspondence, more contemporary: On Decrypting Encrypted Correspondence ). Analsis frekuensi bisa dikatakan sudah merevolusi ilmu kriptografi sampai sekarang yang kita kenal sekarang ini.

Caesar Cipher bagian 2, [bruteforce attack]


Setelah sebelum nya kita pernah membahas tentang caesar cipher menggunakan java pada postingan berikut https://ridhobustami.wordpress.com/2015/03/31/caesar-cipher/ sayang nya kita lupa membahas bagaimana mendekripsikan cipher text tersebut, prinsip dekripsi pada caesar cipher tidak sulit, hanya dengan mengurangkan cipher textnya sesuai dengan rotasi nya, selain itu kita juga akan mencoba bruteforce attack di caesar cipher, untuk lebih jelasnya perhatikan script java berikut:

package encryptdecrypt;



public class CaesarCipher {
	
	public static String bacaString(){
        int karakter;
        String str = "";
        boolean selesai =false;
         
        while(!selesai){
            try{
                karakter =System.in.read();
                if (karakter <0 || (char) karakter == '\n')
                    selesai=true;
                else if ((char) karakter != '\r')
                    str = str + (char) karakter;
                }
            catch(java.io.IOException e) {
                System.err.println("ada kesalahan");
                selesai = true;
            }
        }
      return str;
    }
	    
	private static String encrypting(String st, int rtint){
        int pjgstr=st.length();
        char [] ciphertext = new char [pjgstr];
       
        int[] ascist;
        ascist = new int [pjgstr];
 
        int[] cipherasci1;
        cipherasci1 = new int [pjgstr];
        int[] cipherasci2;
        cipherasci2 = new int [pjgstr];
        int salah = 0;
 
        if (rtint >= 26)
            rtint = rtint%25;
      

        for (int a=0; a < pjgstr; a++) {
        ascist[a] = String.valueOf(st).codePointAt(a);

        if (ascist[a] >= 97 && ascist[a] <= 122 ){
            cipherasci1 [a] = ascist[a]+rtint;
            if (cipherasci1 [a] >= 123)
                cipherasci2 [a] = 97 + (cipherasci1 [a] % 123);
            else
                cipherasci2 [a] = cipherasci1 [a];   
        }
        else if (ascist[a] >= 65 && ascist[a] <= 90 ) {
            cipherasci1 [a] = ascist[a]+rtint;
            if (cipherasci1 [a] >= 91)
                cipherasci2 [a] = 65 + (cipherasci1 [a] % 91);
            else
                cipherasci2 [a] = cipherasci1 [a];
        }
        else if (ascist[a] == 32 ) {
            cipherasci2 [a] = 32;
        }
 
        else {
            salah = 1;
        }
        
        ciphertext [a] = (char) cipherasci2 [a];
            }
        
        String Ct = String.valueOf(ciphertext);
     
        if (salah == 1)
            System.out.println("==error== (masukan hanya huruf besar / kecil dan spasi)"); 
        return Ct;
	}
	
	private static String decrypting(String st, int rtint){
        int pjgstr=st.length();
        char [] ciphertext = new char [pjgstr];
      
        int[] ascist;
        ascist = new int [pjgstr];
 
        int[] cipherasci1;
        cipherasci1 = new int [pjgstr];
        int[] cipherasci2;
        cipherasci2 = new int [pjgstr];
        int salah = 0;
 
        if (rtint >= 26)
            rtint = rtint%25;
     
        
        for (int a=0; a < pjgstr; a++) {
        ascist[a] = String.valueOf(st).codePointAt(a);
  
        if (ascist[a] >= 97 && ascist[a] <= 122 ){
        	
            
            cipherasci1 [a] = ascist[a]-rtint;
            if (cipherasci1 [a] <= 96)
                cipherasci2 [a] = -96 + 122 + (cipherasci1 [a] % 97);
            else
                cipherasci2 [a] = cipherasci1 [a]; 
          
        }
       
        else if (ascist[a] >= 65 && ascist[a] <= 90 ) {
            cipherasci1 [a] = ascist[a]-rtint;
            if (cipherasci1 [a] <= 64)
                cipherasci2 [a] = -64 + 90 + (cipherasci1 [a] % 65);
            else
                cipherasci2 [a] = cipherasci1 [a];
        }
        else if (ascist[a] == 32 ) {
            cipherasci2 [a] = 32;
        }
 
        else {
            salah = 1;
        }
        
        ciphertext [a] = (char) cipherasci2 [a];
            }
        
        if (salah == 1)
            System.out.println("==error== (masukan hanya huruf besar / kecil dan spasi)");

        String pt = String.valueOf(ciphertext);
        return pt;
		
	}
	
	private static String [] BruteForce (String st){
		String plainAr [] = new String [26];
		for (int i=0; i < 26; i++){
			String plain = decrypting (st, i);
			plainAr [i]=plain;
		}
		return plainAr;
	}
	
	
	public static void main(String[] args){
	        System.out.print("Plaintext: ");
	        String st = bacaString();
	        System.out.print("ROT: ");
	        String rt = bacaString();
	        int rtint = Integer.parseInt(rt);
	        String cipher = encrypting (st, rtint);
	        System.out.print("Ciphertext: ");
	        System.out.println( cipher);
	        String plain = decrypting (cipher, rtint);
	        System.out.print("Plaintext: ");
	        System.out.println( plain );
	        System.out.println();
	        String [] plainAr = BruteForce (cipher);
	        
	       for (int i =0; i <26; i++){
	    	   	System.out.print("Brute Force attack ke " + i + " : ");
	        	System.out.println( plainAr[i]);
	       }
	        	         
	    }
	 }
	

hasil dari script diatas jika kita mengisi plaintext dengan kalimat when you saw him call me dengan rotasi sebanyak 8 maka di console akan kita dapatkan hasil sebagai berikut

Plaintext: when you saw him call me
ROT: 8
Ciphertext: epmv gwc aie pqu kitt um
Plaintext: when you saw him call me

Brute Force attack ke 0 : epmv gwc aie pqu kitt um
Brute Force attack ke 1 : dolu fvb zhd opt jhss tl
Brute Force attack ke 2 : cnkt eua ygc nos igrr sk
Brute Force attack ke 3 : bmjs dtz xfb mnr hfqq rj
Brute Force attack ke 4 : alir csy wea lmq gepp qi
Brute Force attack ke 5 : zkhq brx vdz klp fdoo ph
Brute Force attack ke 6 : yjgp aqw ucy jko ecnn og
Brute Force attack ke 7 : xifo zpv tbx ijn dbmm nf
Brute Force attack ke 8 : when you saw him call me
Brute Force attack ke 9 : vgdm xnt rzv ghl bzkk ld
Brute Force attack ke 10 : ufcl wms qyu fgk ayjj kc
Brute Force attack ke 11 : tebk vlr pxt efj zxii jb
Brute Force attack ke 12 : sdaj ukq ows dei ywhh ia
Brute Force attack ke 13 : rczi tjp nvr cdh xvgg hz
Brute Force attack ke 14 : qbyh sio muq bcg wuff gy
Brute Force attack ke 15 : paxg rhn ltp abf vtee fx
Brute Force attack ke 16 : ozwf qgm kso zae usdd ew
Brute Force attack ke 17 : nyve pfl jrn yzd trcc dv
Brute Force attack ke 18 : mxud oek iqm xyc sqbb cu
Brute Force attack ke 19 : lwtc ndj hpl wxb rpaa bt
Brute Force attack ke 20 : kvsb mci gok vwa qozz as
Brute Force attack ke 21 : jura lbh fnj uvz pnyy zr
Brute Force attack ke 22 : itqz kag emi tuy omxx yq
Brute Force attack ke 23 : hspy jzf dlh stx nlww xp
Brute Force attack ke 24 : grox iye ckg rsw mkvv wo
Brute Force attack ke 25 : fqnw hxd bjf qrv ljuu vn

pada method BruteForce (cipher) tidak diperlukan nilai rotasi atau kunci namun dengan mengunakan brute force kita mendapatkan 25 kombinasi hasil dekripsi yang hanya pada nilai Brute Force attack ke 8 memiliki arti. Disini kita bisa melihat salah satu kelemahan dari caesar cipher, hanya beberapa millisecond bruteforce attack dapat dilakukan, namun di program ini belum dapat menentukan secara otomatis hasil dekripsi yamg mana yang memiliki arti dalam bahasa.

Memodifikasi Sbox pada algoritma GOST28147 provider BC


Salah satu parameter dalam Algoritma GOST28147 adalah Sbox, Sbox bisa bersifat secret ataupun open. Didalam algoritma GOST28147 yang disediakan oleh provider BC terdapat beberapa alternatif SBOX seperti yang terdapat didalam
GOST28147Engine.java, kita dapat melihatnya dari baris 22 sampai 116 pada class tersebut. Scriptnya sebagai berikut:

    // these are the S-boxes given in Applied Cryptography 2nd Ed., p. 333
    // This is default S-box!
    private byte S[] = {
        0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3,
        0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9,
        0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB,
        0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3,
        0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2,
        0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE,
        0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC,
        0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC
    };
    
    /*
     * class content S-box parameters for encrypting
     * getting from, see: http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-01.txt
     *                    http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-02.txt
     */
    private static byte[] ESbox_Test = {
         0x4,0x2,0xF,0x5,0x9,0x1,0x0,0x8,0xE,0x3,0xB,0xC,0xD,0x7,0xA,0x6,
         0xC,0x9,0xF,0xE,0x8,0x1,0x3,0xA,0x2,0x7,0x4,0xD,0x6,0x0,0xB,0x5,
         0xD,0x8,0xE,0xC,0x7,0x3,0x9,0xA,0x1,0x5,0x2,0x4,0x6,0xF,0x0,0xB,
         0xE,0x9,0xB,0x2,0x5,0xF,0x7,0x1,0x0,0xD,0xC,0x6,0xA,0x4,0x3,0x8,
         0x3,0xE,0x5,0x9,0x6,0x8,0x0,0xD,0xA,0xB,0x7,0xC,0x2,0x1,0xF,0x4,
         0x8,0xF,0x6,0xB,0x1,0x9,0xC,0x5,0xD,0x3,0x7,0xA,0x0,0xE,0x2,0x4,
         0x9,0xB,0xC,0x0,0x3,0x6,0x7,0x5,0x4,0x8,0xE,0xF,0x1,0xA,0x2,0xD,
         0xC,0x6,0x5,0x2,0xB,0x0,0x9,0xD,0x3,0xE,0x7,0xA,0xF,0x4,0x1,0x8
    };
    
    private static byte[] ESbox_A = {
         0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5,
         0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1,
         0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9,
         0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6,
         0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6,
         0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6,
         0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE,
         0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4
    };
    
    private static byte[] ESbox_B = {
         0x8,0x4,0xB,0x1,0x3,0x5,0x0,0x9,0x2,0xE,0xA,0xC,0xD,0x6,0x7,0xF,
         0x0,0x1,0x2,0xA,0x4,0xD,0x5,0xC,0x9,0x7,0x3,0xF,0xB,0x8,0x6,0xE,
         0xE,0xC,0x0,0xA,0x9,0x2,0xD,0xB,0x7,0x5,0x8,0xF,0x3,0x6,0x1,0x4,
         0x7,0x5,0x0,0xD,0xB,0x6,0x1,0x2,0x3,0xA,0xC,0xF,0x4,0xE,0x9,0x8,
         0x2,0x7,0xC,0xF,0x9,0x5,0xA,0xB,0x1,0x4,0x0,0xD,0x6,0x8,0xE,0x3,
         0x8,0x3,0x2,0x6,0x4,0xD,0xE,0xB,0xC,0x1,0x7,0xF,0xA,0x0,0x9,0x5,
         0x5,0x2,0xA,0xB,0x9,0x1,0xC,0x3,0x7,0x4,0xD,0x0,0x6,0xF,0x8,0xE,
         0x0,0x4,0xB,0xE,0x8,0x3,0x7,0x1,0xA,0x2,0x9,0x6,0xF,0xD,0x5,0xC
    };
    
    private static byte[] ESbox_C = {
         0x1,0xB,0xC,0x2,0x9,0xD,0x0,0xF,0x4,0x5,0x8,0xE,0xA,0x7,0x6,0x3,
         0x0,0x1,0x7,0xD,0xB,0x4,0x5,0x2,0x8,0xE,0xF,0xC,0x9,0xA,0x6,0x3,
         0x8,0x2,0x5,0x0,0x4,0x9,0xF,0xA,0x3,0x7,0xC,0xD,0x6,0xE,0x1,0xB,
         0x3,0x6,0x0,0x1,0x5,0xD,0xA,0x8,0xB,0x2,0x9,0x7,0xE,0xF,0xC,0x4,
         0x8,0xD,0xB,0x0,0x4,0x5,0x1,0x2,0x9,0x3,0xC,0xE,0x6,0xF,0xA,0x7,
         0xC,0x9,0xB,0x1,0x8,0xE,0x2,0x4,0x7,0x3,0x6,0x5,0xA,0x0,0xF,0xD,
         0xA,0x9,0x6,0x8,0xD,0xE,0x2,0x0,0xF,0x3,0x5,0xB,0x4,0x1,0xC,0x7,
         0x7,0x4,0x0,0x5,0xA,0x2,0xF,0xE,0xC,0x6,0x1,0xB,0xD,0x9,0x3,0x8
    };
    
    private static byte[] ESbox_D = {
         0xF,0xC,0x2,0xA,0x6,0x4,0x5,0x0,0x7,0x9,0xE,0xD,0x1,0xB,0x8,0x3,
         0xB,0x6,0x3,0x4,0xC,0xF,0xE,0x2,0x7,0xD,0x8,0x0,0x5,0xA,0x9,0x1,
         0x1,0xC,0xB,0x0,0xF,0xE,0x6,0x5,0xA,0xD,0x4,0x8,0x9,0x3,0x7,0x2,
         0x1,0x5,0xE,0xC,0xA,0x7,0x0,0xD,0x6,0x2,0xB,0x4,0x9,0x3,0xF,0x8,
         0x0,0xC,0x8,0x9,0xD,0x2,0xA,0xB,0x7,0x3,0x6,0x5,0x4,0xE,0xF,0x1,
         0x8,0x0,0xF,0x3,0x2,0x5,0xE,0xB,0x1,0xA,0x4,0x7,0xC,0x9,0xD,0x6,
         0x3,0x0,0x6,0xF,0x1,0xE,0x9,0x2,0xD,0x8,0xC,0x4,0xB,0xA,0x5,0x7,
         0x1,0xA,0x6,0x8,0xF,0xB,0x0,0x4,0xC,0x3,0x5,0x9,0x7,0xD,0x2,0xE
    };
    
    //S-box for digest
    private static byte DSbox_Test[] = {
         0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3,
         0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9,
         0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB,
         0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3,
         0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2,
         0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE,
         0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC,
         0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC
    };
    
    private static byte DSbox_A[] = {
         0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF,
         0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8,
         0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD,
         0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3,
         0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5,
         0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3,
         0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB,
         0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC
    };

Bagaimana kita dapat menggunakan Sbox tersebut?, secara default Sbox yang digunakan adalah SBox private byte S[]. Seperti Script dibawah ini yang menggunakan Sbox default:

public class Gost_ChangeSbox {
	public static void main (String[] args) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
		byte[]        input = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
		//GOST
				byte[] keyBytes = new byte[] { 
		        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				}; //256 bytes
		        SecretKeySpec key = new SecretKeySpec(keyBytes, "GOST28147");
		      
      
        Cipher        cipher = Cipher.getInstance("GOST28147/ECB/NoPadding","BC");
        // encryption pass
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
        int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
        ctLength += cipher.doFinal(cipherText, ctLength);
       
        // decryption pass
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] plainText = new byte[cipher.getOutputSize(ctLength)];
        int ptLength = cipher.update(cipherText, 0, ctLength, plainText, 0);  
        ptLength += cipher.doFinal(plainText, ptLength);
      
	}
}

kita ingin menggunakan Sbox ESbox_A, maka kita perlu mengeset parameter terlebih dahulu, perhatikan script lengkapnya sebagai berikut:

public class Gost_ChangeSbox {
	public static void main (String[] args) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
		byte[]        input = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
		//GOST
				byte[] keyBytes = new byte[] { 
		        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				}; //256 bytes
		        SecretKeySpec key = new SecretKeySpec(keyBytes, "GOST28147");
		       
        Cipher        cipher = Cipher.getInstance("GOST28147/ECB/NoPadding","BC");
       
        // encryption pass
        GOST28147ParameterSpec paramss = new GOST28147ParameterSpec (GOST28147Engine.getSBox("E-A"));
        
        cipher.init(Cipher.ENCRYPT_MODE, key, paramss);
        //cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
        int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
        ctLength += cipher.doFinal(cipherText, ctLength);
        
        // decryption pass
        cipher.init(Cipher.DECRYPT_MODE, key, paramss);
        byte[] plainText = new byte[cipher.getOutputSize(ctLength)];
        int ptLength = cipher.update(cipherText, 0, ctLength, plainText, 0);  
        ptLength += cipher.doFinal(plainText, ptLength);
       
	}
}


Konversi 4 bytes ke 32 bit unsigned integer (java)


misal kita dihadapkan case bagaimana untuk menkonversi 4 bytes kedalam 32 bit integer, misal:
data = {0x01, 0x03, (byte) 0xFF , 0x01}; kita ingin mendapatkan nilai 17039105 atau yang jika direpresentasikan dalam bit adalah 0x0103FF01 = 00000001 00000011 11111111 00000001, didalam java kita dapat menggunakan pergeseran bit (<<) sebagai salah satu alternatif untuk memecahkan masalah tersebut, berikut script sederhananya:

public class getUInt32 {
public static void main (String[] args) {
byte [] keyB = {0x01, 0x03, (byte) 0xFF , 0x01};
long key;
key = )((keyB[0] << 24) & 0xFFFFFFFF) | ((keyB[1] << 16) & 0xFFFFFF ) | ((keyB[2] << 8) & 0xFFFF ) | (keyB[3] & 0xFF)) & 0x00000000FFFFFFFFL ;
System.out.print(key);
}
}