Merubah dari Bytes ke Bentuk Hexadecimal & Contoh Enkripsi simple menggunakan algoritma simetrik


Enkripsi menggunakan JCE-JCA baik menggunakan provider bawaan java ataupun provider lain seperti BC mempunyai inputan, outputan dan kunci beupa array byte sesuai dengan panjang dari spesifikasi algoritma tersebut. Untuk memudahkan verifikasi hasil khususnya didalam console print kita dapat menggunakan format hexadecimal sebagai representasi dari data array byte, sebagai contoh berikut:

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

data diatas jika kita langsung System.out.println(input); maka hasil yang kita dapatkan adalah [B@372ea2bc, tidak sesuai dengan reperesentasi byte yang kita inginkan oleh karena itu diperlukan fungsi sebagai berikut

public class Utils
{
    private static String digits = "0123456789abcdef";
    /**
     * Return length many bytes of the passed in byte array as a hex string.
     *
     * @param data the bytes to be converted.
     * @param length the number of bytes in the data block to be converted.
     * @return a hex representation of length bytes of data.
     */
    public static String toHex(byte[] data, int length)
    {
        StringBuffer    buf = new StringBuffer();
        for (int i = 0; i != length; i++)
        {
            int v = data[i] & 0xff;
            buf.append(digits.charAt(v >> 4));
            buf.append(digits.charAt(v & 0xf));
        }
        return buf.toString();
    }
    /**
     * Return the passed in byte array as a hex string.
     *
     * @param data the bytes to be converted.
     * @return a hex representation of data.
     */
    public static String toHex(byte[] data)
    {
        return toHex(data, data.length);
    }
}

sebagai contoh, fungsi tersebut kita gunakan untuk Enkirpsi menggunakan AES dengan mode ECB dan tanpa padding, sebagai berikut:

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class SimpleSymmetricExample
{
    public static void main(String[] args) throws Exception
    {
        byte[]        input = new byte[] {
                          0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
                          (byte)0x88, (byte)0x99, (byte)0xaa, (byte)0xbb,
                          (byte)0xcc, (byte)0xdd, (byte)0xee, (byte)0xff };
        byte[]        keyBytes = new byte[] {
                          0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                          0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
                          0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };
        SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
        Cipher        cipher = Cipher.getInstance("AES/ECB/NoPadding", "BC");
        System.out.println("input text : " + Utils.toHex(input));
        // encryption pass
        byte[] cipherText = new byte[input.length];
        cipher.init(Cipher.ENCRYPT_MODE, key);
        int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
        ctLength += cipher.doFinal(cipherText, ctLength);
        System.out.println("cipher text: " + Utils.toHex(cipherText)
                                                     + " bytes: " + ctLength);

        // decryption pass
        byte[] plainText = new byte[ctLength];
        cipher.init(Cipher.DECRYPT_MODE, key);
        int ptLength = cipher.update(cipherText, 0, ctLength, plainText, 0);
        ptLength += cipher.doFinal(plainText, ptLength);
        System.out.println("plain text : " + Utils.toHex(plainText)
                                                     + " bytes: " + ptLength);
    }
}

maka hasil yang kita dapatkan sebagai berikut:
input text : 00112233445566778899aabbccddeeff
cipher text: dda97ca4864cdfe06eaf70a0ec0d7191 bytes: 16
plain text : 00112233445566778899aabbccddeeff bytes: 16

Mengirim multiple Email menggunakan SSL Java


Kali ini misal kita dihadapkan case sebagai berikut:
– Kirimkan email berikut gambar dan attachment ke 20 list penerima
– email harus bersifat personal atau tanpa menggabung alamat-alamat email tersebut kedalam satu surat
– Judul disisipkan Nama penerima , dan juga format message disisipkan nama lengkap dan nama panggilan
– format message yang dimaksud sebagai berikut:

Continue reading “Mengirim multiple Email menggunakan SSL Java”

Install provider Bouncy castle


Sebenarnya kita dapat menggunakan library bawaan java yaoti JCA dan JCE, namun kali ini kita menggunakan provider lain yaitu Bouncy castle, BC sendiri adalah salah satu komunitas open source yang memiliki interest kebidang kirptografi sejak tahun 1990 khususnya didalam pemograman c# dan java. BC sendiri sudah mendukung algoritma kriptografi simetrik seperti GOST. Untuk menginstall dan menEnableKan berikut langkah-langkahnya

tambahkan didalam line berikut list provider java.security didirektori /usr/lib/jvm/java-8-oracle/jre/lib/security

security.provider.N=org.bouncycastle.jce.provider.BouncyCastleProvider

N adalah urutan sesuai nomor urut yang terdapat didalam java.security anda, sebagai contoh

#
# List of providers and their preference orders (see above):
#
security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
security.provider.3=sun.security.ec.SunEC
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC

maka tambahkandilne setelah N=9: security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider

setelah itu install library bcprov-JdkVersion-Version.jar. sesuai versi yang anda inginkan, .jar dapat didownload di https://www.bouncycastle.org/latest_releases.html

cek apakah BC sudah terinstall:


import java.security.Security;
/**
* Basic class to confirm the Bouncy Castle provider is
* installed.
*/
public class SimpleProviderTest
{
public static void main(String[] args)
{
String providerName = "BC";
if (Security.getProvider(providerName) == null)
{
System.out.println(providerName + " provider not installed");
}
else
{
System.out.println(providerName + " is installed.");
}
}
}

Jika sudah di console akan terprint
BC is installed.

Continue reading “Install provider Bouncy castle”

Kompas.com vs Detik.com Lanjutan (bagian 2)


Web scraping adalah salah satu teknik yang digunakan oleh untuk mengekstrasi informasi dari website.
Kali ini akan dilakukan scraping kepada media daring kompas.com dan detik.com menggunakan java sebagai bahasa pemograman dan mysql sebagai database, scrapping dilakukan dari Wed Apr 13 13:48:03 SAMT 2016 sampai dengan Thu Apr 14 19:20:03 SAMT 2016 dengan interval 3 kali scraping/ 2-3 detik
Data yang diambil dari kedua website tersebut adalah data berita dengan rincian: Waktu berita, Judul berita, link berita secara berturut-turut berdasarkan waktu posting. Dan data scraping tersebut telah mengalami sortir sehingga tidak terjadi duplikasi terhadap link berita. Jumlah data yg berhasil discraping sebanyak 1338 Judul berita dengan kompas.com sebanyak 721 dan detik.com sebanyak 616 judul berita
Salah satu tujuan dari scraping website tersebut adalah ingin mengetahui seberapa sering nama-nama ditulis dalam Judul berita berdasarkan kata kunci sebagai berikut:
gambar 1,2,3: joko, ahok, yusril, lulung, griezmann, jk, rio, messi, sunny, nyalla, zaskia, aguan
gambar 3,4,5: kpk, polri, jaksa, presiden, dpr, dprd, bpk, bumn, gubernur, menteri, kejagung, polisi
Hasil yang didapatkan sebagai berikut:

f

e

d

c

b

a

Kompas.com vs Detik.com


Oke, kali ini kita mencoba mengulik tentang scraping website. Scraping website gampangnya adalah suatu teknik mengambil data (text, gambar, link, dll) yang berasal dari website. Website media daring atau online adalah website yang memiliki pergerakan yang luar biasa, yang saya maksud adalah update dilaman utamanya, nanti kita liat lebih detail lagi. Saya mencoba memilih kompas.com dan detik.com, alasannya adalah kekesalan saya terhadap berita tentang fauzi bowo, dikarenakan sangat sedikit sekali berita tentang beliau, padahal beliau menjabat menjadi wakil gubernur DKI jakarta selama 5 tahun! dan juga menjabat gubernur DKI jakarta selama 5 tahun!, dan tidak ketinggalan menjadi sekda selama 4 tahun! tetapi apa daya berita tentang beliau hampir tidak ada di media daring di waktu waktu ini, yang ada berita tentang ….

Okeh lupakan sejenak tentang om bowo, sebenernya kalau mau gampang kalian bisa datang ke kantor nya kompas, meminta dengan baik-baik data website kompas.com, data yg kalian bisa minta adalah judul dari newsfeed, jam berapa, judul postingannya. Dari data tersebut kita bisa melihat seberapa sering fauzi bowo (lagi) menjadi judul berita kompas.com. Atau kalian ingin tau lagi kalian bisa dapat jam kerja tukang posting dari website tersebut, kira kira kalau malam-malam dia kerja ngak ya?? Namun karena saya ngak mau dateng ke kantor kompas atau detik karena sangat tidak efektif! mengapa tidak efektif? …………

Oke, tools yang saya gunakan dalam scrapping adalah, Java dengan bantuan libary Jsoup, Mysql, dan tentunya komputer dan internet, skema sederhana nya bisa dilihat sebagai berikut:
DSC_0006

hasil yang saya dapatkan sebagai berikut:
Scrapping dilakukan pada waktu Wed Apr 13 13:48:03 SAMT 2016 sampai dengan Thu Apr 14 08:03:30 SAMT 2016 atau Hari Rabu 13 April 2016 pukul 13:48:03 sampai dengan Hari Kamis 14 April 2016 pukul 11:03:30 kurang lebih 18 jam 15 menit 27 detik

Screenshot from 2016-04-14 08:03:55

Kompas unggul dalam jumlah postingan dibanding detik dalam kurun waktu tersebut, artinya karyawan kompas lebih rajin dibanding detik, jika kita rata-ratakan maka dalam satu jam kompas berhasil memposting 19 berita

Sekarang kita coba lihat berapa kali Presiden Jokowi dengan keysearch ‘joko’ (jikalau ki joko bodo menjadi judul berita maka akan ada error)
Screenshot from 2016-04-14 08:23:39
Screenshot from 2016-04-14 08:25:04

Dikompas Jokowi unggul 11 posting dibanding detik yang ‘hanya’ 7. Dan kebetulan ki Joko Bodo tidak ada yang ada Djokovic (error 1)

Oke, sekarang kita test coba tebak lebih banyak berita dengan keysearch di judul ‘bola’ atau berita dengan keysearch di judul ‘indonesia’, kenapa tidak dengan bulutangkis misalnya? karena hasilnya sudah ketahuan
Screenshot from 2016-04-14 08:56:39
Screenshot from 2016-04-14 08:57:18

Ternyata Bola unggul 54 point dibanding Indonesia yang hanya mendapat 27 point, hal ini bisa dimaklumi dikarenakan semalam adalah liga champion!

Kembali ke revenge Fauzi Bowo, seltelah mantan gubernur DKI jakarta kita sudah periksa di atas, sekarang kita check ‘musuh bebuyutan’ (judul film yg dibintangi oleh benyamin) dari Fauzi Bowo
Screenshot from 2016-04-14 09:05:44

32 point lebih banyak dari keysearch Indonesia, tapi tetep masih kalah sama anak bola!

Sekarang kalau penasaran sama si tukang posting di kompas.com sama detik.com jam kerjanya, kita bisa liat dari time posting newsfeed tersebut, data waktu disini mungkin terdapat selisih sampai 1 menit dengan postingan nya, karena data waktu yang saya dapatkan adalah data waktu execute program java pada saat parsing
DSC_0006bb

sayangnya jam 8,9,10,11 masih belum full tercaputre, (catatan waktu menggunakan samara time atau 3 jam lebih lambat dibanding WIB, jadi kalau jam 9 tertulis digrafik berarti jam 12 waktu WIB).

update data waktu posting dan sudah dikonverter kedalam WIB
DSC_0006bbc

Dari waktu grafik waktu tersebut kita bisa liat tukang posting mengalami penurunan produktifitas postingan nya selepas jam 18 SMT atau 21 WIB dan menanjak lagi di 03 SMT atau 06 WIB, artinya apa? karena tukang posting manusia juga dan siapa juga yang baca berita malem-malem!

Pesan moral yg bisa diambil adalah kurangilah membaca media daring! perbanyak baca buku!

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");

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);
}
}

