Rabu, 30 Oktober 2024

Punya Banyak Akun dan Attack Surface

Dalam dunia siber/internet, terdapat istilah attack vector dan attack surface. Suatu attack vector adalah cara-cara untuk menerobos masuk ke suatu sistem informasi. Dengan kata lain, ini adalah lubang dalam keamanan sistem informasi. Istilah vector diambil dari konsep dalam biologi. Kumpulan attack vector disebut sebagai attack surface. Penting untuk mempersempit attack surface dalam suatu sistem, baik dari pihak pengelola sistem maupun dari pihak penggunanya.

Pengelola sistem bisa mengamankan sistemnya, misal dengan memastikan keamanan tiap titik ujung (attack surface). Selain itu, pemeriksaan rutin terhadap otorisasi dan hak tiap pengguna juga diperlukan.

Di sisi lain, kita sebagai pengguna sistem juga perlu mengamankan akun kita. Pada masa sekarang ini, sudah banyak yang sedikit-sedikit buat akun sehingga kita jadi punya banyak sekali akun di berbagai sistem/layanan. Makin banyak sistem tempat kita punya akun, makin luas pula attack surface akun kita di internet. Bagaimana caranya?

Karena kita belum tentu bisa mengamankan sistem yang kita pakai, kita hanya bisa mempercayakannya kepada pengelola sistem tersebut. Yang bisa kita lakukan, antara lain, berikut:

  • menggunakan sandi yang aman (tidak berisi hal-hal/informasi/deskripsi diri);
  • menggunakan sandi yang berbeda untuk tiap akun/platform/sistem (tidak menggunakan sandi berulang);
  • menggunakan autentikasi dua faktor (2FA);
  • waspada terhadap usaha penipuan (phishing); serta
  • memantau aktivitas akun (misal ada yang mencoba masuk atau bahkan yang berhasil masuk).

Mungkin itu yang bisa kutulis saat ini di sela-sela penelitian dan eksperimen. Tetap berhati-hati di internet, semuanya!

Sabtu, 28 September 2024

Algoritma LFSR dan Bilangan Acak pada Komputer

Suatu program komputer tidak bisa menghasilkan bilangan acak sejati karena program komputer bersifat deterministik, yaitu hasilnya hanya ditentukan oleh masukannya. Namun, program komputer bisa menerima masukan dari sumber di luar program komputer sehingga bisa mendapatkan bilangan acak sejati dari luar program komputer.

Bagaimana komputer mendapatkan bilangan acak sejati?

Sebagai contoh, prosesor keluarga x86 memiliki perintah khusus untuk mendapatkan bilangan acak sejati, yaitu RDSEED (panduan lebih lanjut: Intel Digital Random Number Generator dan AMD Secure Random Number Generator). Untuk prosesor lain, seperti ARM, sumber bilangan acak sejati didapat dari komponen lain dalam sebuah sistem-pada-cip (system-on-chip/SoC). Ada juga komputer yang memang tidak memiliki perangkat keras untuk mendapatkan bilangan acak sejati. Dengan kata lain, komputer tersebut hanya mengandalkan pengolahan data oleh perangkat lunak untuk mendapatkan bilangan acak, misal dari jam komputer, gerakan tetikus, dan suara mikrofon.

Meski demikian, penghasil bilangan acak sejati ini hanya mampu menghasilkan 16/32/64 bita acak setiap ratusan siklus, bahkan ribuan siklus, karena komponen ini perlu mengumpulkan cukup data agar entropi dari bilangan acak cukup tinggi. Selain itu, tidak ada jaminan bahwa hasil dari RDSEED atau sejenisnya memiliki distribusi yang seragam. Ada kemungkinan nilai yang diperoleh darinya condong (skew) kepada bilangan tertentu.

Penghasil bilangan acak semu (pseudo-random number generator/PRNG) dibuat untuk menjawab masalah tersebut. Selain lebih cepat, algoritma-algoritma PRNG juga bisa diuji secara matematis bahwa distribusinya seragam sehingga hasilnya lebih bagus. Terdapat banyak contoh PRNG, antara lain, Xorshift, Mersenne Twister, linear-feedback shift register (LFSR), linear congruential generator (LCG), dan metode middle-square. Tiap algoritma PRNG memiliki kelebihan dan kekurangan masing-masing. Yang akan dibahas kali ini adalah linear-feedback shift register (LFSR).

Jadi, apa itu LFSR?

