我必须编写一个程序,使用字母位移来加密用户输入的字符串。加密代码如下:
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);
}
}
这适用于此密钥,但如果我使用不同的短语或不同的密钥则不起作用。
我错过了什么?
答案 0 :(得分: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
然而,仅仅因为它们是相对素数并不意味着加密/解密将起作用。
仍然看着它。
答案 1 :(得分:0)
问题是解密函数中的更新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
位置取自短语的0th
位置,
1th
位置取自短语的4th
位置,依此类推。
解密后,解密后的字符串变为:
"123456789"
,“索引”为036714682
表示解密字符串的0th
位置取自加密字符串的0th
位置,
1th
位置取自加密字符串的3th
位置,依此类推。
因此,您的程序应按0->3->5->7->1->4->6->8->2
请注意0->3
增加3,而3->5
增加2,
你的程序应该解决这种情况。
答案 2 :(得分:0)
主要问题是,使用您的方法,您基本上将输入拆分为固定大小的块。但是,最后一个块可能具有不同的大小,因此您需要考虑到这一点。我在使用键5,字母&#34; i&#34;时遇到了这个问题。位于第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)
希望这可以解决您的问题。