Enkripsi Citra menggunakan javax.crypto bagian 2


Setelah kita mencoba membuat enkripsi citra http://wp.me/prw8r-1cR, namun hasil enkripsi tidak dapat dilihat dikarenakan perubahan pada header citra digital yang menyebabkan komputer tidak dapat mendeteksi type file dll.

setidaknya ada 2 alternatif untuk mengatasi masalah tersebut, alternatif pertama adalah enkripsi dilakukan hanya pada byte nilai pixel dan juga enkripsi tidak dilakukan pada file-file header. Cara tersebut sangat cocok bagi type file uncompressed seperti .bmp dikarenakan niai-nilai byte pada pixel berkisar antara 0-255 dan memiliki letak posisi yang jelas pada posisi format byte. sebagai contoh berikut

Screenshot from 2016-01-27 09:13:52

perhatikan pada posisi byte ke 10 dengan nilai 0x36 dalam format .bmp kita dapat mendapatkan posisi awal dari nilai pixel yaitu pada byte ke 36, detailnya bisa dilihat di https://en.wikipedia.org/wiki/BMP_file_format dengan begitu kita dapat mengenkripsi hanya pada nilai pixel nya tanpa mengenkripsi headernya atau informasi lainnya.


import imageEncryption.ImageBMP;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.imageio.ImageIO;

	public class Des_imagebezheader {
		KeyGenerator keyGenerator = null;  
	    SecretKey secretKey = null;  
	    Cipher cipher = null;  
	  
	    public Des_imagebezheader() {  
	        try {   
	            keyGenerator = KeyGenerator.getInstance("DES");  
	            secretKey = keyGenerator.generateKey();  
	            
	            
	            cipher = Cipher.getInstance("DES/ECB/NoPadding");  
	        } catch (NoSuchPaddingException ex) {  
	            System.out.println(ex);  
	        } catch (NoSuchAlgorithmException ex) {  
	            System.out.println(ex);  
	        }  
	    }  
	    
	    public static void main(String[] args) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, IOException {  
	        String fileToEncrypt = "XING_B24.BMP";  
	        String encryptedFile = "encryptXING_B24.bmp";  
	        String decryptedFile = "decryptXING_B24.bmp";    
	        String directoryPath = "/media/ratjoen/javaFiles/Izhobrazhenie_KriptografiyV3.0L/";  
	        Des_imagebezheader encryptFile = new Des_imagebezheader();  
	        System.out.println("Starting Encryption...");  
	        encryptFile.encrypt(directoryPath + fileToEncrypt,  
	                directoryPath + encryptedFile);  
	        System.out.println("Encryption completed...");   
	        
	        System.out.println("Starting Decryption...");  
	        encryptFile.decrypt(directoryPath + encryptedFile,  
	                directoryPath + decryptedFile);  
	        System.out.println("Decryption completed...");
	    }  
	    
	    private void encrypt(String srcPath, String destPath) throws InvalidKeyException, IOException, IllegalBlockSizeException, BadPaddingException {  
	        File rawFile = new File(srcPath);  
	        File encryptedFile = new File(destPath);  
	        InputStream inStream = null;  
	        OutputStream outStream = null;  
	     
	        cipher.init(Cipher.ENCRYPT_MODE, secretKey);  
	        
	        try {
	        inStream = new FileInputStream(rawFile);
	        outStream = new FileOutputStream(encryptedFile);  

	        int lengfile = (int) rawFile.length() ;
	       
	        byte[] buffer = new byte[lengfile]; 
	        inStream.read(buffer);
	        
	        System.out.println(buffer.length);
	        int startP = buffer[10];//for bmp format
	        System.out.println(startP);
	        
	        int lengthE = lengfile-startP;
	       
	        
	        byte[] bufferE = new byte[lengthE]; 
	       
	        for (int i = 0; i < bufferE.length ; i++){
	        	bufferE[i]=buffer[i+startP];
	        }
	        
	        byte[] bufferP = new byte[lengthE]; 
	        
	        cipher.update(bufferE, 0, lengthE , bufferP, 0);
	        cipher.doFinal(bufferP);  
	        
	        for (int i = 0; i < bufferE.length ; i++){
	        	buffer[i+startP]=bufferP[i];
	        }
	        
	        outStream.write(buffer);  
            outStream.flush();
	       
	        }catch(Exception e){
	        	e.printStackTrace();
	        }
	    }
	           	 
	          
	    private void decrypt(String srcPath, String destPath) throws InvalidKeyException, IOException, IllegalBlockSizeException, BadPaddingException {  
	        File rawFile = new File(srcPath);  
	        File encryptedFile = new File(destPath);  
	        InputStream inStream = null;  
	        OutputStream outStream = null;  
	     
	        cipher.init(Cipher.DECRYPT_MODE, secretKey);  
	        
	        try {
	        inStream = new FileInputStream(rawFile);
	        outStream = new FileOutputStream(encryptedFile);  

	        int lengfile = (int) rawFile.length() ;
	        String Format = rawFile.getName();
	        byte[] buffer = new byte[lengfile]; 
	        inStream.read(buffer);
	        
	        System.out.println(buffer.length);
	        int startP = buffer[10];//for bmp format
	        System.out.println(startP);
	        
	        int lengthE = lengfile-startP;
	       
	        
	        byte[] bufferE = new byte[lengthE]; 
	       
	        for (int i = 0; i < bufferE.length ; i++){
	        	bufferE[i]=buffer[i+startP];
	        }
	        
	        byte[] bufferP = new byte[lengthE]; 
	        
	        cipher.update(bufferE, 0, lengthE , bufferP, 0);
	        cipher.doFinal(bufferP);  
	        
	        for (int i = 0; i < bufferE.length ; i++){
	        	buffer[i+startP]=bufferP[i];
	        }
	        
	        outStream.write(buffer);  
            outStream.flush();
	       
	        }catch(Exception e){
	        	e.printStackTrace();
	        }
	    }        
	}

