Структурирование классов - PullRequest
3 голосов
/ 03 ноября 2010

Я должен написать коды для имитации работы трех методов шифрования: - Цезарь Шифр ​​, Транспонирование столбцов и 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);
    }

}

Правильно ли это структурирование классов?Это правильный дизайн ОО?Заранее спасибо.

1 Ответ

5 голосов
/ 03 ноября 2010

Простое решение - не использовать то, что вы называете одиночками.Каждый раз, когда вы хотите зашифровать, просто создайте новый экземпляр реализации шифрования.Если вы сделаете это, вы можете сохранить все необходимое состояние в экземплярах шифрования.Эти экземпляры предназначены для использования только один раз;вы можете защитить их от повторного использования в коде.

В качестве альтернативы, поскольку вам необходимо сохранить состояние, вы можете создать класс EncryptionContext, экземпляры которого передаются в ваш метод шифрования.Все необходимые состояния могут быть сохранены в этих экземплярах контекста, и вы можете проверить ошибки в контексте, чтобы убедиться, что присутствует вся информация, необходимая для продолжения на любом данном этапе.Если вы сделали что-то подобное, вы можете повторно использовать ваши экземпляры реализации шифрования.Вы должны будете изменить свой интерфейс, хотя ..

Что касается вашей озабоченности по поводу ОО-дизайна, вы, кажется, на правильном пути.Надлежащие навыки ОО приобретаются с течением времени, вы не можете действительно изучить их в классе.Вы используете свои интерфейсы правильно, вы задаете правильные вопросы о том, как обрабатывать состояние.Вы можете легко интегрировать свое решение в шаблон стратегии , что хорошо.

EDIT ---

Если одна реализация нуждается в состоянии, то они также могут нуждаться в состоянии.Если вы не хотите использовать третий вариант, а именно создать отдельный интерфейс для алгоритмов шифрования с сохранением состояния.Тем не менее, это непривлекательно, так как это деталь реализации и не должна отражаться в интерфейсе, цель которого - представить поведение , а не реализация .Я бы все равно выбрал один из двух вариантов выше, либо все в порядке, но и ОО, ИМХО.

...