Что не так с моим кодом для изменения моего кода шифрования?

1

Я должен написать программу, которая использует смещение букв для шифрования строки, введенной пользователем. Код для шифрования выглядит так:

for (int j = 0; j<key; j++) {
    for (i = j; i <length; i += key)
    {
        password += phrase.charAt(i);
    }
}

Эта работа, как я ожидаю.

Например, когда я использую длину ключа 3, она изменяется

Testing1234567890ABCDEF

в

Ttg369BEei1470CFsn258AD

Моя проблема в том, когда я пытаюсь ее отменить.

for (int j = 0; j<=Math.ceil(phrase.length()/key); j++){
    for (int i = j; i < phrase.length(); i += Math.ceil((phrase.length()/key))+1)
    {
        password += phrase.charAt(i);
    }
}

Это работает для этой фразы по этому ключу, но не работает, если я использую другую фразу или другой ключ.

Что мне не хватает?

Теги:
string

3 ответа

1

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

public String encrypt(String s, int key) {
    String encrypted = "";
    for (int j = 0; j < key; j++) {
        for (int i = j; i < s.length(); i += key) {
            encrypted += s.charAt(i);
        }
    }
    return encrypted;
}

public String decrypt(String encrypted, int key) {
    String decrypted = "";
    for (int j = 0; j <= Math.ceil(encrypted.length() / key); j++) {
        for (int i = j; i < encrypted.length(); i += Math.ceil((encrypted.length() / key)) + 1) {
            decrypted += encrypted.charAt(i);
        }
    }
    return decrypted;
}

private static int gcd(int a, int b) {
    return BigInteger.valueOf(a).gcd(BigInteger.valueOf(b)).intValue();
}

private void test(String s) {
    for (int key = 1; key < 10; key++) {
        String encrypted = encrypt(s, key);
        String decrypted = decrypt(encrypted, key);
        boolean good = decrypted.equals(s);
        System.out.println(s + " -> " + encrypted + " -> " + decrypted + "(" + key + ")" + " gcd(" + s.length() + "," + key + ") = " + gcd(s.length(), key) + " " + (good ? "*" : ""));

    }
}

public void test() {
    test("Testing1234567890ABCDEF");
    test("Testing1234567890ABCDEFG");

}

печать

Testing1234567890ABCDEF -> Testing1234567890ABCDEF -> Testing1234567890ABCDEF(1) gcd(23,1) = 1 *
Testing1234567890ABCDEF -> Tsig24680BDFetn13579ACE -> Testing1234567890ABCDEF(2) gcd(23,2) = 1 *
Testing1234567890ABCDEF -> Ttg369BEei1470CFsn258AD -> Testing1234567890ABCDEF(3) gcd(23,3) = 1 *
Testing1234567890ABCDEF -> Ti260Den37AEsg48BFt159C -> Testing1234567890ABCDEF(4) gcd(23,4) = 1 *
Testing1234567890ABCDEF -> Tn49Deg50Es16AFt27Bi38C -> Test3ng1284567C90ABDEFi(5) gcd(23,5) = 1 
Testing1234567890ABCDEF -> Tg6Be17Cs28Dt39Ei40Fn5A -> Testing1234567890ABCDEF(6) gcd(23,6) = 1 *
Testing1234567890ABCDEF -> T18Ee29Fs30t4Ai5Bn6Cg7D -> Tes4Bg123An7890i6DEFt5C(7) gcd(23,7) = 1 
Testing1234567890ABCDEF -> T20e3As4Bt5Ci6Dn7Eg8F19 -> Testing1234567890ABCDEF(8) gcd(23,8) = 1 *
Testing1234567890ABCDEF -> T3Be4Cs5Dt6Ei7Fn8g9102A -> Testin923456781ABCDEFg0(9) gcd(23,9) = 1 
Testing1234567890ABCDEFG -> Testing1234567890ABCDEFG -> Testing1234567890ABCDEFG(1) gcd(24,1) = 1 *
Testing1234567890ABCDEFG -> Tsig24680BDFetn13579ACEG -> Ttsni1g32547698A0CBEDGFe(2) gcd(24,2) = 2 
Testing1234567890ABCDEFG -> Ttg369BEei1470CFsn258ADG -> Ti2t15g4837A60D9CGBFEsen(3) gcd(24,3) = 3 
Testing1234567890ABCDEFG -> Ti260Den37AEsg48BFt159CG -> Tn49i38C27BG6AF0EtDs1eg5(4) gcd(24,4) = 4 
Testing1234567890ABCDEFG -> Tn49Deg50Es16AFt27BGi38C -> Testing1234567890ABCDEFG(5) gcd(24,5) = 1 *
Testing1234567890ABCDEFG -> Tg6Be17Cs28Dt39Ei40Fn5AG -> T18Eng7Di56Ct4ABs30Ge29F(6) gcd(24,6) = 6 
Testing1234567890ABCDEFG -> T18Ee29Fs30Gt4Ai5Bn6Cg7D -> Test5C1234Bg890An7EFGi6D(7) gcd(24,7) = 1 
Testing1234567890ABCDEFG -> T20e3As4Bt5Ci6Dn7Eg8F19G -> T3Bi7F2At6E10s5Dg9e4Cn8G(8) gcd(24,8) = 8 
Testing1234567890ABCDEFG -> T3Be4Cs5Dt6Ei7Fn8Gg9102A -> Testing034567892BCDEFG1A(9) gcd(24,9) = 3 