Screenshot from 2016-01-27 09:34:08

Screenshot from 2016-01-27 09:34:00

Enkripsi Citra menggunakan javax.crypto


kali ini kita akan mencoba mengenkripsi citra menggunakan javax.crypto, beberapa library lainnya juga kita gunakan untuk menunjanng agar data berupa image dapat di enkripsi. Salah satu source code yang tersedia di internet adalah sebagai berikut http://www.theinsanetechie.in/2011/09/java-data-encryption-standard-des.html

package dataencryptionstandart;

import java.io.File;  
import java.io.FileInputStream;  
import java.io.FileNotFoundException;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.OutputStream;  
import java.security.InvalidKeyException;  
import java.security.NoSuchAlgorithmException;  
import javax.crypto.BadPaddingException;  
import javax.crypto.Cipher;  
import javax.crypto.IllegalBlockSizeException;  
import javax.crypto.KeyGenerator;  
import javax.crypto.NoSuchPaddingException;  
import javax.crypto.SecretKey;  
  
/** 
 * 
 * @author dhanoopbhaskar 
 */  
public class desimage {  
  
    KeyGenerator keyGenerator = null;  
    SecretKey secretKey = null;  
    Cipher cipher = null;  
  
    public desimage() {  
        try {   
            keyGenerator = KeyGenerator.getInstance("DES");  
            secretKey = keyGenerator.generateKey();  
            cipher = Cipher.getInstance("DES");  
        } catch (NoSuchPaddingException ex) {  
            System.out.println(ex);  
        } catch (NoSuchAlgorithmException ex) {  
            System.out.println(ex);  
        }  
    }  
  
