Sabtu, 25 Mei 2024

Soal-Soal Konsep Pemrograman Gambar Bentuk

Beberapa hari lalu, ada yang mengetwit tentang contoh soal konsep pemrograman. Konsep yang diuji sederhana, sih, yaitu percabangan dan perulangan. Soal-soal sejenis ini juga biasa muncul dalam mata kuliah Konsep Pemrograman.

Betul, soal-soal yang kumaksud adalah membuat program yang mencetak bentuk-bentuk tertentu menggunakan teks (seperti seni ASCII). Ada yang berbentuk segitiga, persegi, jajaran genjang, belah ketupat, dan jam pasir. Ada yang terisi penuh; ada yang hanya bingkai/garis tepinya. Ada yang hanya teks, ada yang berisi urutan bilangan tertentu.

Ilustrasi enam belas soal gambar bentuk, seperti tabel di bawahnya
Enam Belas Soal Gambar Bentuk

Ada enam belas soal. Berikut daftarnya:

Daftar Enam Belas Soal Gambar Bentuk
Nama Target Hasil
Segitiga Kiri Bawah
*
* *
* * *
* * * *
* * * * *
Segitiga Kanan Bawah
        *
      * *
    * * *
  * * * *
* * * * *
Segitiga Sama Sisi
    *
   * *
  * * *
 * * * *
* * * * *
Segitiga Kiri Atas
* * * * *
* * * *
* * *
* *
*
Segitiga Kanan Atas
* * * * *
  * * * *
    * * *
      * *
        *
Segitiga Sama Sisi Terbalik
* * * * *
 * * * *
  * * *
   * *
    *
Jajaran Genjang
* * * *
 * * * *
  * * * *
   * * * *
    * * * *
Belah Ketupat
   *
  * *
 * * *
* * * *
 * * *
  * *
   *
Jam Pasir
* * * *
 * * *
  * *
   *
  * *
 * * *
* * * *
Bingkai Persegi
* * * * *
*       *
*       *
*       *
* * * * *
Bingkai Segitiga Sama Sisi
    *
   * *
  *   *
 *     *
* * * * *
Bintang Segitiga Sama Sisi Terbalik
* * * * *
 *     *
  *   *
   * *
    *
Bingkai Belah Ketupat
   *
  * *
 *   *
*     *
 *   *
  * *
   *
Bingkai Jam Pasir
* * * *
 *   *
  * *
   *
  * *
 *   *
* * * *
Segitiga Floyd
1
2 3
4 5 6
7 8 9 10
Segitiga Pascal
   1
  1 1
 1 2 1
1 3 3 1

Kita bahas satu-satu, ya. Perlu diingat bahwa pembahasan berikut menganggap bahwa spasi pada akhir baris berpengaruh sehingga tidak boleh ada.

Tiap soal akan dijawab dengan dua bahasa pemrograman, yaitu bahasa Python dan C. Khusus bahasa C, berikut ada fungsi pembantu untuk memudahkan dalam menulis kode.

void cetak_ulang(char teks[], int jumlah) {
	for (int i = 0; i < jumlah; i ++)
		printf(teks);
}

Oh, iya. Kode-kode program berikut kutulis dalam sehari. Jadi, mungkin ada cara yang lebih efektif/optimal untuk membuat bentuk yang diminta.

Segitiga Kiri Bawah

*
* *
* * *
* * * *
* * * * *

Ini bentuk paling sederhana. Kita cukup membuat perulangan dua tingkat: satu untuk baris dan satu lagi untuk kolom. Kalau spasi pada akhir baris tidak dianggap, kita cukup mengulang teks "* ". Namun, karena itu berpengaruh, kita ubah menjadi cetak "*" sekali, lalu cetak " *" untuk sisanya.

Jawaban

Python

def segitiga_kiri_bawah(ukuran):
	for i in range(1, ukuran + 1):
		print('*' + ' *' * (i - 1))

