Java,如何实现移位密码(凯撒密码)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19108737/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 14:10:20  来源:igfitidea点击:

Java, How to implement a Shift Cipher (Caesar Cipher)

javaencryption

提问by Sophia Ali

I want to implement a Caesar Cipher shift to increase each letter in a string by 3.

我想实现一个凯撒密码转换,将字符串中的每个字母增加 3。

I am receiving this error:

我收到此错误:

possible loss of precision required char; found int

Here is my code so far:

到目前为止,这是我的代码:

import java.util.Scanner;
import java.io.*;

public class CaesarCipher
{
    public static void main (String [] args) {

        char[] letters = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 
            'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 
            'w', 'x', 'y', 'z'};

        char[] message = "onceuponatime".toCharArray();
        char[] eMessage = new char[message.length];
        char shift = 3;

        //encrypting message
        for(int i = 0; i <= message.length; ++i)
        {
            eMessage[i] = (message[i] + shift) % (char) letters.length;
            System.out.println(x);               
        }              
    }
}

What causes this error? How can I implement a caesar Cipher shift to increase each letter in a string by 3?

是什么导致了这个错误?如何实现凯撒密码转换以将字符串中的每个字母增加 3?

回答by azz

The warning is due to you attempting to add an integer (int shift = 3) to a character value. You can change the data type to charif you want to avoid that.

警告是由于您试图将整数 ( int shift = 3)添加到字符值。char如果您想避免这种情况,您可以将数据类型更改为。

A charis 16 bits, an intis 32.

Achar是 16 位,anint是 32。

char shift = 3;
// ...
eMessage[i] = (message[i] + shift) % (char)letters.length;

As an aside, you can simplify the following:

顺便说一句,您可以简化以下内容:

char[] message = {'o', 'n', 'c', 'e', 'u', 'p', 'o', 'n', 'a', 't', 'i', 'm', 'e'}; 

To:

到:

char[] message = "onceuponatime".toCharArray();

回答by Ayan

Two ways to implement a Caesar Cipher:

实现凯撒密码的两种方法:

Option 1: Change chars to ASCII numbers, then you can increase the value, then revert it back to the new character.

选项 1:将字符更改为 ASCII 数字,然后您可以增加值,然后将其恢复为新字符。

Option 2: Use a Map map each letter to a digit like this.

选项 2:使用地图将每个字母映射到这样的数字。

A - 0
B - 1
C - 2
etc...

With a map you don't have to re-calculate the shift every time. Then you can change to and from plaintext to encrypted by following map.

使用地图,您不必每次都重新计算班次。然后您可以通过以下地图在明文和加密之间进行更改。

回答by Sorpresa

Hello...I have created a java client server application in swing for caesar cipher...I have created a new formula that can decrypt the text properly... sorry only for lower case..!

你好...我已经为凯撒密码在swing中创建了一个java客户端服务器应用程序...我已经创建了一个可以正确解密文本的新公式...抱歉只适用于小写...!

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.*;

public class ceasarserver extends JFrame implements ActionListener {
    static String cs = "abcdefghijklmnopqrstuvwxyz";
    static JLabel l1, l2, l3, l5, l6;
    JTextField t1;
    JButton close, b1;
    static String en;
    int num = 0;
    JProgressBar progress;

    ceasarserver() {
        super("SERVER");
        JPanel p = new JPanel(new GridLayout(10, 1));
        l1 = new JLabel("");
        l2 = new JLabel("");
        l3 = new JLabel("");
        l5 = new JLabel("");
        l6 = new JLabel("Enter the Key...");
        t1 = new JTextField(30);
        progress = new JProgressBar(0, 20);
        progress.setValue(0);
        progress.setStringPainted(true);
        close = new JButton("Close");
        close.setMnemonic('C');
        close.setPreferredSize(new Dimension(300, 25));
        close.addActionListener(this);
        b1 = new JButton("Decrypt");
        b1.setMnemonic('D');
        b1.addActionListener(this);
        p.add(l1);
        p.add(l2);
        p.add(l3);
        p.add(l6);
        p.add(t1);
        p.add(b1);
        p.add(progress);
        p.add(l5);
        p.add(close);
        add(p);
        setVisible(true);
        pack();
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == close)
            System.exit(0);
        else if (e.getSource() == b1) {
            int key = Integer.parseInt(t1.getText());
            String d = "";
            int i = 0, j, k;
            while (i < en.length()) {
                j = cs.indexOf(en.charAt(i));
                k = (j + (26 - key)) % 26;
                d = d + cs.charAt(k);
                i++;
            }
            while (num < 21) {
                progress.setValue(num);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException ex) {
                }
                progress.setValue(num);
                Rectangle progressRect = progress.getBounds();
                progressRect.x = 0;
                progressRect.y = 0;
                progress.paintImmediately(progressRect);
                num++;
            }
            l5.setText("Decrypted text: " + d);
        }
    }

    public static void main(String args[]) throws IOException {
        new ceasarserver();
        String strm = new String();
        ServerSocket ss = new ServerSocket(4321);
        l1.setText("Secure data transfer Server Started....");
        Socket s = ss.accept();
        l2.setText("Client Connected !");
        while (true) {
            Scanner br1 = new Scanner(s.getInputStream());
            en = br1.nextLine();
            l3.setText("Client:" + en);
        }
    }

The client class:

客户端类:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.*;

public class ceasarclient extends JFrame {
    String cs = "abcdefghijklmnopqrstuvwxyz";
    static JLabel l1, l2, l3, l4, l5;
    JButton b1, b2, b3;
    JTextField t1, t2;
    JProgressBar progress;
    int num = 0;
    String en = "";