    public static void main(String[] args) {  
        String fileToEncrypt = "5.png";  
        String encryptedFile = "encryptedFile.png";  
        String decryptedFile = "decryptedFile.png";  
        String directoryPath = "/media/ratjoen/javaFiles/Izhobrazhenie_KriptografiyV3.0L/";  
        desimage encryptFile = new desimage();  
        System.out.println("Starting Encryption...");  
        encryptFile.encrypt(directoryPath + fileToEncrypt,  
                directoryPath + encryptedFile);  
        System.out.println("Encryption completed...");  
        System.out.println("Starting Decryption...");  
        encryptFile.decrypt(directoryPath + encryptedFile,  
                directoryPath + decryptedFile);  
        System.out.println("Decryption completed...");  
    }  
  
    /** 
     *  
     * @param srcPath 
     * @param destPath 
     * 
     * Encrypts the file in srcPath and creates a file in destPath 
     */  
    private void encrypt(String srcPath, String destPath) {  
        File rawFile = new File(srcPath);  
        File encryptedFile = new File(destPath);  
        InputStream inStream = null;  
        OutputStream outStream = null;  
        try {  
            /** 
             * Initialize the cipher for encryption 
             */  
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);  
            /** 
             * Initialize input and output streams 
             */  
            inStream = new FileInputStream(rawFile);  
            outStream = new FileOutputStream(encryptedFile);  
            byte[] buffer = new byte[1024];  
            int len;  
            while ((len = inStream.read(buffer)) > 0) {  
                outStream.write(cipher.update(buffer, 0, len));  
                outStream.flush();  
            }  
            outStream.write(cipher.doFinal());  
            inStream.close();  
            outStream.close();  
        } catch (IllegalBlockSizeException ex) {  
            System.out.println(ex);  
        } catch (BadPaddingException ex) {  
            System.out.println(ex);  
        } catch (InvalidKeyException ex) {  
            System.out.println(ex);  
        } catch (FileNotFoundException ex) {  
            System.out.println(ex);  
        } catch (IOException ex) {  
            System.out.println(ex);  
        }  
    }  
  
    /** 
     *  
     * @param srcPath 
     * @param destPath 
     * 
     * Decrypts the file in srcPath and creates a file in destPath 
     */  
    private void decrypt(String srcPath, String destPath) {  
        File encryptedFile = new File(srcPath);  
        File decryptedFile = new File(destPath);  
        InputStream inStream = null;  
        OutputStream outStream = null;  
        try {  
            /** 
             * Initialize the cipher for decryption 
             */  
            cipher.init(Cipher.DECRYPT_MODE, secretKey);  
            /** 
             * Initialize input and output streams 
             */  
            inStream = new FileInputStream(encryptedFile);  
            outStream = new FileOutputStream(decryptedFile);  
            byte[] buffer = new byte[1024];  
            int len;  
            while ((len = inStream.read(buffer)) > 0) {  
                outStream.write(cipher.update(buffer, 0, len));  
                outStream.flush();  
            }  
            outStream.write(cipher.doFinal());  
            inStream.close();  
            outStream.close();  
        } catch (IllegalBlockSizeException ex) {  
            System.out.println(ex);  
        } catch (BadPaddingException ex) {  
            System.out.println(ex);  
        } catch (InvalidKeyException ex) {  
            System.out.println(ex);  
        } catch (FileNotFoundException ex) {  
            System.out.println(ex);  
        } catch (IOException ex) {  
            System.out.println(ex);  
        }  
    }  
}  