C

void segitiga_kiri_bawah(int ukuran) {
	for (int i = 1; i <= ukuran; i ++) {
		printf("*");
		cetak_ulang(" *", i - 1);
		printf("\n");
	}
}

Segitiga Kanan Bawah

        *
      * *
    * * *
  * * * *
* * * * *

Bentuk ini mirip dengan sebelumnya, tetapi perlu ditambah spasi sebelum mulai mencetak tiap barisnya. Jumlah spasi berbanding terbalik dengan nomor baris (dari 2 × [nomor baris - 1] sampai 0). Cara lainnya adalah dengan mengulang cetak 2 spasi (" ") sebanyak (nomor baris - 1) sehingga tidak perlu ada kali 2 pada jumlah pengulangannya.

Jawaban

Python

def segitiga_kanan_bawah(ukuran):
	for i in range(1, ukuran + 1):
		print('  ' * (ukuran - i) + '*' + ' *' * (i - 1))

C

void segitiga_kanan_bawah(int ukuran) {
	for (int i = 1; i <= ukuran; i ++) {
		cetak_ulang("  ", ukuran - i);
		printf("*");
		cetak_ulang(" *", i - 1);
		printf("\n");
	}
}

Segitiga Sama Sisi

    *
   * *
  * * *
 * * * *
* * * * *

Ini mirip dengan sebelumnya, tetapi jumlah spasinya tidak perlu dikali dua sehingga hanya setengah dari yang sebelumnya. Yang sebelumnya pakai 2 spasi cukup mengubahyna menjadi 1 karakter spasi.

Jawaban

Python

def segitiga_sama_sisi(ukuran):
	for i in range(1, ukuran + 1):
		print(' ' * (ukuran - i) + '*' + ' *' * (i - 1))

C

void segitiga_sama_sisi(int ukuran) {
	for (int i = 1; i <= ukuran; i ++) {
		cetak_ulang(" ", ukuran - i);
		printf("*");
		cetak_ulang(" *", i - 1);
		printf("\n");
	}
}

Segitiga Kiri Atas

* * * * *
* * * *
* * *
* *
*

Soal ini mirip dengan soal Segitiga Kiri Bawah, tetapi urutan barisnya dibalik. Membaliknya bisa dengan mengubah urutan nilai i pada perulangan baris.

Jawaban

Python

def segitiga_kiri_atas(ukuran):
	for i in range(ukuran, 0, -1):
		print('*' + ' *' * (i - 1))

C

void segitiga_kiri_atas(int ukuran) {
	for (int i = ukuran; i > 0; i --) {
		printf("*");
		cetak_ulang(" *", i - 1);
		printf("\n");
	}
}

Segitiga Kanan Atas

* * * * *
  * * * *
    * * *
      * *
        *

Yang ini juga mirip dengan sebelumnya. Kita cukup mengubah urutan baris dari Segitiga Kanan Bawah.

Jawaban

Python

def segitiga_kanan_atas(ukuran):
	for i in range(ukuran, 0, -1):
		print('  ' * (ukuran - i) + '*' + ' *' * (i - 1))

C

void segitiga_kanan_atas(int ukuran) {
	for (int i = ukuran; i > 0; i --) {
		cetak_ulang("  ", ukuran - i);
		printf("*");
		cetak_ulang(" *", i - 1);
		printf("\n");
	}
}

Segitiga Sama Sisi Terbalik

* * * * *
 * * * *
  * * *
   * *
    *

Ini masih sama, ya. Kita cukup mengubah urutan baris dari Segitiga Sama Sisi.

Jawaban

Python

def segitiga_sama_sisi_terbalik(ukuran):
	for i in range(ukuran, 0, -1):
		print(' ' * (ukuran - i) + '*' + ' *' * (i - 1))

C

