I am supposed to write codes to simulate the working of three Encryption techniques:- Caesar Cipher, Columnar Transposition and RSA. I made an interface named Encryption
public interface Encryption {
public String encrypt(String key, String message);
}
and made two classes viz. CaesarCipherEncryptor and
public class CaeserCipherEncryptor implements Encryption {
private static final CaeserCipherEncryptor INSTANCE = new CaeserCipherEncryptor();
private CaeserCipherEncryptor(){ }
public static CaeserCipherEncryptor getInstance(){
return INSTANCE;
}
public String encrypt(String key, String message) {
int noOfShifts = Integer.parseInt(key);
String cipherText = "";
for(char c:message.toCharArray()){
//to handle UpperCase and LowerCase alphabets
if((Character.isUpperCase(c) && ((c+noOfShifts) > 90)) || (Character.isLowerCase(c) && ((c+noOfShifts) > 122)))
c = (char)((c + noOfShifts) - 26);
else
c = (char)(c + noOfShifts);
cipherText += c;
}
return cipherText;
}
}
ColumnarTranspositionEncryptor implement it.
import java.util.ArrayList;
public class ColumnarTranspositionEncryptor implements Encryption {
private static final ColumnarTranspositionEncryptor INSTANCE = new ColumnarTranspositionEncryptor();
public static ColumnarTranspositionEncryptor getInstance(){
return INSTANCE;
}
private ColumnarTranspositionEncryptor(){}
@Override
public String encrypt(String key, String message) {
int rowLength = key.length();
key.toUpperCase();
ArrayList<Integer> finalOrder = new ArrayList<Integer>();
for(int i=0;i<rowLength;i++){
int rank=0;
char c = key.charAt(i);
for(int j=0;j<rowLength;j++){
if(c>key.charAt(j))
rank++;
}
finalOrder.add((rank+1));
}
ArrayList<String> rowsOfString=new ArrayList<String>();
for(;message.length()>rowLength;message=message.substring(rowLength)){
rowsOfString.add(message.substring(0, rowLength));
}
for(;message.length()>0 && message.length()<rowLength;){
char c=65;
message += (char)(c+new java.util.Random().nextInt(26));
}
rowsOfString.add(message);
String cipherText = "";
for(int i=1;i<=finalOrder.size();i++){
int j=finalOrder.indexOf(i);
for(String s:rowsOfString){
cipherText += s.charAt(j);
}
}
System.out.println("Alphabetical order and columns:");
for(int i:finalOrder)
System.out.print(i + " ");
System.out.println();
System.out.println();
for(String s:rowsOfString){
for(int i=0;i<s.length();i++)
System.out.print(s.charAt(i) + " ");
System.out.println();开发者_JAVA百科
}
// TODO Auto-generated method stub
return cipherText;
}
}
These two classes were made Singeltons since they are plain algorithms. However, as given in the wikipedia link, in RSA encryption, I need to store the state of a particular user in the entities n, phiOfN, publicKey and privateKey in order to simulate the procedure of encryption. Please suggest a more generalized solution for structuring the RSAEncryptor class. The below given code is all that I could work out :|.
import java.util.ArrayList;
import java.math.BigInteger;
public class RSAUser {
private int p,q,n,phiOfN, publicExponent, privateExponent;
private static int gcd(int a, int b) {
if (b == 0)
return a;
else
return gcd(b, a % b);
}
public RSAUser(int p,int q){
this.p = p;
this.q = q;
n = p * q;
int phiOfN = (p - 1) * (q - 1);
int min = Math.min(p, q);
this.publicExponent = 2;
ArrayList<Integer> x = new ArrayList<Integer>();
for (; publicExponent < min - 1; publicExponent++) {
if (RSAUser.gcd(publicExponent, phiOfN) == 1)
x.add(publicExponent);
}
this.publicExponent = x.get(new java.util.Random().nextInt(x.size()));
privateExponent = phiOfN / publicExponent;
for (int i = 1;; i++) {
long product = phiOfN * i + 1;
if (product % publicExponent == 0) {
privateExponent = (int)product / publicExponent;
break;
}
}
System.out.println("Public Key:"+this.getPublicKey()+"\nPrivate Key:"+this.getPrivateKey());
}
//to print in the format "(n, publicExponent)"
public String getPublicKey(){
return "("+Integer.toString(n)+","+Integer.toString(publicExponent)+")";
}
public String getPrivateKey(){
return "("+Integer.toString(n)+","+Integer.toString(privateExponent)+")";
}
}
public class RSAEncryptor implements Encryption {
private static RSAEncryptor instance = new RSAEncryptor();
private RSAEncryptor(){
}
public static RSAEncryptor getInstance(){
return instance;
}
@Override
public String encrypt(String key, String message) {
key.trim();
String[] keys = key.split(",");
String n = keys[0].substring(1).trim();
String publicExponent = keys[1].trim();
publicExponent = publicExponent.substring(0, publicExponent.length()-1);
BigInteger m = new BigInteger(message);
return m.pow(Integer.parseInt(publicExponent)).mod(new BigInteger(n)).toString(10);
}
}
Is this structuring of classes correct? Is this proper OO design? Thank You, in Advance.
A simple solution is to not use what you are calling singletons. Every time you want to encrypt, just create a new instance of an Encryption implementation. If you do this, you can store all the state you need on the encryption instances. These instances are only ever meant to be used once; you can guard against them being reused in the code.
Alternatively, since you need to to store state, you can create an EncryptionContext class, instances of which get passed to your encrypt method. All the necessary state can be stored in those context instances, and you can error check on the context to make sure all the info you need to proceed at any given step is present. If you did something like this you could reuse your Encryption implementation instances. You would have to change your interface though..
With respect to your concerns about OO design, you seem to be on the correct track. Proper OO skills are acquired over time, you can't really learn them in a class. You are using your interfaces correctly, you are asking the correct questions about how to handle state. You can easily integrate you solution into the Strategy Pattern, which is good.
EDIT ---
If one implementation needs state, then they might as well all need state. Unless you want to take a third option, which is create a separate interface for stateful encryption algorithms. However, this is unappealing, as this is an implementation detail and shouldn't need to be reflected in an interface, the purpose of which is to represent behavior and not implementation. I would still go with one of the two options above, either is ok and is OO, IMHO.
精彩评论