namun hasil yang diharapkan kurang sesuai dengan yang saya inginkan dikarenakan hasil enkripsi tidak dapat dibuka
Screenshot from 2016-01-21 15:55:16

mengapa hal tersebut terjadi, kita bisa lihat detailnya dalam hex menggunakan xxd pada linux command

File asli:
Screenshot from 2016-01-21 15:56:37

File terenkripsi
Screenshot from 2016-01-21 15:58:09

dari capture hex tersebut kita bisa lihat di baris pertama bahwa 8950 yang merupakan extensi dari .PNG juga ikut terenkripsi menjadi 0eda hal tersebut menyebabkan tidak dapat nya komputer mendisplay citra yang telah terenkripsi. namun saat sudah file yang telah terdekripsi dapat terdisplay karena hex kembali seperti semula

bagaimana caranya agar kita tidak mengenkripsi file format header, tetapi hanya nilai pixel nya?

How Do You Know the Policy Files Really Behave as Sun Says They Do?


When you look at the history behind the JCE, it is easy to see why some people would be inclined to feel it is all a conspiracy by Sun, the U.S. government, the UN, the Illuminati, the Greys, or some other “organization” and that anything running under the JCE should not be trusted, as you cannot see the code that deals with key strength and various other control mechanisms that the policy files allow you to turn on or off. If this is a concern for you, remember, just as you would test a hardware cryptography adapter by comparing its outputs for given inputs against the outputs produced by an alternative implementation for the same set of outputs, you can also treat the JCE and the underlying provider as a black box and perform the same tests. As it happens the Bouncy Castle provider was first developed as a lightweight library for MIDP, so if you are feeling really enthused, you can start by verifying that the Bouncy Castle provider and the JCE is producing the same output as its lightweight equivalent. It is true that in matters like these you should not take what people tell you at face value, but always remember you can test and investigate the truth of other people’s claims yourself.