void segitiga_sama_sisi_terbalik(int ukuran) {
	for (int i = ukuran; i > 0; i --) {
		cetak_ulang(" ", ukuran - i);
		printf("*");
		cetak_ulang(" *", i - 1);
		printf("\n");
	}
}

Jajaran Genjang

* * * *
 * * * *
  * * * *
   * * * *
    * * * *

Untuk membuat jajaran genjang, kita bisa mulai dengan membuat persegi panjang. Kita perlu dua perulangan: tingkat pertama untuk baris (dari 0 sampai tinggi) dan tingkat kedua untuk kolom (dari 0 sampai alas). Sebelum mencetak tiap baris, kita perlu mencetak spasi sebanyak 2 × (nomor baris - 1).

Jawaban

Python

def jajaran_genjang(alas, tinggi):
	if alas <= 0:
		return
	for i in range(tinggi):
		print(' ' * i + '*' + ' *' * (alas - 1))

C

void jajaran_genjang(int alas, int tinggi) {
	if (alas <= 0)
		return;
	for (int i = 0; i < tinggi; i ++) {
		cetak_ulang(" ", i);
		printf("*");
		cetak_ulang(" *", alas - 1);
		printf("\n");
	}
}

Belah Ketupat

   *
  * *
 * * *
* * * *
 * * *
  * *
   *

Belah ketupat bisa dibagi menjadi dua segitiga. Segitiga yang di atas sama dengan Segitiga Sama Sisi. Segitiga yang di bawah sama dengan Segitiga Sama Sisi Terbalik. Salah satunya dikurangi satu baris agar tidak ada baris ganda di tengah.

Jawaban

Python

def belah_ketupat(sisi):
	if sisi <= 0:
		return
	for i in range(1, sisi):
		print(' ' * (sisi - i) + '*' + ' *' * (i - 1))
	for i in range(sisi, 0, -1):
		print(' ' * (sisi - i) + '*' + ' *' * (i - 1))

C

void belah_ketupat(int sisi) {
	for (int i = 1; i < sisi; i ++) {
		cetak_ulang(" ", sisi - i);
		printf("*");
		cetak_ulang(" *", i - 1);
		printf("\n");
	}
	for (int i = sisi; i > 0; i --) {
		cetak_ulang(" ", sisi - i);
		printf("*");
		cetak_ulang(" *", i - 1);
		printf("\n");
	}
}

Jam Pasir

* * * *
 * * *
  * *
   *
  * *
 * * *
* * * *

Bentuk ini kebalikan dari Belah Ketupat. Segitiga yang di atas sama dengan Segitiga Sama Sisi Terbalik (!). Segitiga yang di bawah sama dengan Segitiga Sama Sisi. Jangan lupa bahwa salah satunya dikurangi satu baris agar tidak ada baris ganda di tengah.

Jawaban

Python

def jam_pasir(sisi):
	for i in range(sisi, 1, -1):
		print(' ' * (sisi - i) + '*' + ' *' * (i - 1))
	for i in range(1, sisi + 1):
		print(' ' * (sisi - i) + '*' + ' *' * (i - 1))

C

void jam_pasir(int sisi) {
	for (int i = sisi; i > 1; i --) {
		cetak_ulang(" ", sisi - i);
		printf("*");
		cetak_ulang(" *", i - 1);
		printf("\n");
	}
	for (int i = 1; i <= sisi; i ++) {
		cetak_ulang(" ", sisi - i);
		printf("*");
		cetak_ulang(" *", i - 1);
		printf("\n");
	}
}

Bingkai Persegi

* * * * *
*       *
*       *
*       *
* * * * *

Bentuk ini dibuat dalam tiga tahap. Pertama, cetak sisi atas. Kedua, cetak sisi kiri dan kanan secara berulang. Ketiga, cetak sisi bawah.

Jawaban

Python

def bingkai_persegi(sisi):
	if sisi > 0:
		print('*' + ' *' * (sisi - 1))
	for i in range(sisi - 2):
		print('*' + '  ' * (sisi - 2) + ' *')
	if sisi > 1:
		print('*' + ' *' * (sisi - 1))