Однако только потому, что они относительно простые, это не означает, что шифрование/расшифровка будет работать.

Все еще смотрю на это.

0

Основная проблема заключается в том, что с помощью вашего метода вы в основном разделяете ввод в кусках фиксированного размера. Тем не менее, последний кусок может иметь разный размер, и поэтому вам нужно учитывать это. Я столкнулся с этой проблемой при использовании ключа 5, буква "i" находится в 19-м индексе вместо 20-го, потому что последний кусок имеет длину всего 3 символа (DEF), поэтому на 4-м проходе дешифр все еще читает 20-й (3).

Мне удалось решить проблему, добавив трейлинг символов (я выбрал =, но вы можете выбрать другой) перед тем, как зашифровать, а затем удалить завершающие символы после дешифрования. Фраза всегда имеет размер, кратный ключу до шифрования.

Здесь код:

private static final char TRAILING_CHAR = '=';     

public static void main(String[] args) {
            test("Testing1234567890ABCDEF");
            test("Testing1234567890ABCDEFG");
       }

    public static String encrypt(String phrase, int key) {
        StringBuilder password = new StringBuilder(phrase.length());
        phrase = trail(phrase, key); //add trailing
        for(int j = 0; j < key; j++) {
            for(int i = j; i < phrase.length(); i+=key) {
                password.append(phrase.charAt(i));
            }
        }
        return password.toString();
    }

    public static String decrypt(String phrase, int key) {
        StringBuilder password = new StringBuilder(phrase.length());
        int chunkSize = (int) Math.ceil(phrase.length()/key); //size of chunks
        for(int j = 0; j < chunkSize; j++) {
            for(int i = j; i < phrase.length(); i+=chunkSize) {
                password.append(phrase.charAt(i));
            }
        }  
        //remove trailing
        return password.toString().replaceAll(String.valueOf(TRAILING_CHAR), "");
    }

    public static void test(String s) {
        for(int key = 1; key < 10; key++) {
            String trailed = trail(s, key);
            String encrypted = encrypt(s, key);
            String decrypted = decrypt(encrypted, key);
            System.out.println(s + " -> "+trailed+" -> " + encrypted + " -> " + decrypted + "(" + key + ")");
        }
    }

    private static String trail(String s, int key) {
        int trailingSize = s.length() % key;
        for(int i = trailingSize;i != 0 && i < key; i++) {
            s += TRAILING_CHAR; //add trailing
        }
        return s;
    }

Я использовал процедуру тестирования из @OldCurmudgeon, и он дает мне следующий результат:

Testing1234567890ABCDEF -> Testing1234567890ABCDEF -> Testing1234567890ABCDEF -> Testing1234567890ABCDEF(1)
Testing1234567890ABCDEF -> Testing1234567890ABCDEF= -> Tsig24680BDFetn13579ACE= -> Testing1234567890ABCDEF(2)
Testing1234567890ABCDEF -> Testing1234567890ABCDEF= -> Ttg369BEei1470CFsn258AD= -> Testing1234567890ABCDEF(3)
Testing1234567890ABCDEF -> Testing1234567890ABCDEF= -> Ti260Den37AEsg48BFt159C= -> Testing1234567890ABCDEF(4)
Testing1234567890ABCDEF -> Testing1234567890ABCDEF== -> Tn49Deg50Es16AFt27B=i38C= -> Testing1234567890ABCDEF(5)
Testing1234567890ABCDEF -> Testing1234567890ABCDEF= -> Tg6Be17Cs28Dt39Ei40Fn5A= -> Testing1234567890ABCDEF(6)
Testing1234567890ABCDEF -> Testing1234567890ABCDEF===== -> T18Ee29Fs30=t4A=i5B=n6C=g7D= -> Testing1234567890ABCDEF(7)
Testing1234567890ABCDEF -> Testing1234567890ABCDEF= -> T20e3As4Bt5Ci6Dn7Eg8F19= -> Testing1234567890ABCDEF(8)
Testing1234567890ABCDEF -> Testing1234567890ABCDEF==== -> T3Be4Cs5Dt6Ei7Fn8=g9=10=2A= -> Testing1234567890ABCDEF(9)
Testing1234567890ABCDEFG -> Testing1234567890ABCDEFG -> Testing1234567890ABCDEFG -> Testing1234567890ABCDEFG(1)
Testing1234567890ABCDEFG -> Testing1234567890ABCDEFG -> Tsig24680BDFetn13579ACEG -> Testing1234567890ABCDEFG(2)
Testing1234567890ABCDEFG -> Testing1234567890ABCDEFG -> Ttg369BEei1470CFsn258ADG -> Testing1234567890ABCDEFG(3)
Testing1234567890ABCDEFG -> Testing1234567890ABCDEFG -> Ti260Den37AEsg48BFt159CG -> Testing1234567890ABCDEFG(4)
Testing1234567890ABCDEFG -> Testing1234567890ABCDEFG= -> Tn49Deg50Es16AFt27BGi38C= -> Testing1234567890ABCDEFG(5)
Testing1234567890ABCDEFG -> Testing1234567890ABCDEFG -> Tg6Be17Cs28Dt39Ei40Fn5AG -> Testing1234567890ABCDEFG(6)
Testing1234567890ABCDEFG -> Testing1234567890ABCDEFG==== -> T18Ee29Fs30Gt4A=i5B=n6C=g7D= -> Testing1234567890ABCDEFG(7)
Testing1234567890ABCDEFG -> Testing1234567890ABCDEFG -> T20e3As4Bt5Ci6Dn7Eg8F19G -> Testing1234567890ABCDEFG(8)
Testing1234567890ABCDEFG -> Testing1234567890ABCDEFG=== -> T3Be4Cs5Dt6Ei7Fn8Gg9=10=2A= -> Testing1234567890ABCDEFG(9)

Надеюсь, это решит вашу проблему.

0

i += Math.ceil((phrase.length()/key))+1 заключается в том, что обновление i += Math.ceil((phrase.length()/key))+1 в вашей функции расшифровки не должно быть постоянным

for (int j = 0; j<=Math.ceil(phrase.length()/key); j++){
    for (int i = j; i < phrase.length(); i += Math.ceil((phrase.length()/key))+1)
    {
        password += phrase.charAt(i);
    }
}

Чтобы проиллюстрировать, скажем, key=4, введите фразу = "123456789".

После шифрования пароль становится: "159263748", "индекс" - 048152637,

что означает, что 0th позиция encypted string взята из 0th позиции фразы,

1th позиция encypted string берется из 4th положения фразы и т.д.

После дешифрования расшифрованная строка становится: "123456789", "индекс" - 036714682

что означает, что 0th позиция дешифрованной строки берется из 0th позиции зашифрованной строки,

1th позиция деципированной строки берется из 3th позиции зашифрованной строки и т.д.

Поэтому ваша программа должна прочитать зашифрованную строку в последовательности 0->3->5->7->1->4->6->8->2

обратите внимание, что 0->3 занял инкремент 3, а 3->5 занял 2,

ваша программа должна решить эту ситуацию.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню