我应该编写代码来模拟三种加密技术的工作: - Caesar Cipher,Columnar Transposition和RSA。我创建了一个名为Encryption的接口
public interface Encryption {
public String encrypt(String key, String message);
}
并制作了两个班级。 CaesarCipherEncryptor和
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实现它。
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();
}
// TODO Auto-generated method stub
return cipherText;
}
}
这两个类是Singeltons,因为它们是简单的算法。但是,正如维基百科链接中给出的,在RSA加密中,我需要将特定用户的状态存储在实体n,phiOfN,publicKey和privateKey中,以便模拟加密过程。请建议一个更通用的解决方案来构建RSAEncryptor类。下面给出的代码是我能解决的所有问题:|。
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);
}
}
这种类的结构是否正确?这是适当的OO设计吗?谢谢,提前。
答案 0 :(得分:5)
一个简单的解决方案是不使用你所称的单身人士。每次要加密时,只需创建一个加密实现的新实例。如果执行此操作,则可以在加密实例上存储所需的所有状态。这些实例只能用一次;你可以防止他们在代码中重复使用。
或者,由于您需要存储状态,因此可以创建EncryptionContext类,其实例将传递给您的encrypt方法。所有必要的状态都可以存储在这些上下文实例中,您可以对上下文进行错误检查,以确保在任何给定步骤中您需要执行的所有信息都存在。如果你做了这样的事情,你可以重用你的加密实现实例。你必须改变你的界面..
关于您对OO设计的担忧,您似乎正处于正确的轨道上。随着时间的推移获得适当的OO技能,你无法在课堂上学到它们。您正在正确使用接口,您正在询问有关如何处理状态的正确问题。您可以轻松地将解决方案集成到Strategy Pattern中,这很好。
编辑---
如果一个实现需要状态,那么它们也可能都需要状态。除非您想采用第三种选择,即为有状态加密算法创建单独的接口。但是,这是没有吸引力的,因为这是一个实现细节,不需要反映在接口中,其目的是表示行为而不是实现。我仍然会选择上面两个选项中的一个,或者是好的并且是OO,恕我直言。