C

void bingkai_persegi(int sisi) {
	if (sisi > 0) {
		printf("*");
		cetak_ulang(" *", sisi - 1);
		printf("\n");
	}
	for (int i = 1; i < sisi - 1; i ++) {
		printf("*");
		cetak_ulang("  ", sisi - 2);
		printf(" *");
		printf("\n");
	}
	if (sisi > 1) {
		printf("*");
		cetak_ulang(" *", sisi - 1);
		printf("\n");
	}
}

Bingkai Segitiga Sama Sisi

    *
   * *
  *   *
 *     *
* * * * *

Bentuk ini adalah versi bingkai dari Segitiga Sama Sisi. Untuk bagian tengah, yang tadinya cetak karakter bintang berulang itu diubah menjadi hanya cetak karakter bintang pada sisi kiri dan sisi kanan.

Jawaban

Python

def bingkai_segitiga_sama_sisi(ukuran):
	for i in range(1, ukuran + 1):
		print(' ' * (ukuran - i), end='*')
		if i == ukuran:
			print(' *' * (i - 1))
		else:
			print('  ' * (i - 2) + ' *' if i > 1 else '')

C

void bingkai_segitiga_sama_sisi(int ukuran) {
	for (int i = 1; i <= ukuran; i ++) {
		cetak_ulang(" ", ukuran - i);
		printf("*");
		if (i == ukuran)
			cetak_ulang(" *", i - 2);
		else
			cetak_ulang("  ", i - 2);
		if (i > 1)
			printf(" *");
		printf("\n");
	}
}

Bintang Segitiga Sama Sisi Terbalik

* * * * *
 *     *
  *   *
   * *
    *

Yang ini juga sama dengan sebelumnya, tetapi untuk versi yang terbalik.

Jawaban

Python

def bingkai_segitiga_sama_sisi_terbalik(ukuran):
	for i in range(ukuran, 0, -1):
		print(' ' * (ukuran - i), end='*')
		if i == ukuran:
			print(' *' * (i - 1))
		else:
			print('  ' * (i - 2) + ' *' if i > 1 else '')

C

void bingkai_segitiga_sama_sisi_terbalik(int ukuran) {
	for (int i = ukuran; i > 0; i --) {
		cetak_ulang(" ", ukuran - i);
		printf("*");
		if (i == ukuran)
			cetak_ulang(" *", i - 2);
		else
			cetak_ulang("  ", i - 2);
		if (i > 1)
			printf(" *");
		printf("\n");
	}
}

Bingkai Belah Ketupat

   *
  * *
 *   *
*     *
 *   *
  * *
   *

Bentuk ini gabungan dari dua bingkai segitiga sebelumnya.

Jawaban

Python

def bingkai_belah_ketupat(sisi):
	if sisi <= 0:
		return
	for i in range(1, sisi):
		print(' ' * (sisi - i), end='*')
		print('  ' * (i - 2) + ' *' if i > 1 else '')
	for i in range(sisi, 0, -1):
		print(' ' * (sisi - i), end='*')
		print('  ' * (i - 2) + ' *' if i > 1 else '')

C

void bingkai_belah_ketupat(int sisi) {
	if (sisi <= 0)
		return;
	for (int i = 1; i < sisi; i ++) {
		cetak_ulang(" ", sisi - i);
		printf("*");
		cetak_ulang("  ", i - 2);
		if (i > 1)
			printf(" *");
		printf("\n");
	}
	for (int i = sisi; i > 0; i --) {
		cetak_ulang(" ", sisi - i);
		printf("*");
		cetak_ulang("  ", i - 2);
		if (i > 1)
			printf(" *");
		printf("\n");
	}
}

Bingkai Jam Pasir

* * * *
 *   *
  * *
   *
  * *
 *   *
