This is one of my class assignment in Security, please take a look at my Miller-Rabin prime number test for more information.
Enjoy.
[code]import java.math.*;
import java.util.*;
public class MyRSA {
private static Random aRand;
private static BigInteger n;
private static BigInteger pn;
private static BigInteger e;
private static BigInteger d;
private static BigInteger IV;
private static BigInteger p, q;
private static final int MAX_BIT = 1024;
private static final int MAX_TRY = 5;
private static final int CHR_SIZE = 8;
private static final BigInteger ONE = BigInteger.valueOf(1);
private static int blocLength;
private static int ZN = 256;
private static String myPadding = "The wolrd wonders";
public MyRSA(Random aRandom) {
aRand = aRandom;
generatePQ(aRand);
findED();
}
public BigInteger getN() {
return n;
}
public BigInteger getE() {
return e;
}
public BigInteger getD() {
return d;
}
public static BigInteger RSAEncrypt(BigInteger m) {
return m.modPow(e, n);
}
public static BigInteger RSADecrypt(BigInteger c) {
return c.modPow(d, n);
}
public static BigInteger RSAEncrypt(BigInteger am, BigInteger an, BigInteger ae) {
return am.modPow(ae, an);
}
public static BigInteger RSADecrypt(BigInteger ac, BigInteger an, BigInteger ad) {
return ac.modPow(ad, an);
}
public String RSAEncryptBloc(String aString) {
String result = "";
Vector<String> aVectorMStr = new Vector<String>();
Vector<String> aVectorCStr = new Vector<String>();
Vector<BigInteger> aVectorMInt = new Vector<BigInteger>();
Vector<BigInteger> aVectorCInt = new Vector<BigInteger>();
blocLength = findBlocLength();
genIV(blocLength);
aVectorMStr = chopStringToAsciiBlocs(aString, blocLength, true);
aVectorMInt = getBigIntVector(aVectorMStr);
for (int i = 0; i < aVectorMInt.size(); i++) {
if (i == 0) {
aVectorCInt.add(RSAEncrypt(aVectorMInt.elementAt(0).xor(IV)));
} else {
aVectorCInt.add(RSAEncrypt(aVectorMInt.elementAt(i).xor(aVectorCInt.elementAt(i - 1))));
}
}
aVectorCStr = getAsciiVector(aVectorCInt);
for(int i = 0; i < aVectorCStr.size(); i++) {
result += aVectorCStr.elementAt(i);
}
return result;
}
public String RSADecryptBloc(String aString) {
String result = "";
Vector<String> aVectorCStr = new Vector<String>();
Vector<String> aVectorMStr = new Vector<String>();
Vector<BigInteger> aVectorCInt = new Vector<BigInteger>();
Vector<BigInteger> aVectorMInt = new Vector<BigInteger>();
aVectorCStr = chopStringToAsciiBlocs(aString, blocLength + 1, false);
aVectorCInt = getBigIntVector(aVectorCStr);
for (int i = 0; i < aVectorCInt.size(); i++) {
if (i == 0) {
aVectorMInt.add(RSADecrypt(aVectorCInt.elementAt(0)).xor(IV));
} else {
aVectorMInt.add(RSADecrypt(aVectorCInt.elementAt(i)).xor(aVectorCInt.elementAt(i - 1)) );
}
}
aVectorMStr = getAsciiVector(aVectorMInt);
for (int i = 0; i < aVectorMStr.size(); i++) {
result += aVectorMStr.elementAt(i);
}
result = removePadding(result);
return result;
}
public static Vector<String> getAsciiVector(Vector<BigInteger> aVectorInt) {
Vector<String> aVectorStr = new Vector<String>();
for (int i = 0; i < aVectorInt.size(); i++) {
aVectorStr.add(convertBigIntegerToAsciiBlocBaseN(aVectorInt.elementAt(i)));
}
return aVectorStr;
}
public static String convertBigIntegerToAsciiBlocBaseN(BigInteger aBigInt) {
String result = "";
int t;
Vector<Character> aCharVector = new Vector<Character>();
BigInteger m = aBigInt;
do {
t = m.mod(BigInteger.valueOf(ZN)).intValue();
m = m.divide(BigInteger.valueOf(ZN));
char c = (char)t;
aCharVector.add(new Character(c));
}while (m.compareTo(BigInteger.ZERO) > 0);
for (int i = 0; i < aCharVector.size(); i++ ) {
result += aCharVector.elementAt(i);
}
return result;
}
public static Vector<BigInteger> getBigIntVector(Vector<String> aVectorStr) {
Vector<BigInteger> aVectorBigInt = new Vector<BigInteger>();
for (int i = 0; i < aVectorStr.size(); i++) {
aVectorBigInt.add(convertAsciiBloctToBigIntegerBaseN(aVectorStr.elementAt(i)));
}
return aVectorBigInt;
}
public static BigInteger convertAsciiBloctToBigIntegerBaseN(String aString) {
BigInteger result = BigInteger.ZERO;
for (int i = 0; i < aString.length(); i++) {
int n = (char)aString.charAt(i);
result = result.add(BigInteger.valueOf(ZN).pow(i).multiply(BigInteger.valueOf(n)));
}
return result;
}
public static int findBlocLength() {
int l = 0;
BigInteger t = n;
while(t.compareTo(BigInteger.valueOf(ZN)) > 0) {
t = t.subtract(t.remainder(BigInteger.valueOf(ZN)));
t = t.divide(BigInteger.valueOf(ZN));
l++;
}
return l;
}
private static void generatePQ(Random aRand) {
p = new BigInteger(MAX_BIT, MAX_TRY, aRand);
do {
q = new BigInteger(MAX_BIT, MAX_TRY, aRand);
} while (q.compareTo(p) == 0);
n = p.multiply(q);
pn = (p.subtract(ONE)).multiply(q.subtract(ONE));
//System.out.println("p: " + p.toString());
//System.out.println("q: " + q.toString());
//System.out.println("n: " + n.toString());
//System.out.println("pn: " + pn.toString());
}
private static void findED() {
BigInteger aGCD;
do {
e = myBigRanNum(MAX_BIT);
if (e.compareTo(pn) >= 0) e = e.mod(pn);
aGCD = gcd(e, pn);
//System.out.println("e: " + e.toString());
} while (e.compareTo(BigInteger.ZERO) == 0 || e.compareTo(BigInteger.ONE) == 0 || aGCD.compareTo(BigInteger.ONE) != 0);
//System.out.println("e: " + e.toString());
d = ModInverse(e, pn);
//d = e.modInverse(pn);
//System.out.println("d: " + d.toString());
}
public static void genIV(int blocLength) {
IV = new BigInteger(blocLength * CHR_SIZE, aRand);
}
public static Vector<String> chopStringToAsciiBlocs(String aString, int blocLength, boolean padding) {
Vector<String> aVectorStr = new Vector<String>();
String tmp = aString;
do {
if (tmp.length() > blocLength) {
String m = tmp.substring(0, blocLength);
tmp = tmp.substring(blocLength);
aVectorStr.add(m);
//System.out.println("chop > : " + m);
} else if (tmp.length() == blocLength) {
aVectorStr.add(tmp);
//System.out.println("chop = : " + tmp);
if (padding) aVectorStr.add(addPadding("", blocLength));
break;
} else {
//System.out.println("chop < : " + tmp);
if (padding) aVectorStr.add(addPadding(tmp, blocLength));
break;
}
} while (true);
return aVectorStr;
}
public static String addPadding(String m, int l) {
String result = m;
int i = 0;
do {
result = result + myPadding.charAt(i);
i++;
if (i >= myPadding.length()) {
i = 0;
}
} while (result.length() < l);
return result;
}
public static String removePadding(String aString) {
String result = aString;
String tmp = "";
for (int i = 0; i < myPadding.length(); i++) {
tmp = myPadding.substring(0, myPadding.length() - 1 -i );
if (result.endsWith(tmp)) {
result = result.substring(0, result.indexOf(tmp));
break;
}
}
return result;
}
public static BigInteger gcd(BigInteger x, BigInteger y) {
BigInteger a = x;
BigInteger b = y;
while (b.compareTo(BigInteger.ZERO) != 0) {
BigInteger t = b;
b = a.mod(b);
a = t;
}
return a;
}
public static BigInteger ModInverse(BigInteger mx, BigInteger my) {
BigInteger a = mx;
BigInteger b = my;
BigInteger x = BigInteger.ZERO;
BigInteger y = BigInteger.ONE;
BigInteger lx = BigInteger.ONE;
BigInteger ly = BigInteger.ZERO;
while (b.compareTo(BigInteger.ZERO) != 0) {
//System.out.print(a.toString() + " " + b.toString() + " ");
BigInteger t = b;
b = a.mod(b);
BigInteger q = (a.subtract(b)).divide(t);
//System.out.println(q.toString());
a = t;
t = x;
x = lx.subtract(q.multiply(x));
lx = t;
t = y;
y = ly.subtract(q.multiply(y));
ly = t;
}
if (lx.compareTo(BigInteger.ZERO) < 0) lx = lx.add(my);
return lx;
}
public static BigInteger myBigRanNum(int numBits) {
//We only deal with positive number
BigInteger aBigInterger = new BigInteger(numBits, aRand);
aBigInterger = aBigInterger.abs();
return aBigInterger;
}
}[/code]