David Hook-Beginning Cryptography with Java-Wrox (2005)

Buku Cryptography for Internet and Database Applications


salah satu buku tentang kriptografi yang recommended Cryptography for Internet and Database Applications Developing Secret and Public Key Techniques with JavaTM oleh Nick Galbreath,

berikut daftar isi dari buku tersebut

Chapter 1 Bits and Bytes
General Operations
Number Bases
Bits and Bytes
Signed Bytes
Bitwise Operators
Complementation or Bitwise NOT
Bitwise AND
Bitwise OR
Bitwise Exclusive OR (XOR)
Left-Shift
Right-Shift
Special Operations and Abbreviations
Packed Words
Integers and Endian Notation
Java Numerics
Basic Types
Type Conversion
Unsigned to Signed Conversions
Overflow
Arrays
Numeric Classes
Booleans and BitFields
Chars
Working with Bytes
Sign Problems
Conversion of Integral Types to Byte Arrays
Converting to Hex Strings
BigInteger
Creating and Converting
BigInteger and Cryptography
Secret Methods in BigInteger

Chapter 2 Secret Key Cryptography
Symmetric Block Ciphers
Cipher Properties
Security Properties
Brute-Force Attacks
Other Attacks
Common Block Ciphers
Data Encryption Standard (DES)
Triple DES
Blowfish
IDEA
RC5
Rijndael and the Advanced Encryption Standard (AES)
Twofish
RC6
Ciphers You Shouldn’t Use
Password XOR Schemes
Classical Cryptography
ROT 13
Padding
Fixed-Value Padding
Random Padding
PKCS Padding
Modes of Operations
Initialization Vectors
Electronic Codebook Mode (ECB)
Cipher Block Chaining Mode (CBC)
Cipher Feedback Mode (CFB)
Output Feedback Mode (OFB)
Counter Mode (CTR)
Propagating CBC (PCBC) Mode
Key Wrapping
Triple DES KEY Wrapping
AES Key Wrapping
Turning Passwords into Keys
Elliptic Curves
Underlying Mathematics: Elliptic Curves
The Algorithm
Standards and Practice
Other Public Key Cryptographic Systems
Rabin Cryptosystem
NTRU