* * * *

Untuk yang ini, kita membalik segitiga seperti sebelumnya.

Jawaban

Python

def bingkai_jam_pasir(sisi):
	for i in range(sisi, 1, -1):
		print(' ' * (sisi - i), end='*')
		if i == sisi:
			print(' *' * (i - 1))
		else:
			print('  ' * (i - 2) + ' *' if i > 1 else '')
	for i in range(1, sisi + 1):
		print(' ' * (sisi - i), end='*')
		if i == sisi:
			print(' *' * (i - 1))
		else:
			print('  ' * (i - 2) + ' *' if i > 1 else '')

C

void bingkai_jam_pasir(int sisi) {
	for (int i = sisi; i > 1; i --) {
		cetak_ulang(" ", sisi - i);
		printf("*");
		if (i == sisi)
			cetak_ulang(" *", i - 2);
		else
			cetak_ulang("  ", i - 2);
		if (i > 1)
			printf(" *");
		printf("\n");
	}
	for (int i = 1; i <= sisi; i ++) {
		cetak_ulang(" ", sisi - i);
		printf("*");
		if (i == sisi)
			cetak_ulang(" *", i - 2);
		else
			cetak_ulang("  ", i - 2);
		if (i > 1)
			printf(" *");
		printf("\n");
	}
}

Segitiga Floyd

1
2 3
4 5 6
7 8 9 10

Segitiga Floyd pada dasarnya memiliki bentuk yang sama dengan Segitiga Kiri Bawah, tetapi karakter bintang diganti dengan bilangan berurutan yang dimulai dari satu.

Jawaban

Python

def segitiga_Floyd(ukuran):
	k = 1
	for i in range(ukuran):
		for j in range(i + 1):
			print(str(k) + (' ' if j < i else ''), end='')
			k += 1
		print()

C

void segitiga_Floyd(int ukuran) {
	int k = 1;
	for (int i = 1; i <= ukuran; i ++) {
		printf("%d", k ++);
		for (int j = 1; j < i; j ++)
			printf(" %d", k ++);
		printf("\n");
	}
}

Segitiga Pascal

   1
  1 1
 1 2 1
1 3 3 1

Segitiga Pascal adalah segitiga yang baris selanjutnya adalah penjumlahan dua bilangan di kiri-atas dan kanan-atas-nya. Untuk mencetaknya, kita bisa menggunakan pola yang sama dengan Segitiga Sama Sisi. Untuk menentukan bilangan yang akan dicetak, kita perlu menghitung per baris.

Karena jumlah bilangan per baris sama dengan nomor baris, kita cukup menyiapkan sebuah larik (array) yang berisi nilai 0 sebanyak jumlah baris. Kemudian, bilangan pertama diatur menjadi 1. Untuk menghitung baris selanjutnya, kita bisa mulai dari bilangan ke-2 yang merupakan penjumlahan dari bilangan ke-1 dan bilangan ke-2 pada baris sebelumnya. Begitu pula seterusnya dengan pola bilangan ke-n baris baru = bilangan ke-(n-1) baris sebelumnya + bilangan ke-n baris sebelumnya. Kita memulai dari bilangan ke-2 karena bilangan ke-1 tidak pernah berubah, yaitu selalu 1.

Jawaban Python
def segitiga_Pascal(ukuran):
	if ukuran <= 0:
		return
	nilai = [0] * ukuran
	nilai_baru = [0] * ukuran
	nilai[0] = 1
	nilai_baru[0] = 1
	for i in range(1, ukuran + 1):
		print(' ' * (ukuran - i), end='')
		print(nilai[0], end='')
		for j in range(1, i):
			print(' ' + str(nilai[j]), end='')
		print()
		for k in range(1, ukuran):
			nilai_baru[k] = nilai[k - 1] + nilai[k]
		nilai = nilai_baru.copy()