Linear-feedback shift register (LFSR) adalah register geser ke kanan yang menggunakan kombinasi linear dari bit-bit terpilih (disebut taps) untuk mengisi bit paling kiri (sebagai feedback). Operasi XOR sering digunakan sebagai operator kombinasi linear sehingga LFSR biasanya tersusun dari operasi geser dan operasi XOR. Hasil dari LFSR adalah untaian bit yang dikeluarkan dari bit paling kanan/bit satuan.

LFSR berukuran n akan melakukan siklus melalui semua kemungkinan dikurangi satu (2ᵐ - 1, nol tidak dihitung), kecuali jika register sejak awal bernilai nol yang berarti akan selalu nol. Sebagai contoh, LFSR 2-bit akan mulai dari 01, ke 10, ke 11, dan kembali ke 01. Namun, bila dimulai dari 00, LFSR tersebut hanya akan menghasilkan 00.

LFSR dengan XOR memiliki dua bentuk: LFSR Fibonacci dan LFSR Galois. Bentuk Fibonacci mengambil XOR dari bit-bit taps untuk mengisi bit paling kiri, sedangkan bit-bit taps dalam bentuk Galois mengambil XOR dari bit sebelah kiri dengan bit keluaran/paling kanan sebelum pergeseran. Keduanya digambarkan oleh ilustrasi di bawah ini. Perhatikan bahwa penomoran bit LFSR Fibonacci dan LFSR Galois terbalik.

Diagram LFSR Fibonacci yang terdiri dari empat kotak berlabelkan 1, 2, 3, dan 4. Di bawah keempat kotak, terdapat gerbang logika XOR yang menerima masukan dari kotak 3 dan kotak 4 dan meneruskan hasil ke kotak 1. Selain itu, terdapat panah dari kotak 4 ke huruf X (keluaran).
Diagram kerja LFSR Fibonacci 4-bit
Diagram LFSR Galois yang terdiri dari empat kotak berlabelkan 4, 3, 2, dan 1. Di antara kotak 4 dan 3, terdapat gerbang logika XOR yang menerima masukan dari kotak 4 dan kotak 1 dan meneruskan hasil ke kotak 3. Selain itu, terdapat panah dari kotak 1 ke kotak 4 dan panah dari kotak 1 ke huruf X (keluaran).
Diagram kerja LFSR Galois 4-bit

n.b. Pada diagram LFSR Galois, bit paling kiri tidak memiliki gerbang logika XOR karena 0 XOR x akan menghasilkan x pula.

Dari mana kita tahu taps yang sesuai?

Salah satu cara untuk mengetahui taps yang sesuai adalah dengan mencoba kombinasi taps yang mungkin. Namun, untuk mempersempit ruang pencarian, kombinasi taps yang dicari hanyalah yang menggunakan taps berjumlah genap (Ahmad dkk., 1997). Berikut adalah cuplikan tabel taps LFSR Galois yang disusun oleh Ward dan Molteno (2012).

n Jumlah kombinasi Bit-bit taps
232 dan 1
373 dan 2
4154 dan 3
82558, 6, 5, dan 4
1665.53516, 14, 13, dan 11
32±4,3 miliar32, 30, 26, dan 25
64±18 kuintiliun64, 63, 61, dan 60

Bagaimana langkah-langkah pengerjaannya?

Sebagai contoh, kita akan melakukan LFSR Fibonacci 3-bit dengan taps bit ke-2 dan bit ke-3 serta nilai register awal 001. Untuk tiap iterasi, bit-bit register digeser ke kanan, lalu bit ke-1 adalah hasil XOR dari bit ke-2 dan bit ke-3 sebelum pergeseran.

Bit ke- Keterangan
1 2 3
001(nilai register awal)
1000 XOR 1 = 1
0100 XOR 0 = 0
1011 XOR 0 = 0
1100 XOR 1 = 1
1111 XOR 0 = 1
0111 XOR 1 = 0
0011 XOR 1 = 0 (kembali ke awal)

LFSR tersebut menghasilkan untaian 7 bit 1001011 berulang. Untaian bit tersebut cukup "acak". Untuk lebih acak, kita bisa menggunakan ukuran register yang lebih besar agak untaian bit lebih panjang sebelum akhirnya berulang lagi.

Bonus: Contoh Program

register = 1
for i in range(8):
	print(f"{register:03b} -- {(register & 1):01b}")
	bit_baru = (register ^ (register >> 1)) & 1
	register = (register >> 1) | (bit_baru << 2)
Hasil keluaran
001 -- 1
100 -- 0
010 -- 0
101 -- 1
110 -- 0
111 -- 1
011 -- 1
001 -- 1