Chapter 4
Summary
Random Numbers
Randomness and Security
Testing for Randomness
FIPS 140-2 Requirements
Pseudorandom Number Generators
Cryptographic PRNG
SHA-1 PRNG
Cipher-CBC or ANSI X9.17
FIPS 186
Blum-Blum-Shub
Stream Ciphers
One-Time Pads
RC4 or ArcFour
Using Randomness
Generating Random Numbers for Gaming
Generating Random Numbers in a Range
Shuffling
Generating Random Permutations
Small Permutations
Large Fixed Permutations
Random Sampling
Accessing Entropy
OS Services
Win32 CryptoAPI CryptGenRandom
/dev/random and friends
Userland Services
Entropy Generating Daemon (EGD)
PRNGD
Yarrow and EGADS
TrueRand Library
Remote Services
RAND Corporation
HotBits
Random.org
LavaRnd
Java and Random Numbers
Random and SecureRandom
java.util.random
java.security.SecureRandom
Developer Issues
Reseeding
Collecting Entropy
An Entropy Pool Implementation
Basic System State
Thread Schemes
Reading External Sources
Application Events
User Events

Chapter 5 Java Cryptography
Organization
Providers and Engine Classes
Parameters, Keys, and Certificates
Error Handling
Providers
Standard Names
Standard Sun and SunJCE Providers
Other Providers
Initializing Providers
Writing Your Own Provider
Core Engine Classes
MessageDigest
Digest Streams
MAC
SecureRandom
Ciphers
Additional Cipher-Related Objects
Signatures
SignedObject
Key Agreement Protocols
Parameters, Keys, and Certificates
Algorithm Parameters
AlgorithmParameters
AlgorithmParameterGenerators
Keys
Secret Keys
Public/Private Keys
Encoding and Encrypting Keys
Summary 202