C
void segitiga_Pascal(int ukuran) {
	if (ukuran <= 0)
		return;
	int nilai[ukuran];
	int nilai_baru[ukuran];
	nilai[0] = 1;
	nilai_baru[0] = 1;
	for (int i = 1; i < ukuran; i ++) {
		nilai[i] = 0;
		nilai_baru[i] = 0;
	}
	for (int i = 1; i <= ukuran; i ++) {
		cetak_ulang(" ", ukuran - i);
		printf("%d", nilai[0]);
		for (int j = 1; j < i; j ++)
			printf(" %d", nilai[j]);
		printf("\n");
		for (int j = 1; j < ukuran; j ++)
			nilai_baru[j] = nilai[j - 1] + nilai[j];
		for (int j = 0; j < ukuran; j ++)
			nilai[j] = nilai_baru[j];
	}
}

Penutup

Sekian dahulu yang bisa kutulis. Buatku, ini latihan sekaligus mengenang masa-masa ketika aku belajar konsep pemrograman. Kalau ada masukan, jangan sungkan untuk tinggalkan komentar, ya. Semoga bermanfaat!

Jumat, 24 Mei 2024

Enkripsi Ujung-ke-Ujung, Protokol Signal, dan WhatsApp

Beberapa waktu lalu, aku membaca twit yang terkesan seperti penggaung (buzzer) aplikasi Telegram. Twitnya merendahkan orang-orang yang masih menggunakan WhatsApp. Apakah WhatsApp serendah itu jika dibandingkan dengan Telegram?

Kalau kita lihat dari sisi fitur yang disediakan, fitur yang ada di Telegram memang jauh lebih banyak: kapasitas grupnya lebih besar; dukungan botnya lebih bagus; kita bisa menyembunyikan nomor telepon (diganti nama pengguna); dan lain-lain. Namun, bagaimana kalau kita lihat dari sisi keamanan data?

Salah satu keuntungan WhatsApp adalah enkripsi ujung-ke-ujung (end-to-end encryption/E2EE) yang berlaku untuk seluruh pesan. Pada Telegram, fitur ini hanya berlaku jika menggunakan Secret Chat.

Enkripsi ujung-ke-ujung

Enkripsi ujung-ke-ujung berarti pesan yang dikirim sudah dikunci/disandi sebelum meninggalkan perangkat yang dipakai dan hanya bisa dibuka oleh perangkat penerima. Dampaknya, server yang menjadi perantara pun tidak tahu isi pesan yang dikirim.

WhatsApp menggunakan protokol Signal, protokol buatan Open Whisper Systems (OWS) yang juga digunakan oleh aplikasi Signal dan beberapa lainnya. Telegram menggunakan protokol MTProto (versi 2.0 sejak Telegram versi 4.6, Desember 2017). Aku kurang tahu tentang tingkat keamanan MTProto, tetapi (katanya) MTProto 2.0 lebih bagus dan lebih aman daripada versi 1.0-nya.

Protokol Signal menggunakan algoritma-algoritma kriptografi, seperti pertukaran kunci X3DH (Extended Triple Diffie-Hellman) untuk menentukan kunci bersama antara dua pihak serta Double Ratchet (krek ganda) untuk memastikan forward secrecy walau perangkat penerima sedang luring.

Metadata dan Meta

Meski demikian, protokol Signal tidak membatasi server perantara untuk mengumpulkan metadata pesan seperti identitas pengirim, identitas penerima, dan waktu pengiriman pesan. Hal ini menjadi bermasalah ketika WhatsApp diakuisisi oleh Meta dan mulai mengumpulkan metadata pesan. Banyak penolakan terhadap keputusan ini, tetapi Meta tetap lanjut dengan keputusannya.

Meski demikian, alternatif yang ada adalah aplikasi Signal itu sendiri yang (sejauh ini) tidak menyimpan metadata pesan. Aplikasi perpesanan lain seperti Telegram (kecuali Secret Chat), LINE, dan Facebook Messenger menyimpan pesan asli di server mereka. SMS juga sama tidak amannya (karenanya, WhatsApp juga menyediakan fitur verifikasi dua langkah).