Cara mendapatkan bit baru (paling kiri) cukup dengan menghitung XOR dari register dan register >> 1 (yang sudah digeser ke kanan sekali), lalu mengambil AND darinya dengan 1 (mengambil bit satuan). Hal tersebut sama dengan melakukan XOR bit terakhir (bit ke-3) dengan bit kedua terakhir (bit ke-2).

Penutup

Itu yang bisa kutulis kali ini. Topik LFSR ini mendadak terpikirkan saat aku mencari ide untuk menulis di blogku ini. Ada dua video yang cocok sebagai pengayaan dari tulisanku ini, sekaligus menjadi inspirasiku dalam menulis pos ini, yaitu "True Random Numbers" dan "Random Numbers with LFSR" yang keduanya dari saluran YouTube Computerphile. Semoga bermanfaat!

Rabu, 28 Agustus 2024

Jaringan Substitusi-Permutasi

Pada pembahasan kali ini, kita beralih dari penyandian teks menjadi penyandian untaian bita secara umum. Karena komputer melihat data sebagai untaian bita-bita, penyandian untaian bita secara umum memampukan kita untuk melakukan penyandian data apa pun, seperti gambar, suara, video, dan dokumen jenis apa pun.

Sandi substitusi dan sandi transposisi (khususnya permutasi) dapat digabungkan menjadi suatu jaringan yang disebut sebagai jaringan substitusi-permutasi (SP). Jaringan SP terdiri atas operasi substitusi (biasa disebut sebagai kotak-S) dan operasi permutasi (kotak-P) yang disusun secara bergantian dan diulang beberapa kali. Jumlah pengulangan SP biasa disebut sebagai jumlah ronde.

Seperti penyandian pada umumnya, jaringan SP mengubah teks pesan menjadi teks tersandi dengan kunci yang diberikan. Untuk mengembalikan teks pesan, teks tersandi dimasukkan ke dalam inversi jaringan SP, yaitu sama dengan jaringan SP, tetapi urutan operasinya dibalik. Sebagai contoh, jaringan K-S-P-K-S-P-K memiliki inversi sebagai berikut: K-P-S-K-P-S-K. K adalah operasi penambahan kunci ke dalam teks.

Komponen Jaringan SP

Kotak-S berisi daftar konversi dari satu bita ke bita lain atau satu untaian bit ke untaian bit lain. Hal ini seperti konversi A menjadi B, lalu B menjadi K, dan seterusnya. Hal ini menyebabkan nilai-nilai bita hasil konversi tidak lagi memiliki hubungan linear terhadap nilai-nilai bita masukan.

Kotak-P berisi cara memetakan suatu bit dalam suatu bita ke bit lain dalam bita lain. Sebagai contoh, dari masukan 8 bita, bit ke-5 dalam bita ke-2 dipetakan ke bit ke-7 dalam bita ke-5. Hal ini menyebabkan susunan bit tidak lagi sama dengan sebelumnya sehingga relasi antara teks pesan dan teks tersandi menjadi sulit dimengerti.

Sebelum, setelah, dan di antara operasi substitusi dan permutasi, terdapat operasi penambahan kunci ke dalam teks. Namun, kunci yang digunakan berbeda-beda untuk tiap ronde, padahal hanya ada satu kunci yang diberikan. Caranya adalah penjadwalan kunci.

Penjadwalan kunci adalah cara untuk mendapatkan nilai kunci yang berbeda-beda untuk tiap ronde berdasarkan satu kunci yang diberikan. Terdapat beberapa cara untuk melakukannya, misalnya TEA membagi kunci 128 bit menjadi empat kunci 32 bit yang digunakan bergantian atau AES memiliki prosedur yang lebih kompleks untuk menjadwalkan kunci.

Contoh Kasus

Sebagai contoh, kita akan menyandikan pesan C5 37 2B 9F dengan menggunakan struktur K-S-P-K-S-P-K dan ukuran masukan empat bita. Selain itu, kunci yang diberikan juga empat bita: 58 65 9F DD.

Spesifikasi Jaringan SP

Berikut adalah nilai kotak-S yang digunakan dalam AES:

_0_1_2_3_4_5_6_7_8_9_A_B_C_D_E_F
0_637C777BF26B6FC53001672BFED7AB76
1_CA82C97DFA5947F0ADD4A2AF9CA472C0
2_B7FD9326363FF7CC34A5E5F171D83115
3_04C723C31896059A071280E2EB27B275
4_09832C1A1B6E5AA0523BD6B329E32F84
5_53D100ED20FCB15B6ACBBE394A4C58CF
6_D0EFAAFB434D338545F9027F503C9FA8
7_51A3408F929D38F5BCB6DA2110FFF3D2
8_CD0C13EC5F974417C4A77E3D645D1973
9_60814FDC222A908846EEB814DE5E0BDB
A_E0323A0A4906245CC2D3AC629195E479
B_E7C8376D8DD54EA96C56F4EA657AAE08
C_BA78252E1CA6B4C6E8DD741F4BBD8B8A
D_703EB5664803F60E613557B986C11D9E
E_E1F8981169D98E949B1E87E9CE5528DF
F_8CA1890DBFE6426841992D0FB054BB16