    ceasarclient(final Socket s) {
        super("CLIENT");
        JPanel p = new JPanel(new GridLayout(10, 1));
        setSize(500, 500);
        t1 = new JTextField(30);
        b1 = new JButton("Send");
        b1.setMnemonic('S');
        b2 = new JButton("Close");
        b2.setMnemonic('C');
        l1 = new JLabel("Welcome to Secure Data transfer!");
        l2 = new JLabel("Enter the word here...");
        l3 = new JLabel("");
        l4 = new JLabel("Enter the Key:");
        b3 = new JButton("Encrypt");
        b3.setMnemonic('E');
        t2 = new JTextField(30);
        progress = new JProgressBar(0, 20);
        progress.setValue(0);
        progress.setStringPainted(true);
        p.add(l1);
        p.add(l2);
        p.add(t1);
        p.add(l4);
        p.add(t2);
        p.add(b3);
        p.add(progress);
        p.add(b1);
        p.add(l3);
        p.add(b2);
        add(p);
        setVisible(true);
        b1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
                    pw.println(en);
                } catch (Exception ex) {
                }
                ;
                l3.setText("Encrypted Text Sent.");
            }
        });
        b3.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String strw = t1.getText();
                int key = Integer.parseInt(t2.getText());
                int i = 0, j, k;
                while (i < strw.length()) {
                    j = cs.indexOf(strw.charAt(i));
                    k = (j + key) % 26;
                    en = en + cs.charAt(k);
                    i++;
                }
                while (num < 21) {
                    progress.setValue(num);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException exe) {
                    }
                    progress.setValue(num);
                    Rectangle progressRect = progress.getBounds();
                    progressRect.x = 0;
                    progressRect.y = 0;
                    progress.paintImmediately(progressRect);
                    num++;
                }
            }
        });
        b2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        pack();
    }

    public static void main(String args[]) throws IOException {
        final Socket s = new Socket(InetAddress.getLocalHost(), 4321);
        new ceasarclient(s);
    }
}

回答by Eric Leschinski

Java Shift Caesar Cipher by shiftspaces.

Java Shift Caesar Cipher 按shift空格。

Restrictions:

限制:

  1. Only works with a positive number in the shift parameter.
  2. Only works with shift less than 26.
  3. Does a += which will bog the computer down for bodies of text longer than a few thousand characters.
  4. Does a cast number to character, so it will fail with anything but ascii letters.
  5. Only tolerates letters a through z. Cannot handle spaces, numbers, symbols or unicode.
  6. Code violates the DRY (don't repeat yourself) principle by repeating the calculation more than it has to.
  1. 仅适用于 shift 参数中的正数。
  2. 仅适用于小于 26 的班次。
  3. 是否使用 += 会使计算机陷入超过几千个字符的文本正文。
  4. 将数字转换为字符,因此除了 ascii 字母之外的任何内容都会失败。
  5. 只允许字母 a 到 z。无法处理空格、数字、符号或 unicode。
  6. 代码违反了 DRY(不要重复自己)原则,重复计算的次数超过了它必须的次数。

Pseudocode:

伪代码:

  1. Loop through each character in the string.
  2. Add shift to the character and if it falls off the end of the alphabet then subtract shift from the number of letters in the alphabet (26)
  3. If the shift does not make the character fall off the end of the alphabet, then add the shift to the character.
  4. Append the character onto a new string. Return the string.
  1. 循环遍历字符串中的每个字符。
  2. 向字符添加移位,如果它从字母表的末尾脱落,则从字母表中的字母数中减去移位 (26)
  3. 如果移位没有使字符从字母表的末尾脱落,则向字符添加移位。
  4. 将字符附加到新字符串上。返回字符串。

Function:

功能:

String cipher(String msg, int shift){
    String s = "";
    int len = msg.length();
    for(int x = 0; x < len; x++){
        char c = (char)(msg.charAt(x) + shift);
        if (c > 'z')
            s += (char)(msg.charAt(x) - (26-shift));
        else
            s += (char)(msg.charAt(x) + shift);
    }
    return s;
}

How to invoke it:

如何调用它:

System.out.println(cipher("abc", 3));  //prints def
System.out.println(cipher("xyz", 3));  //prints abc

回答by nanosoft

Below code handles upper and lower cases as well and leaves other character as it is.

下面的代码也处理大写和小写,并保持其他字符不变。

import java.util.Scanner;

public class CaesarCipher
{
    public static void main(String[] args)
    {
    Scanner in = new Scanner(System.in);
    int length = Integer.parseInt(in.nextLine());
    String str = in.nextLine();
    int k = Integer.parseInt(in.nextLine());

    k = k % 26;

    System.out.println(encrypt(str, length, k));

    in.close();
    }

    private static String encrypt(String str, int length, int shift)
    {
    StringBuilder strBuilder = new StringBuilder();
    char c;
    for (int i = 0; i < length; i++)
    {
        c = str.charAt(i);
        // if c is letter ONLY then shift them, else directly add it
        if (Character.isLetter(c))
        {
        c = (char) (str.charAt(i) + shift);
        // System.out.println(c);

        // checking case or range check is important, just if (c > 'z'
        // || c > 'Z')
        // will not work
        if ((Character.isLowerCase(str.charAt(i)) && c > 'z')
            || (Character.isUpperCase(str.charAt(i)) && c > 'Z'))

            c = (char) (str.charAt(i) - (26 - shift));
        }
        strBuilder.append(c);
    }
    return strBuilder.toString();
    }
}