Penggunaan WhatsApp memang lazim di Indonesia. Setidaknya, keamanan isi pesan sudah lebih bagus daripada alternatif yang ada walau ada kurang-kurangnya dikit, tetapi tidak fatal. Kalau mau yang (sedikit) lebih aman, orang-orang bisa pakai Signal atau Matrix.

Penutup

Jadi, siapa yang menang dari WhatsApp vs. Telegram? Itu kembali kepada prioritas tiap orang.

Minggu, 28 April 2024

Pengantar Kriptografi dan Sandi Geser

Beberapa waktu lalu, aku menemukan twit-twit pertanyaan tentang cara mengerjakan salah satu jenis soal UTBK SBMPTN (SNBT sejak 2023). Jenis soal yang dimaksud adalah soal dengan kalimat pertanyaan dan jawaban tersandi beserta kuncinya (k).

(k = 7)
ILYHWHRHO UPSHP KHYP APNH WHUNRHA KBH?
- APNH
- LTWHA
- KLSHWHU
- ZLTIPSHU
- ZLWBSBO

Hal tersebut mengingatkanku tentang mata kuliah pilihan yang kuambil saat mengambil S-1, yaitu mata kuliah Kriptografi.

Apa itu kriptografi?

Kriptografi adalah metode menulis pesan rahasia. Yang dimaksud dengan pesan dalam hal ini bisa bermacam-macam (misal tulisan, gambar, suara) selama bisa dikodekan secara matematis. Yang dimaksud dengan rahasia dalam hal ini adalah bahwa pesan yang sudah disandikan tidak bisa dibaca oleh pihak lain. Dengan kata lain, pesan tersandi tampak seperti data/tulisan acak.

Secara umum, berikut alur kerja kriptografi:

  1. Pengirim menulis pesan.
  2. Pengirim menyandikan pesan.
  3. Pesan tersandi dikirim melalui saluran komunikasi terbuka/publik. Siapa pun yang menemukan pesan ini hanya melihatnya sebagai data/tulisan acak.
  4. Penerima membuka sandi pesan.
  5. Penerima membuka pesan.
Diagram alur kerja kriptografi: Pengirim memberikan pesan x dan Kunci kepada Penyandi Pesan dalam ruang privat. Penyandi Pesan mengubah pesan x menjadi y dengan Kunci tersebut. Pesan y dikirimkan melalui ruang publik. Pembuka Sandi mengubah pesan tersandi y menjadi pesan x menggunakan Kunci yang diberikan oleh Penerima dalam ruang privat. Penerima menerima pesan x dari Pembuka Sandi dalam ruang privat.
Diagram alur kerja kriptografi

Ada berbagai macam kriptografi. Menurut kunci yang digunakan, kriptografi dapat dibagi menjadi (a) kriptografi kunci-simetris dan (b) kriptografi kunci-publik (asimetris). Selain itu, menurut cara penerapannya, kriptografi dapat dibagi menjadi (a) penyandian aliran dan (b) penyandian blok.

Kriptografi kunci-simetris adalah metode penyandian yang menggunakan kunci yang sama untuk menyandikan dan membuka sandi (simetris). Metode ini hanya menggunakan satu kunci. Contohnya beragam dari yang klasik, seperti sandi geser/sandi Caesar dan sandi Vigenère, sampai yang modern, seperti Standar Enkripsi Lanjutan (AES) dan sandi ChaCha. Metode kriptografi kunci-simetris klasik, seperti sandi substitusi, sudah ada sejak sekitar 1900 SM.

