IMPLEMENTASI ALGORITMA KRIPTOGRAFI RSA DAN RABIN PADA THREE-PASS PROTOCOL UNTUK PENGAMANAN DATA PADA APLIKASI CHAT BERBASIS ANDROID
A-1
LISTING PROGRAM
1. Program Rabin
package com.januar.tppchat.crypto;
import java.nio.ByteBuffer;
public class Rabin {
public static long Encrypt(long n, long m) {
long cipher = GeneralMath.ModularExponential(m, 2, n);
return cipher;
}
public static long Decrypt(Long cipher, int p, int q){
long[] euclidean = GeneralMath.ExtendedEuclideanAll(p, q);
long Yp = euclidean[1];
long Yq = euclidean[2];
long mp = 0;
long mq = 0;
long n = p * q;
mp = GeneralMath.ModularExponential(cipher, (p+1)/4, p);
mq = GeneralMath.ModularExponential(cipher, (q+1)/4, q);
Long R = GeneralMath.mod((Yp * p * mq) + (Yq * q * mp), n);
Long S = GeneralMath.mod((Yp * p * mq) - (Yq * q * mp), n);
Long T = GeneralMath.mod(-1*(Yp * p * mq) + (Yq * q * mp),
n);
Long U = GeneralMath.mod(-1*(Yp * p * mq) - (Yq * q * mp),
n);
if (checkSimilarity(R) != -1) {
return checkSimilarity(R);
}else if (checkSimilarity(S) != -1) {
return checkSimilarity(S);
}else if (checkSimilarity(T) != -1) {
return checkSimilarity(T);
}else if (checkSimilarity(U) != -1) {
return checkSimilarity(U);
}
return 0;
}
public static long[] DecryptArray(Long cipher, long p, long q){
long[] euclidean = GeneralMath.ExtendedEuclideanAll(p, q);
long Yp = euclidean[1];
long Yq = euclidean[2];
long mp = 0;
long mq = 0;
long n = p * q;
mp = GeneralMath.ModularExponential(cipher, (p+1)/4, p);
mq = GeneralMath.ModularExponential(cipher, (q+1)/4, q);
Long R = GeneralMath.mod((Yp * p * mq) + (Yq * q * mp), n);
Long S = GeneralMath.mod((Yp * p * mq) - (Yq * q * mp), n);
Long T = GeneralMath.mod(-1*(Yp * p * mq) + (Yq * q * mp),
A-2
n);
Long U = GeneralMath.mod(-1*(Yp * p * mq) - (Yq * q * mp),
n);
long[] result = new long[]{R,S,T,U};
return result;
}
public static String Decrypt(int p, int q, byte[] cipherByte) throws
InvalidKeyException {
String plainText = "";
for (int i = 0; i < cipherByte.length / 8; i++) {
byte[] cipher = new byte[4];
byte[] kongruenByte = new byte[4];
for (int j = 0; j < kongruenByte.length; j++) {
cipher[j] = cipherByte[(i*8)+j];
kongruenByte[j] = cipherByte[(i*8+4)+j];
}
int cipherInt = ByteBuffer.wrap(cipher).getInt();
int plainInt = (int)Decrypt((long)cipherInt, p, q);
if (plainInt == 0) {
throw new InvalidKeyException("private key wrong.");
}
String plainBitString = Integer.toString(plainInt, 2);
plainText = plainText +
(char)Integer.parseInt(plainBitString.substring(0,
plainBitString.length() - 8), 2)
+
(char)Integer.parseInt(plainBitString.substring(plainBitString.length
() - 8), 2);
}
return plainText;
}
public static int checkSimilarity(Long p)
{
String binary = Long.toString(p, 2);
if ((binary.length() % 2) == 0) {
if (binary.substring(0, binary.length() /
2).equals(binary.substring(binary.length() /2))) {
return Integer.parseInt(binary.substring(0, binary.length() /2), 2);
}else{
return -1;
}
} else {
return -1;
}
}
}
A-3
2. Program RSA
package com.januar.tppchat.crypto;
import java.math.BigInteger;
import java.util.Random;
public class RSA {
public static long getPublicKey(long totien){
Random random = new Random();
long e = 100 + (long)(random.nextDouble()*(totien - 100));
while (GeneralMath.GCD(totien, e) != 1) {
e = 100 + (long)(random.nextDouble()*(totien - 100));
}
return e;
}
public static long getPrivateKey(long totien, long e){
return GeneralMath.ExtendedEuclidean(totien, e);
}
public static long Encrypt(long m, long e, long n){
//
return GeneralMath.ModularExponential(m, e, n);
BigInteger b_m = new BigInteger(Long.toString(m));
BigInteger b_e = new BigInteger(Long.toString(e));
BigInteger b_n = new BigInteger(Long.toString(n));
BigInteger result = b_m.modPow(b_e,b_n);
return Long.parseLong(result.toString());
}
public static long Decrypt(long c, long d, long n){
//
return GeneralMath.ModularExponential(c, d, n);
BigInteger b_c = new BigInteger(Long.toString(c));
BigInteger b_d = new BigInteger(Long.toString(d));
BigInteger b_n = new BigInteger(Long.toString(n));
BigInteger result = b_c.modPow(b_d,b_n);
return Long.parseLong(result.toString());
}
}
3. Program Sieve of Eratosthenes
package com.januar.tppchat.crypto;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class SieveofEratosthenes {
public static final int MAX = 99999999;
public static List generate(int min, int limit) {
//int limit = 99999999; // Batas maksimum bil. prima yang dicari
A-4
boolean[] bil_asal = new boolean[limit];
for (int i = 0; i < limit; i++) {
bil_asal[i] = true;
}
bil_asal[0] = false; // bilangan 0 bukan bilangan prima
bil_asal[1] = false; // bilangan 1 bukan bilangan prima
// Penerapan algoritma Sieve of Erathosthenes
for (int i = 2; i = min) {
prima.add(i);
}
}
System.out.println("Jumlah bilangan prima antara "+ min +"
sampai " + limit
+ " adalah " + prima.size() + " buah");
return prima;
}
public static List generate() {
return SieveofEratosthenes.generate(2, MAX);
}
public static List generate(int limit) {
return SieveofEratosthenes.generate(2, limit);
}
public static List generateKey() {
List keys = new ArrayList();
List prima = SieveofEratosthenes.generate(100,
10000);
Random random = new Random();
int q = 0;
int temp = random.nextInt(prima.size());
keys.add(prima.get(temp));
do {
temp = random.nextInt(prima.size());
q = prima.get(temp);
} while (keys.get(0) == q);
keys.add(q);
return keys;
}
public static List generateRabinKey() {
List keys = new ArrayList();
List prima = SieveofEratosthenes.generate(100000,
1000000);
A-5
Random random = new Random();
while (keys.size() != 2) {
int temp = random.nextInt(prima.size());
if (prima.get(temp) % 4 == 3) {
if (!keys.contains(prima.get(temp))) {
keys.add(prima.get(temp));
}
}
}
return keys;
}
}
4. Program Three-Pass Protocol
package com.januar.tppchat.crypto;
import android.util.Base64;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
public class ThreePassProtocol {
public static String PassOne(String text, long n) throws
UnsupportedEncodingException {
byte[] cipherByte = new byte[text.length() * 8]; // dikali 8 karena
ukuran tipe data long
int i = 0;
for (char ch : text.toCharArray()) {
int c = (int)ch;
String plaintext = Integer.toString(c, 2);
plaintext = plaintext + plaintext;
long m = Long.parseLong(plaintext, 2);
long enc = Rabin.Encrypt(n, m);
System.arraycopy(ByteBuffer.allocate(8).putLong(enc).array(), 0,
cipherByte, i * 8, 8);
i++;
}
return Base64.encodeToString(cipherByte, Base64.DEFAULT);
}
public static String PassTwo(String text, long e, long n) throws
UnsupportedEncodingException {
byte[] plainByte = Base64.decode(text, Base64.DEFAULT);
byte[] cipherByte = new byte[plainByte.length]; // panjang byte plain
dengan cipher sama
for (int i = 0; i < (plainByte.length / 8); i++) {
byte[] temp = new byte[8];
System.arraycopy(plainByte, i * 8, temp, 0, 8);
long m = ByteBuffer.wrap(temp).getLong();
long enc = RSA.Encrypt(m, e, n);
A-6
System.arraycopy(ByteBuffer.allocate(8).putLong(enc).array(), 0,
cipherByte, i * 8, 8);
}
return Base64.encodeToString(cipherByte, Base64.DEFAULT);
}
public static String PassThree(String text, long p, long q) throws
UnsupportedEncodingException {
byte[] cipherByte = Base64.decode(text, Base64.DEFAULT);
byte[] plainByte = new byte[cipherByte.length * 4]; // setiap satu
bilangan menghasilkan 4 hasil dekripsi
for (int i = 0; i < (cipherByte.length / 8); i++) {
byte[] temp = new byte[8];
System.arraycopy(cipherByte, i * 8, temp, 0, 8);
long c = ByteBuffer.wrap(temp).getLong();
long[] dec = Rabin.DecryptArray(c, p, q);
byte[] decByte = new byte[32];
System.arraycopy(ByteBuffer.allocate(8).putLong(dec[0]).array(), 0,
decByte, 0, 8);
System.arraycopy(ByteBuffer.allocate(8).putLong(dec[1]).array(), 0,
decByte, 8, 8);
System.arraycopy(ByteBuffer.allocate(8).putLong(dec[2]).array(), 0,
decByte, 16, 8);
System.arraycopy(ByteBuffer.allocate(8).putLong(dec[3]).array(), 0,
decByte, 24, 8);
System.arraycopy(decByte, 0, plainByte, (i * 32), 32);
}
return Base64.encodeToString(plainByte, Base64.DEFAULT);
}
public static String DecryptResult(String text, long d, long n) {
String plain = "";
byte[] cipherByte = Base64.decode(text, Base64.DEFAULT);
for (int i = 0; i < (cipherByte.length / 32); i++) {
byte[] temp = new byte[8];
System.arraycopy(cipherByte, i * 32, temp, 0, 8);
long c = ByteBuffer.wrap(temp).getLong();
long c1 = Rabin.checkSimilarity(RSA.Decrypt(c, d, n));
System.arraycopy(cipherByte, (i * 32) + 8, temp, 0, 8);
c = ByteBuffer.wrap(temp).getLong();
long c2 = Rabin.checkSimilarity(RSA.Decrypt(c, d, n));
System.arraycopy(cipherByte, (i * 32) + 16, temp, 0, 8);
c = ByteBuffer.wrap(temp).getLong();
long c3 = Rabin.checkSimilarity(RSA.Decrypt(c, d, n));
System.arraycopy(cipherByte, (i * 32) + 24, temp, 0, 8);
c = ByteBuffer.wrap(temp).getLong();
long c4 = Rabin.checkSimilarity(RSA.Decrypt(c, d, n));
if(c1 != -1){
plain += (char)c1;
}else if(c2 != -1){
A-7
plain += (char)c2;
}else if(c3 != -1){
plain += (char)c3;
}else if(c4 != -1){
plain += (char)c4;
}
}
return plain;
}
}
B-1
CURRICULUM VITAE
DATA PRIBADI
Nama Lengkap
: Januar Andi Halomoan Sirait
Tempat / Tanggal lahir : Medan / 21Januari 1991
Alamat rumah
: Dusun I Kamboja, Laut Dendang
Deli Serdang
Jenis Kelamin
: Laki-Laki
Agama
: Kristen Protestan
Status
: Belum menikah
No. HP
: 085760534549
E-mail
: januar.srt@gmail.com
RIWAYAT PENDIDIKAN FORMAL
1998-2003
: SD BUDI MURNI 7 MEDAN
2003-2006
: SMP BUDI MURNI 4 MEDAN
2006-2009
: SMA NEGERI 7 MEDAN
2009-2012
: POLITEKNIK INFORMATIKA DEL
SEMINAR
2014
: Peserta Seminar Nasional Literasi Informasi (SENARAI)
PENGALAMAN KERJA
2012
: Kerja Praktek di PT. Mandiri Inti Perkasa ,
Jakarta – Kalimantan Timur
2012 - 2016
: Bekerja di PT. Halotec Indonesia, Medan
2016 – sekarang : Bekerja di PT. Infomasi Guna Optima (inGO), Medan
LISTING PROGRAM
1. Program Rabin
package com.januar.tppchat.crypto;
import java.nio.ByteBuffer;
public class Rabin {
public static long Encrypt(long n, long m) {
long cipher = GeneralMath.ModularExponential(m, 2, n);
return cipher;
}
public static long Decrypt(Long cipher, int p, int q){
long[] euclidean = GeneralMath.ExtendedEuclideanAll(p, q);
long Yp = euclidean[1];
long Yq = euclidean[2];
long mp = 0;
long mq = 0;
long n = p * q;
mp = GeneralMath.ModularExponential(cipher, (p+1)/4, p);
mq = GeneralMath.ModularExponential(cipher, (q+1)/4, q);
Long R = GeneralMath.mod((Yp * p * mq) + (Yq * q * mp), n);
Long S = GeneralMath.mod((Yp * p * mq) - (Yq * q * mp), n);
Long T = GeneralMath.mod(-1*(Yp * p * mq) + (Yq * q * mp),
n);
Long U = GeneralMath.mod(-1*(Yp * p * mq) - (Yq * q * mp),
n);
if (checkSimilarity(R) != -1) {
return checkSimilarity(R);
}else if (checkSimilarity(S) != -1) {
return checkSimilarity(S);
}else if (checkSimilarity(T) != -1) {
return checkSimilarity(T);
}else if (checkSimilarity(U) != -1) {
return checkSimilarity(U);
}
return 0;
}
public static long[] DecryptArray(Long cipher, long p, long q){
long[] euclidean = GeneralMath.ExtendedEuclideanAll(p, q);
long Yp = euclidean[1];
long Yq = euclidean[2];
long mp = 0;
long mq = 0;
long n = p * q;
mp = GeneralMath.ModularExponential(cipher, (p+1)/4, p);
mq = GeneralMath.ModularExponential(cipher, (q+1)/4, q);
Long R = GeneralMath.mod((Yp * p * mq) + (Yq * q * mp), n);
Long S = GeneralMath.mod((Yp * p * mq) - (Yq * q * mp), n);
Long T = GeneralMath.mod(-1*(Yp * p * mq) + (Yq * q * mp),
A-2
n);
Long U = GeneralMath.mod(-1*(Yp * p * mq) - (Yq * q * mp),
n);
long[] result = new long[]{R,S,T,U};
return result;
}
public static String Decrypt(int p, int q, byte[] cipherByte) throws
InvalidKeyException {
String plainText = "";
for (int i = 0; i < cipherByte.length / 8; i++) {
byte[] cipher = new byte[4];
byte[] kongruenByte = new byte[4];
for (int j = 0; j < kongruenByte.length; j++) {
cipher[j] = cipherByte[(i*8)+j];
kongruenByte[j] = cipherByte[(i*8+4)+j];
}
int cipherInt = ByteBuffer.wrap(cipher).getInt();
int plainInt = (int)Decrypt((long)cipherInt, p, q);
if (plainInt == 0) {
throw new InvalidKeyException("private key wrong.");
}
String plainBitString = Integer.toString(plainInt, 2);
plainText = plainText +
(char)Integer.parseInt(plainBitString.substring(0,
plainBitString.length() - 8), 2)
+
(char)Integer.parseInt(plainBitString.substring(plainBitString.length
() - 8), 2);
}
return plainText;
}
public static int checkSimilarity(Long p)
{
String binary = Long.toString(p, 2);
if ((binary.length() % 2) == 0) {
if (binary.substring(0, binary.length() /
2).equals(binary.substring(binary.length() /2))) {
return Integer.parseInt(binary.substring(0, binary.length() /2), 2);
}else{
return -1;
}
} else {
return -1;
}
}
}
A-3
2. Program RSA
package com.januar.tppchat.crypto;
import java.math.BigInteger;
import java.util.Random;
public class RSA {
public static long getPublicKey(long totien){
Random random = new Random();
long e = 100 + (long)(random.nextDouble()*(totien - 100));
while (GeneralMath.GCD(totien, e) != 1) {
e = 100 + (long)(random.nextDouble()*(totien - 100));
}
return e;
}
public static long getPrivateKey(long totien, long e){
return GeneralMath.ExtendedEuclidean(totien, e);
}
public static long Encrypt(long m, long e, long n){
//
return GeneralMath.ModularExponential(m, e, n);
BigInteger b_m = new BigInteger(Long.toString(m));
BigInteger b_e = new BigInteger(Long.toString(e));
BigInteger b_n = new BigInteger(Long.toString(n));
BigInteger result = b_m.modPow(b_e,b_n);
return Long.parseLong(result.toString());
}
public static long Decrypt(long c, long d, long n){
//
return GeneralMath.ModularExponential(c, d, n);
BigInteger b_c = new BigInteger(Long.toString(c));
BigInteger b_d = new BigInteger(Long.toString(d));
BigInteger b_n = new BigInteger(Long.toString(n));
BigInteger result = b_c.modPow(b_d,b_n);
return Long.parseLong(result.toString());
}
}
3. Program Sieve of Eratosthenes
package com.januar.tppchat.crypto;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class SieveofEratosthenes {
public static final int MAX = 99999999;
public static List generate(int min, int limit) {
//int limit = 99999999; // Batas maksimum bil. prima yang dicari
A-4
boolean[] bil_asal = new boolean[limit];
for (int i = 0; i < limit; i++) {
bil_asal[i] = true;
}
bil_asal[0] = false; // bilangan 0 bukan bilangan prima
bil_asal[1] = false; // bilangan 1 bukan bilangan prima
// Penerapan algoritma Sieve of Erathosthenes
for (int i = 2; i = min) {
prima.add(i);
}
}
System.out.println("Jumlah bilangan prima antara "+ min +"
sampai " + limit
+ " adalah " + prima.size() + " buah");
return prima;
}
public static List generate() {
return SieveofEratosthenes.generate(2, MAX);
}
public static List generate(int limit) {
return SieveofEratosthenes.generate(2, limit);
}
public static List generateKey() {
List keys = new ArrayList();
List prima = SieveofEratosthenes.generate(100,
10000);
Random random = new Random();
int q = 0;
int temp = random.nextInt(prima.size());
keys.add(prima.get(temp));
do {
temp = random.nextInt(prima.size());
q = prima.get(temp);
} while (keys.get(0) == q);
keys.add(q);
return keys;
}
public static List generateRabinKey() {
List keys = new ArrayList();
List prima = SieveofEratosthenes.generate(100000,
1000000);
A-5
Random random = new Random();
while (keys.size() != 2) {
int temp = random.nextInt(prima.size());
if (prima.get(temp) % 4 == 3) {
if (!keys.contains(prima.get(temp))) {
keys.add(prima.get(temp));
}
}
}
return keys;
}
}
4. Program Three-Pass Protocol
package com.januar.tppchat.crypto;
import android.util.Base64;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
public class ThreePassProtocol {
public static String PassOne(String text, long n) throws
UnsupportedEncodingException {
byte[] cipherByte = new byte[text.length() * 8]; // dikali 8 karena
ukuran tipe data long
int i = 0;
for (char ch : text.toCharArray()) {
int c = (int)ch;
String plaintext = Integer.toString(c, 2);
plaintext = plaintext + plaintext;
long m = Long.parseLong(plaintext, 2);
long enc = Rabin.Encrypt(n, m);
System.arraycopy(ByteBuffer.allocate(8).putLong(enc).array(), 0,
cipherByte, i * 8, 8);
i++;
}
return Base64.encodeToString(cipherByte, Base64.DEFAULT);
}
public static String PassTwo(String text, long e, long n) throws
UnsupportedEncodingException {
byte[] plainByte = Base64.decode(text, Base64.DEFAULT);
byte[] cipherByte = new byte[plainByte.length]; // panjang byte plain
dengan cipher sama
for (int i = 0; i < (plainByte.length / 8); i++) {
byte[] temp = new byte[8];
System.arraycopy(plainByte, i * 8, temp, 0, 8);
long m = ByteBuffer.wrap(temp).getLong();
long enc = RSA.Encrypt(m, e, n);
A-6
System.arraycopy(ByteBuffer.allocate(8).putLong(enc).array(), 0,
cipherByte, i * 8, 8);
}
return Base64.encodeToString(cipherByte, Base64.DEFAULT);
}
public static String PassThree(String text, long p, long q) throws
UnsupportedEncodingException {
byte[] cipherByte = Base64.decode(text, Base64.DEFAULT);
byte[] plainByte = new byte[cipherByte.length * 4]; // setiap satu
bilangan menghasilkan 4 hasil dekripsi
for (int i = 0; i < (cipherByte.length / 8); i++) {
byte[] temp = new byte[8];
System.arraycopy(cipherByte, i * 8, temp, 0, 8);
long c = ByteBuffer.wrap(temp).getLong();
long[] dec = Rabin.DecryptArray(c, p, q);
byte[] decByte = new byte[32];
System.arraycopy(ByteBuffer.allocate(8).putLong(dec[0]).array(), 0,
decByte, 0, 8);
System.arraycopy(ByteBuffer.allocate(8).putLong(dec[1]).array(), 0,
decByte, 8, 8);
System.arraycopy(ByteBuffer.allocate(8).putLong(dec[2]).array(), 0,
decByte, 16, 8);
System.arraycopy(ByteBuffer.allocate(8).putLong(dec[3]).array(), 0,
decByte, 24, 8);
System.arraycopy(decByte, 0, plainByte, (i * 32), 32);
}
return Base64.encodeToString(plainByte, Base64.DEFAULT);
}
public static String DecryptResult(String text, long d, long n) {
String plain = "";
byte[] cipherByte = Base64.decode(text, Base64.DEFAULT);
for (int i = 0; i < (cipherByte.length / 32); i++) {
byte[] temp = new byte[8];
System.arraycopy(cipherByte, i * 32, temp, 0, 8);
long c = ByteBuffer.wrap(temp).getLong();
long c1 = Rabin.checkSimilarity(RSA.Decrypt(c, d, n));
System.arraycopy(cipherByte, (i * 32) + 8, temp, 0, 8);
c = ByteBuffer.wrap(temp).getLong();
long c2 = Rabin.checkSimilarity(RSA.Decrypt(c, d, n));
System.arraycopy(cipherByte, (i * 32) + 16, temp, 0, 8);
c = ByteBuffer.wrap(temp).getLong();
long c3 = Rabin.checkSimilarity(RSA.Decrypt(c, d, n));
System.arraycopy(cipherByte, (i * 32) + 24, temp, 0, 8);
c = ByteBuffer.wrap(temp).getLong();
long c4 = Rabin.checkSimilarity(RSA.Decrypt(c, d, n));
if(c1 != -1){
plain += (char)c1;
}else if(c2 != -1){
A-7
plain += (char)c2;
}else if(c3 != -1){
plain += (char)c3;
}else if(c4 != -1){
plain += (char)c4;
}
}
return plain;
}
}
B-1
CURRICULUM VITAE
DATA PRIBADI
Nama Lengkap
: Januar Andi Halomoan Sirait
Tempat / Tanggal lahir : Medan / 21Januari 1991
Alamat rumah
: Dusun I Kamboja, Laut Dendang
Deli Serdang
Jenis Kelamin
: Laki-Laki
Agama
: Kristen Protestan
Status
: Belum menikah
No. HP
: 085760534549
: januar.srt@gmail.com
RIWAYAT PENDIDIKAN FORMAL
1998-2003
: SD BUDI MURNI 7 MEDAN
2003-2006
: SMP BUDI MURNI 4 MEDAN
2006-2009
: SMA NEGERI 7 MEDAN
2009-2012
: POLITEKNIK INFORMATIKA DEL
SEMINAR
2014
: Peserta Seminar Nasional Literasi Informasi (SENARAI)
PENGALAMAN KERJA
2012
: Kerja Praktek di PT. Mandiri Inti Perkasa ,
Jakarta – Kalimantan Timur
2012 - 2016
: Bekerja di PT. Halotec Indonesia, Medan
2016 – sekarang : Bekerja di PT. Infomasi Guna Optima (inGO), Medan