Untuk kasus ini, kita bisa membuat kotak-P agar menukar satu bita dengan bita sebelahnya. Sebagai contoh, empat bit pertama dari bita ke-1 ditukar dengan empat bit kedua dari bita ke-2, empat bit pertama dari bita ke-3 ditukar dengan empat bit kedua dari bita ke-4, dan seterusnya.

Operasi penambahan kunci hanya melakukan XOR dengan kunci. Selain itu, penjadwalan kunci yang akan kita gunakan sederhana, yaitu hanya melakukan geseran melingkar ke kiri (<<<) sebanyak satu bita untuk tiap ronde.

Perhitungan

Perhitungan dari kasus di atas ditunjukkan dalam tabel berikut:

OperasiTeksKunci
Keadaan awalC5372B9F58659FDD
Penambahan kunci9D52B44258659FDD
Substitusi5E008D2C<<<
Permutasi0E05CD28
Penambahan kunci6B9A1070659FDD58
Substitusi7FB8CA51<<<
Permutasi8FB71A5C
Penambahan kunci106A42399FDD5865

Hasil penyandiannya adalah 10 6A 42 39.

Bonus: Program C
Program C
#include <stdio.h>
#include <stdint.h>

#define UKURAN 4

void penambahanKunci(uint8_t *A, const uint8_t *kunci) { // K
	for (int i = 0; i < UKURAN; i ++)
		A[i] ^= kunci[i];
}

void substitusi(uint8_t *A, const uint8_t *kotakS) { // S
	for (int i = 0; i < UKURAN; i ++)
		A[i] = kotakS[A[i]];
}

void permutasi(uint8_t *A) { // P
	for (int i = 0; i < UKURAN; i += 2) {
		uint8_t lawas1 = A[i + 0];
		uint8_t lawas2 = A[i + 1];
		A[i + 0] = lawas1 & 0x0F | (lawas2 << 4) & 0xF0;
		A[i + 1] = lawas2 & 0xF0 | (lawas1 >> 4);
	}
}

void geserKunci(uint8_t *kunci) { // <<<
	uint8_t k = kunci[0];
	for (int i = 0; i < UKURAN - 1; i ++)
		kunci[i] = kunci[i + 1];
	kunci[UKURAN - 1] = k;
}

void jaringanSP(uint8_t *pesan, uint8_t *kunci, const uint8_t *kotakS) {
	penambahanKunci(pesan, kunci); // K
	substitusi(pesan, kotakS);     // S
	permutasi(pesan);              // P
	geserKunci(kunci);             // <<<
	penambahanKunci(pesan, kunci); // K
	substitusi(pesan, kotakS);     // S
	permutasi(pesan);              // P
	geserKunci(kunci);             // <<<
	penambahanKunci(pesan, kunci); // K
}

int main() {
	uint8_t pesan[] = {0xC5, 0x37, 0x2B, 0x9F};
	uint8_t kunci[] = {0x58, 0x65, 0x9F, 0xDD};
	uint8_t kotakS[256] = {};
	// https://id.wikipedia.org/wiki/Kotak-S_Rijndael
	initialize_aes_sbox(kotakS);
	jaringanSP(pesan, kunci, kotakS);
	printf("%X %X %X %X\n", pesan[0], pesan[1], pesan[2], pesan[3]);
	return 0;
}

Prinsip Shannon

Jaringan SP memenuhi prinsip pengacakan dan penghamburan Shannon.

  • Pengacakan: Bila salah satu bit teks pesan diubah, hasil dari kotak-S akan jauh berbeda yang kemudian akan makin tersebar oleh kotak-P. Hal ini berulang dalam beberapa ronde. Hasilnya adalah teks tersandi sulit untuk ditebak hanya dengan perubahan kecil.
  • Penghamburan: Bila salah satu bit kunci diubah, kunci ronde disebar ke seluruh/potongan teks sehingga perubahan teks tersandi sulit dilacak.

Penutup

Sekian dahulu tulisanku kali ini. Aku sudah ingin membahas ini sejak lama, terutama bagian menulis kode programnya, tetapi menunggu tulisan pembahasan sandi substitusi dan sandi transposisi selesai agar pembahasannya runtut. Semoga bermanfaat!