Kriptografi kunci-publik adalah metode penyandian yang menggunakan dua kunci yang berbeda untuk (1) menyandikan dan (2) membuka sandi. Metode ini menggunakan dua kunci: salah satunya bersifat publik dan satu yang lain lagi bersifat privat. Metode ini cukup baru. Artikel pertama yang menjelaskan tentang metode ini baru terbit pada tahun 1970-an.

Bagaimana contohnya di kehidupan nyata?

Di dunia nyata, baik kunci-simetris maupun kunci-publik digunakan bersamaan. Karena operasi kriptografi kunci-publik lebih lambat daripada kriptografi kunci-simetris, yang biasa dilakukan adalah sebagai berikut:

  1. Kedua belah pihak (pengirim dan penerima) menyepakati kunci bersama melalui saluran komunikasi terbuka/publik (misal pertukaran kunci Diffie–Hellman). Ini salah satu metode kriptografi kunci-publik.
  2. Pengirim menggunakan kunci bersama untuk menyandikan pesan. Ini metode kriptografi kunci-simetris.
  3. Pesan tersandi dikirim melalui saluran komunikasi terbuka/publik.
  4. Penerima membuka sandi dengan kunci bersama.

Bagaimana cara kedua belah pihak bisa menyepakati kunci bersama? Tentang itu, kita bahas lain kali, ya.

Sepertinya itu saja untuk kali ini.

Oi, oi, bagaimana cara membaca contoh soal di atas?

Oh, iya. Contoh soal di atas menggunakan sandi geser/sandi Caesar. Kita sudah diberi tahu tentang jumlah gesernya, yaitu 7. Kita tinggal "menggeser" huruf-huruf dalam alfabet untuk membuka sandinya.

Permasalahannya adalah bahwa tidak ada keterangan tentang arah gesernya sehingga kita perlu memeriksa dua kasus: (1) ke kanan (dikurangi) dan (2) ke kiri (ditambah). Kalau gesernya ke kanan (dikurangi), deretan ABCDE menjadi TUVWX. Kalau gesernya ke kiri (ditambah), deretan ABCDE menjadi HIJKL.

Diagram pergeseran huruf-huruf dalam alfabet. Baris pertama adalah hasil geser kiri 7 kali dan berisi ABCDEFGHIJKLMN. Baris kedua adalah deret sebelum digeser dan berisi TUVWXYZABCDEFG. Baris ketiga adalah hasil geser kanan 7 kali dan berisi MNOPQRSTUVWXYZ.
Diagram pergeseran huruf-huruf dalam alfabet
Operasi Hasil
Teks asli ILYHWHRHO UPSHP KHYP APNH WHUNRHA KBH? APNH, LTWHA, KLSHWHU, ZLTIPSHU, ZLWBSBO
Geser ke kanan (dikurangi) 7 kali BERAPAKAH NILAI DARI TIGA PANGKAT DUA? TIGA, EMPAT, DELAPAN, SEMBILAN, SEPULUH
Geser ke kiri (ditambah) 7 kali PSFODOYOV BWZOW ROFW HWUO DOBUYOH RIO? HWUO, SADOH, RSZODOB, GSAPWZOB, GSDIZIV

Untuk membuka sandi, ternyata yang diperlukan adalah geser ke kanan (dikurangi). Jadi, jawabannya adalah ZLTIPSHU (SEMBILAN).

Sudah, ya. Sampai jumpa!

Bonus: Program Python

alfabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
teks = "ILYHWHRHO UPSHP KHYP APNH WHUNRHA KBH? APNH, LTWHA, KLSHWHU, ZLTIPSHU, ZLWBSBO"
k = 7
hasil = ""
for h in teks:
	j = alfabet.find(h)
	if j == -1: # bukan karakter yang bisa digeser
		hasil += h
	else:
		hasil += alfabet[(j - k) % len(alfabet)] # geser ke kanan
print(hasil) # BERAPAKAH NILAI DARI TIGA PANGKAT DUA? TIGA, EMPAT, DELAPAN, SEMBILAN, SEPULUH