Chapter 6 Small Message Encoding and Encryption
Preprocessing 203
Converting Digits into Bytes
7-bit to 8-bit Compression
General Compression and java.util.zip.Deflate
Adding Check and Parity Bits
Small Message Encryption
Single-Block Encryption
n-Block Encryption
Very Small Message Encryption
XOR Tables
Small Codebooks
RC5-16/16
Small Message Encoding
Encoding for Customer-Usable Data
Capacity and Range
Selecting a Base Representation
Selecting Base Alphabets
Mixed Bases and Alphabets
Adding Check Digits
Encoding for Machines and Customer-Visible Applications
Base 64
Base 85
Base 128 and Java Source Encoding

Chapter 7 Application and Data Architecture
Database Architecture for Encrypted Data
Selecting a Cipher
Secret or Public?
Cipher Selection
Data
Passwords
Challenges and Responses
Payment, Credit Card, and Other Account Numbers
Social Security Number (U.S.)
Birthdates and Birthdays
Last Name
Searching, Indexing, and Constraints
Removing Randomness
Deterministic Key Selection
Indexing and Hashing
Uniqueness Constraints
Asymmetric Data Usages
Null Values and Database Applications
Secure Memory Management in Java
Smart Array Classes
Char Arrays
Using SecureRandom
Secret Key Management
Secret Key Data
Key Generation
Key Encryption
Storage
Key Access and Distribution
Using Keys with Ciphers and MACs
Passwords
Startup Passwords
Member Names and Passwords
Selecting Passwords
Member Login, Success and Failure
Changing Passwords and Challenges
Web-Based Password Entry
Generating New Passwords
Member Names
Logging
Embedded-Encryption Logging
Fully Encrypted Log Files
Public Key Logging
Split Log Files
Network-Based Logs
Cryptographic Tokens and Applications
Token Design
Expirations and Time Quantization
Creating the Security Bits
URL Tokens
Tamper-Evident URLs
Protecting Static Content
A Simple URL MAC Implementation
Fast Query String Parsing
URL Encryption
Very Short URLs
Cookie Tokens
Detecting Cookie Capability
Cookies and Authentication
Tokens for Access Control
Buy-on-Demand Systems
Multiple Key Systems
Trials and Expirations
Decimal and Monetary Computations
Doubles and Floats
BigDecimal
Rounding
BigDecimal and Mathematics
BigDecimal Alternatives and Wrappers
Usage and Storage