Implementasi Algoritma Rivest-Shamir-Adleman Untuk Pengamanan Kunci Algoritma Hill Cipher Pada Citra Digital

LISTING PROGRAM

1. Form halaman utama

  using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using IronPython.Hosting; using Microsoft.Scripting; using Microsoft.Scripting.Hosting; using System.IO; using System.Diagnostics; using System.Windows.Forms; using System.Drawing; namespace Aplikasi_Skripsi { public partial class HalamanUtama : Form { public string ling; public HalamanUtama() { InitializeComponent(); } private void mode_TextChanged(object sender, EventArgs e) { if (mode.Text == "Enkripsi") { enkripsiGb.Enabled = true; dekripsiGb.Enabled = false; asliLb.Text = "Citra asli"; palsuLb.Text = "Citra terenkripsi"; pictureBox2.Image = null; } else if (mode.Text == "Dekripsi") { enkripsiGb.Enabled = false; dekripsiGb.Enabled = true; asliLb.Text = "Citra terenkripsi"; palsuLb.Text = "Citra asli"; pictureBox2.Image = null; } } private void button10_Click(object sender, EventArgs e) { Tentang f1 = new Tentang(); f1.Show(); } private void autoBtn_Click(object sender, EventArgs e) { if (rTb.Text == "" || rTb.Text == "Range matriks") { MessageBox.Show("Range tidak boleh kosong!", "Peringatan!", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (rTb.Text == "1") { MessageBox.Show("Range tidak boleh 1!", "Peringatan!", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { Process p = new Process(); // create process (i.e., the python program p.StartInfo.FileName = "C:\\Python27\\python.exe"; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.UseShellExecute = false; // make sure we can read the output from stdout p.StartInfo.Arguments = "bangkitHill.py " + rTb.Text; // start the python program with two parameters p.Start(); // start the process (the python program) StreamReader s = p.StandardOutput; String output = s.ReadToEnd(); string[] r = output.Split(new char[] { ' ' }); // get the parameter string q = r[0]; string[] words = q.Split('.'); mTb1.Text = words[0]; mTb2.Text = words[1]; mTb3.Text = words[2]; mTb4.Text = words[3]; mTb5.Text = words[4]; mTb6.Text = words[5]; mTb7.Text = words[6]; mTb8.Text = words[7]; mTb9.Text = words[8]; detTb.Text = words[9]; p.WaitForExit(); MessageBox.Show("Matriks berhasil dibangkitkan!", "Informasi!", MessageBoxButtons.OK, MessageBoxIcon.Information); } } private void autoBtn2_Click(object sender, EventArgs e) { if (digitTb.Text == "" || digitTb.Text == "Panjang digit" || digitTb.Text == "1") { MessageBox.Show("Panjang digit tidak boleh kosong atau <= 1!", "Peringatan!", MessageBoxButtons.OK, MessageBoxIcon.Error); } else {

  Process p = new Process(); // create process (i.e., the python program p.StartInfo.FileName = "C:\\Python27\\python.exe"; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.UseShellExecute = false; // make sure we can read the output from stdout p.StartInfo.Arguments = "bangkitRSA.py " + digitTb.Text;// start the python program with parameters p.Start(); // start the process (the python program) StreamReader s = p.StandardOutput; String output = s.ReadToEnd(); string[] r = output.Split(new char[] { ' ' }); // get the parameter string q = r[0]; string[] words = q.Split('.'); pTb.Text = words[0]; qTb.Text = words[1]; eTb.Text = words[2]; dTb1.Text = words[3]; int pp = Convert.ToInt16(words[0]); int pq = Convert.ToInt16(words[1]); int n = pp * pq; nTb.Text = n.ToString(); int totn = (pp - 1) * (pq - 1); tTb.Text = totn.ToString(); p.WaitForExit(); MessageBox.Show("Kunci Publik dan Kunci Privat berhasil dibangkitkan!", "Informasi!", MessageBoxButtons.OK, MessageBoxIcon.Information); } } private void pTb_MouseHover(object sender, EventArgs e) { } private void qTb_MouseHover(object sender, EventArgs e) { } private void eTb_MouseHover(object sender, EventArgs e) { } private void textBox10_MouseHover(object sender, EventArgs e) { } private void textBox10_MouseHover_1(object sender, EventArgs e) {

  } private void textBox10_MouseHover_2(object sender, EventArgs e) { } private void rTb_MouseClick(object sender, MouseEventArgs e) { } private void digitTb_MouseClick(object sender, MouseEventArgs e) { } public void importCitraBtn_Click(object sender, EventArgs e) { OpenFileDialog theDialog = new OpenFileDialog(); theDialog.Title = "Open Image File"; theDialog.Filter = "PNG(*.png)|*.png"; theDialog.InitialDirectory = @"D:\"; theDialog.ShowDialog(); if (theDialog.FileName.ToString() != "") { Image image = Image.FromFile(theDialog.FileName.ToString()); pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage; pictureBox1.Image = image; ling = theDialog.FileName.ToString(); mode.Enabled = true; MessageBox.Show("Citra berhasil diimport!", "Informasi!", MessageBoxButtons.OK, MessageBoxIcon.Information); } } public void button1_Click(object sender, EventArgs e) { if (detTb.Text == "") { MessageBox.Show("Matriks tidak ditemukan!", "Peringatan!", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { Process p = new Process(); // create process (i.e., the python program p.StartInfo.FileName = "C:\\Python27\\python.exe"; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.UseShellExecute = false; // make sure we can read the output from stdout p.StartInfo.Arguments = "enkripsiCitra.py " + ling + " "

  • mTb1.Text + " " + mTb2.Text + " " + mTb3.Text + " " + mTb4.Text + " "
  • mTb5.Text + " " + mTb6.Text + " " + mTb7.Text + " " + mTb8.Text + " "
  • mTb9.Text ;// start the python program with parameters
p.Start(); // start the process (the python program) StreamReader s = p.StandardOutput; String output = s.ReadToEnd(); string[] r = output.Split(new char[] { ' ' }); // get the parameter string q = r[0]; string[] words = q.Split('.'); p.WaitForExit(); FileStream fs = new FileStream(words[0] + ".png", FileMode.Open); Image image = Image.FromStream(fs); pictureBox2.SizeMode = PictureBoxSizeMode.StretchImage; pictureBox2.Image = image; fs.Close(); MessageBox.Show("Citra berhasil dienkripsi!", "Informasi!", MessageBoxButtons.OK, MessageBoxIcon.Information); } } private void button3_Click(object sender, EventArgs e) { if (digitTb.Text == "" || pTb.Text == "") { MessageBox.Show("Kunci Publik dan Kunci Privat tidak boleh kosong!", "Peringatan!", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (detTb.Text == "") { MessageBox.Show("Matriks tidak ditemukan!", "Peringatan!", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { Process p = new Process(); // create process (i.e., the python program p.StartInfo.FileName = "C:\\Python27\\python.exe"; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.UseShellExecute = false; // make sure we can read the output from stdout p.StartInfo.Arguments = "enkripsiMatriks.py " + mTb1.Text + " " + mTb2.Text + " " + mTb3.Text + " " + mTb4.Text + " " + mTb5.Text + " " + mTb6.Text + " " + mTb7.Text + " " + mTb8.Text + " " + mTb9.Text + " " + pTb.Text + " " + qTb.Text + " " + eTb.Text;// start the python program with parameters p.Start(); // start the process (the python program) StreamReader s = p.StandardOutput; String output = s.ReadToEnd(); string[] r = output.Split(new char[] { ' ' }); // get the parameter string q = r[0]; string[] words = q.Split('.'); cTb1.Text = words[0]; cTb2.Text = words[1]; cTb3.Text = words[2];

cTb4.Text = words[3]; cTb5.Text = words[4]; cTb6.Text = words[5]; cTb7.Text = words[6]; cTb8.Text = words[7]; cTb9.Text = words[8]; p.WaitForExit(); MessageBox.Show("Matriks berhasil dienkripsi!", "Informasi!", MessageBoxButtons.OK, MessageBoxIcon.Information); } } private void groupBox1_Enter(object sender, EventArgs e) { } private void button5_Click(object sender, EventArgs e) { if (dTb2.Text == "") { MessageBox.Show("d tidak boleh kosong!", "Peringatan!", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if(nTb2.Text == "") { MessageBox.Show("n tidak boleh kosong!", "Peringatan!", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if(c1.Text == "" || c2.Text == "" || c3.Text == "" || c4.Text == ""|| c5.Text == ""|| c6.Text == "" || c7.Text == ""|| c8.Text == ""|| c9.Text == "") { MessageBox.Show("Cipher matrix tidak boleh kosong!", "Peringatan!", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (detTb1.Text == "") { MessageBox.Show("Determinan tidak boleh kosong!", "Peringatan!", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { Process p = new Process(); // create process (i.e., the python program p.StartInfo.FileName = "C:\\Python27\\python.exe"; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.UseShellExecute = false; // make sure we can read the output from stdout p.StartInfo.Arguments = "dekripsiMatriks.py " + c1.Text

  • " " + c2.Text + " " + c3.Text + " " + c4.Text + " " + c5.Text
  • " " + c6.Text + " " + c7.Text + " " + c8.Text + " " + c9.Text
  • " " +
dTb2.Text + " " + nTb2.Text + " " + detTb1.Text;// start the python program with parameters p.Start(); // start the process (the python program) StreamReader s = p.StandardOutput; String output = s.ReadToEnd(); string[] r = output.Split(new char[] { ' ' }); // get the parameter string q = r[0]; string[] words = q.Split('.'); k1.Text = words[0]; k2.Text = words[1]; k3.Text = words[2]; k4.Text = words[3]; k5.Text = words[4]; k6.Text = words[5]; k7.Text = words[6]; k8.Text = words[7]; k9.Text = words[8]; iTb1.Text = words[9]; iTb2.Text = words[10]; iTb3.Text = words[11]; iTb4.Text = words[12]; iTb5.Text = words[13]; iTb6.Text = words[14]; iTb7.Text = words[15]; iTb8.Text = words[16]; iTb9.Text = words[17]; p.WaitForExit(); MessageBox.Show("Matriks berhasil didekripsi!Invers berhasil ditemukan!", "Informasi!", MessageBoxButtons.OK, MessageBoxIcon.Information); } } private void button4_Click(object sender, EventArgs e) { if (detTb1.Text == "") { MessageBox.Show("Determinan tidak boleh kosong!", "Peringatan!", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (dTb2.Text == "") { MessageBox.Show("Matriks tidak ditemukan!", "Peringatan!", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { Process p = new Process(); // create process (i.e., the python program p.StartInfo.FileName = "C:\\Python27\\python.exe"; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.UseShellExecute = false; // make sure we can read the output from stdout

p.StartInfo.Arguments = "dekripsiCitra.py " + ling + " "

  • iTb1.Text + " " + iTb2.Text + " " + iTb3.Text + " " + iTb4.Text + " " + iTb5.Text + " " + iTb6.Text + " " + iTb7.Text + " " + iTb8.Text + " " + iTb9.Text;// start the python program with parameters p.Start(); // start the process (the python program) StreamReader s = p.StandardOutput; String output = s.ReadToEnd(); string[] r = output.Split(new char[] { ' ' }); // get the parameter string q = r[0]; string[] words = q.Split('.'); FileStream fs = new FileStream(words[0] + ".png", FileMode.Open);

  Image image = Image.FromStream(fs); pictureBox2.SizeMode = PictureBoxSizeMode.StretchImage; pictureBox2.Image = image; fs.Close(); MessageBox.Show("Citra berhasil didekripsi!", "Informasi!", MessageBoxButtons.OK, MessageBoxIcon.Information); } } private void button9_Click(object sender, EventArgs e) { Bantuan f4 = new Bantuan(); f4.Show(); } private void button6_Click(object sender, EventArgs e) { DialogResult dialogResult = MessageBox.Show("Hapus semua kolom dan citra pada mode ini?", "Peringatan!", MessageBoxButtons.YesNo); if (dialogResult == DialogResult.Yes) { ClearTextBoxes(enkripsiGb.Controls); } } private void ClearTextBoxes(Control.ControlCollection cc) { pictureBox1.Image = null; pictureBox2.Image = null; foreach (Control ctrl in cc) { TextBox tb = ctrl as TextBox; if (tb != null) tb.Text = ""; else ClearTextBoxes(ctrl.Controls); } } private void button7_Click(object sender, EventArgs e)

  { DialogResult dialogResult = MessageBox.Show("Hapus semua kolom dan citra pada mode ini?", "Peringatan!", MessageBoxButtons.YesNo); if (dialogResult == DialogResult.Yes) { ClearTextBoxes(dekripsiGb.Controls); } } private void Form3_FormClosing(object sender, FormClosingEventArgs e) { DialogResult dialogResult = MessageBox.Show("Apakah anda ingin keluar dari aplikasi ini?\r\nSemua data yang diisi akan terhapus!", "Peringatan!", MessageBoxButtons.YesNo); if (dialogResult == DialogResult.Yes) { MessageBox.Show("Terimakasih telah menggunakan aplikasi ini.", "Menutup Aplikasi!", MessageBoxButtons.OK); Environment.Exit(0); } else { e.Cancel = true; } } private void button2_Click(object sender, EventArgs e) { using (StreamWriter writer = new StreamWriter("kunci.txt")) { writer.WriteLine("Kunci Privat(d, p, q) = (" + dTb1.Text

  • ", " + pTb.Text + ", " + qTb.Text + " )"); writer.WriteLine("Determinan Matriks Kunci = " + detTb.Text); } MessageBox.Show("Kunci Privat berhasil disimpan!", "Informasi!", MessageBoxButtons.OK, MessageBoxIcon.Information); } }

  }

2. Form bantuan

  using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Aplikasi_Skripsi { public partial class Bantuan : Form { public Bantuan() { InitializeComponent(); } private void label9_Click(object sender, EventArgs e) { } } }

3. Form tentang

  using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Aplikasi_Skripsi { public partial class Tentang : Form { public Tentang() { InitializeComponent(); } private void label1_Click(object sender, EventArgs e) { } } }

  4. fungsi.py

  from random import randrange import Image # check the get_determinant if 1 or -1 def get_determinant(key): result = (key[0] * ((key[4] * key[8]) - (key[5] * key[7]))) - \ (key[1] * ((key[3] * key[8]) - (key[5] * key[6]))) + \ (key[2] * ((key[3] * key[7]) - (key[4] * key[6]))) return result # lehmann primality check method def lehmann(p): a = randrange(1, p) res = (a ** ((p - 1)/2)) % p if res == 1 or res == p - 1: return True else: return False # check a random number p givren on parameter with lehmann # will return p as prime and none if p is composite def check_prime(p): error = [] for i in range(10): if lehmann(p) == False: error.append(0) break else: error.append(1) i = 0 for e in error: i += 1 if e != 1: break if i == len(error): return p # hill cipher process def do_hill_cipher(key, x, y, pixels): processed_pixel = [] for j in range (x * y): R = pixels[j][0] G = pixels[j][1] B = pixels[j][2] A = pixels[j][3] result = ((key[0] * R) + (key[1] * G) + (key[2] * B)) % 256 result2 = ((key[3] * R) + (key[4] * G) + (key[5] * B)) % 256 result3 = ((key[6] * R) + (key[7] * G) + (key[8] * B)) % 256 r = [result, result2, result3, A] processed_pixel.append(r) return processed_pixel # create png file def create_png(x, y, pixels): image = Image.new('RGBA', (x, y), 'white') pi = 0 for i in range(x): for j in range(y): R = pixels[pi][0] G = pixels[pi][1] B = pixels[pi][2] A = pixels[pi][3] image.putpixel((i, j), (R, G, B, A)) pi += 1 return image

  # RSA encryption and decryption process def do_rsa(key, mode, n): return (key ** mode) % n # get key matrix inverse def get_inverse(key, get_determinant): # minor matrix m1 = (key[4] * key[8]) - (key[5] * key[7]) m2 = -1 * ((key[3] * key[8]) - (key[5] * key[6])) m3 = (key[3] * key[7]) - (key[4] * key[6]) m4 = -1 * ((key[1] * key[8]) - (key[2] * key[7])) m5 = (key[0] * key[8]) - (key[2] * key[6]) m6 = -1 * ((key[0] * key[7]) - (key[1] * key[6])) m7 = (key[1] * key[5]) - (key[2] * key[4]) m8 = -1 * ((key[0] * key[5]) - (key[2] * key[3])) m9 = (key[0] * key[4]) - (key[1] * key[3]) adjoint = [m1, m4, m7, m2, m5, m8, m3, m6, m9] key_inverse = [] for i in range(9): key_inverse.append(adjoint[i] / get_determinant) return key_inverse

  5. bangkitHill.py

  from fungsi import get_determinant import sys from random import randrange # generate random matrix with key range and get_determinant must either 1 or -1 for singularity key_range = int(sys.argv[1]) a = 0 while a == 0: key_matrix = [] for i in range (9): key_matrix.append(randrange(0,key_range)) if get_determinant(key_matrix) == 1 or get_determinant(key_matrix) == -1: break m = '' for i in key_matrix: m = m + str(i) + '.' print m + str(get_determinant(key_matrix))

  6. bangkitRSA.py

  from fungsi import lehmann, check_prime import sys from random import randrange from fractions import gcd

  # catch 2 primes from C# textbox a = 10 ** (int(sys.argv[1]) - 1) b = 10 ** int(sys.argv[1]) # generate 2 prime number for unique p, q prime = [] while len(prime) != 2: result = check_prime(randrange(a,b)) if result != None: prime.append(result) # RSA Scheme p = prime[0] q = prime[1] n = p * q totient = ( p - 1 ) * ( q - 1 ) # choose first found e e = [] for i in range( 2, n ): if gcd ( i, totient ) == 1: e.append( i ) e = e[0] # find d d = 0 remainder = 0 while remainder != 1: d = d + 1 remainder = ( e * d ) % totient m = '' for i in prime: m = m + str(i) + '.' print m + str(e) + '.' + str(d)

  7. enkripsiCitra.py

  from fungsi import do_hill_cipher, create_png import sys import Image # load image, get pixel and size image = Image.open(sys.argv[1]) pixels = image.load() image_size = image.size x = image_size[0] y = image_size[1] plain_pixel = [] #get image pixels value for i in range (x): for j in range (y): plain_pixel.append(pixels[i, j]) key_matrix = [] for i in range(9): key_matrix.append(int(sys.argv[i+2])) # image encryption process key_round = 1 cipher_pixel = [] cipher_pixel = plain_pixel for i in range(key_round): cipher_pixel = do_hill_cipher(key_matrix, x, y, cipher_pixel) # export encryption image ling2 = "C:\Users\JPS\Desktop\CipherImage.png" create_png(x, y, cipher_pixel).save(ling2, 'PNG') print ling2

  8. enkripsiMatr iks.py

  from fungsi import do_rsa import sys #catch matrix value from C# textbox plain_matrix = [] for i in range(9): plain_matrix.append(int(sys.argv[i+1])) # matrix encryption cipher_matrix= [] e = int(sys.argv[12]) n = int(sys.argv[10]) * int(sys.argv[11]) negative = [] for i in range(9): cipher_matrix.append(do_rsa(plain_matrix[i], e, n)) if plain_matrix[i] <= 0: negative.append (i) c = '' for i in cipher_matrix: c = c + str(i) + '.' for i in negative: c = c + str(n) print c

  9. dekripsiMatr iks.py

  from fungsi import do_rsa, get_inverse import sys # catch matrix from C# textbox cipher_matrix = [] for i in range(9): cipher_matrix.append(int(sys.argv[i+1]))

  # matrix decryption process d = int(sys.argv[10]) n = int(sys.argv[11]) plain_matrix = [] for i in range(9): plain_matrix.append(do_rsa(cipher_matrix[i], d, n)) # get inverse from matrix key_inverse = get_inverse(plain_matrix, int(sys.argv[12])) c = '' for i in plain_matrix: c = c + str(i) + '.' d = '' for i in key_inverse: d = d + str(i) + '.' print c + d

  10. dekripsiCitra.py

  from fungsi import do_hill_cipher, create_png import Image import sys # load image, get pixel and size image = Image.open(sys.argv[1]) pixels = image.load() image_size = image.size x = image_size[0] y = image_size[1] cipher_pixel = [] #get image pixels value for i in range (x): for j in range (y): cipher_pixel.append(pixels[i, j]) key_inverse = [] for i in range(9): key_inverse.append(int(sys.argv[i+2])) key_round = 1 # image decryption process plain_pixel = [] plain_pixel = cipher_pixel for i in range(key_round): plain_pixel = do_hill_cipher(key_inverse, x, y, plain_pixel) ling2 = "C:\Users\JPS\Desktop\RestoredPlainImage.png" # export decryption image create_png(x, y, plain_pixel).save(ling2, 'PNG') print ling2

  

CURRICULUM VITAE

Nama : Johanes Prima Saragih Alamat Sekarang : Jln. Menteng Raya, Gg. Pribadi No. 24 Medan Alamat Orangtua : Panyabungan Telp/Hp : 085277997959 Email : johanesaragih22@gmail.com Riwayat Pendidikan 2010 – 2015 : S-1 Ilmu Komputer Universitas Sumatera Utara, Medan 2006 – 2009 : SMA Negeri 3 Medan 2003 – 2006 : SMP Swasta Budi Murni 1 Medan 1997 – 2003 : SD Swasta Methodist I Aek Nabara Keahlian Bahasa Pemrograman : Python. Database : Microsoft Access, MySQL.

Dokumen yang terkait

Akumulasi Logam Berat (Cu Dan Pb) Pada Rhizophora Stylosa Berdasarkan Tingkat Pancang Dan Pohon

0 0 15

Akumulasi Logam Berat (Cu Dan Pb) Pada Rhizophora Stylosa Berdasarkan Tingkat Pancang Dan Pohon

0 1 11

BAB 2 TINJAUAN PUSTAKA 2.1 Radiografi Sefalometri - Perbandingan Konsistensi Garis E Ricketts Dan Garis S Steiner Dalam Analisis Posisi Horizontal Bibir Pada Mahasiswa Fkg Usu Suku India

0 0 17

Pengaruh Stres Kerja Dan Kompensasi Terhadap Turnover Intention Pada Pt Perkebunan Nusantara Iii (Persero)

0 0 46

BAB II TINJAUAN PUSTAKA 2.1 Uraian Teoritis 2.1.1 Stres Kerja - Pengaruh Stres Kerja Dan Kompensasi Terhadap Turnover Intention Pada Pt Perkebunan Nusantara Iii (Persero)

0 0 8

BAB 2 TINJAUAN PUSTAKA 2.1 Potensial Coulomb untuk Partikel yang Bergerak - Pengaruh Relativistik Terhadap Koreksi Potensial Coulomb Pada Tingkat Atom Hidrogen

0 0 9

BAB 2 TINJAUAN PUSTAKA 2.1 Potensial Coulomb untuk Partikel yang Bergerak - Pengaruh Relativistik Terhadap Koreksi Potensial Coulomb Pada Tingkat Atom Hidrogen

0 0 9

BAB 2 TINJAUAN PUSTAKA 2.1 Saliva - Efektifitas Mengunyah Keju Cheddar Terhadap Peningkatan Konsentrasi Ion Kalsium Saliva Pada Mahasiswa Fakultas Kedokteran Gigi Universitas Sumatera Utara

0 1 9

Efektifitas Mengunyah Keju Cheddar Terhadap Peningkatan Konsentrasi Ion Kalsium Saliva Pada Mahasiswa Fakultas Kedokteran Gigi Universitas Sumatera Utara

0 0 11

BAB II DIVERSI SEBAGAI SUATU KEWAJIBAN DI DALAM PENYELESAIAN PERKARA PIDANA ANAK A. Konsep Diversi dan Restorative Justice Pada Sistem Pengadilan Anak - Penerapan Diversi Di Dalam Penyelesaian Perkara Pidana Anak

0 0 33