一、实习目的
- 熟悉java平台开发环境;
- 理解常见古典加密算法:凯撒密码、多字母替代密码、多表替代密码;
- 理解古典加密技术中的替换技术、置换技术。
二、实习要求
- 实习前认真预习第1、2章相关内容;
- 对实习内容中给定题目上机前先进行程序编写和数据准备;
- 上机编辑、调试、运行程序,并保存最终程序,然后撰写实习报告;
- 实习报告需用专门的报告纸书写,内容包括:实习名称、实习目的、内容、操作过程、程序清单,运行结果,实习中出现的问题及解决方法、实习体会等,具体要求见附录1。
三、实习内容
1.[问题描述]
凯撒密码是把字母表中的每个字母用该字母后的某个字母进行代替。
凯撒密码的通用加密算法是:C=E(P)=(P+k) mod 26 0<k<26
凯撒密码的通用解密算法是:P=D(C)=(P-k) mod 26 0<k<26
2.[阶梯任务]:实习任务按照难度渐次给出,阶梯(1)为必须完成的基础任务,请结合自己的实际选择后续阶梯任务
(1)利用课本表2-1实现凯撒密码的加密、解密算法,能够根据用户选择秘钥(移位数)和明文进行加解密,用户密钥在整数范围内;
(2)对于恺撒加密实现图形界面,用户可以输入明文和密钥,在文本框中显示对应密文;
(3)实现用户对文件的操作,用户可以通过指定路径文件和密钥,加密结果存储在指定文件中;
(4)将恺撒密码扩展到任意起始位置、字符集、密钥长度,加、解密算法;
(5)学习一种中文编码方式,实现字符集加密和解密。(本项选做)。
3.[实现提示]
(1) 用户可以通过命令实现密钥和明文的选择;
(2) 由于字母表中共有26个字符,因此,移位前应先将移动的位数(key)和26取模。Java平台中可以实现字符和整数的自动转换,因此将字符加上一个正整数代表在字母表中右移位数。如果移动的位数为负值,则代表在字母中左移位数。
(3) 尽管移位前已经将移动的位数和26取模,但是通过这种方式实现的右移和左移仍可能发生超界。因此,移位后仍要判断是否超界。
四、实验设计
1、基本思路
(1)设计加密解密算法
根据通用的加密解密算法(凯撒密码的通用加密算法是:C=E(P)=(P+k) mod 26 0<k<26)来实现加密、解密,能够根据用户选择密钥(移位数)和明文进行加解密,用户密钥在整数范围内。首先,先定义一个Caesar类,有两种选择:选择加密后,就要输入要加密的字符串,并输入密钥(移位数),根据加密算法函数进行文字加密,并将加密后的结果输出。选择解密后,就要输入要解密的字符串,并输入密钥(移位数),根据解密算法函数进行文字解密,并将解密后的结果输出。这两个函数刚好相反,所有加解密字符都在a~z以及A~Z之间,若不在其中,就属于超界,需要将其转换到范围值中。
(2)设计加密解密的操作界面
该界面类Caesarframe包括了密文,密钥,密文三个输入的文本框部分,还有加密、解密的两个按钮,对按钮都添加了事件监听器,通过获取输入的字符串,密钥起始位,声明Caesar类的对象,调用加密、解密两个方法实现对输入的字符串加密,解密。
若想要加密,输入要加密的字符串以及密钥,点击“加密”按钮,加密后的密文就显示在密文文本框中。相反,若要解密,输入要解密的字符串以及密钥,点击“解密”按钮,解密后的明文就显示在明文文本框中。
(3)实现用户对文件的操作
在项目文件夹中创建miwen.txt和mingwen.txt两个文件,然后再mingwen.txt中输入明文内容并将其保存。然后依次读取文件内容并根据输入的密钥将文件中的内容加密后保存到miwen.txt中。
2、类图设计
|
| |
图4-1 类图
3、核心方法流程图设计
|
|
图4-2 核心方法流程图
五、实验结果测试
1.设计加密解密算法
加密:输入明文“I love you”,密钥为3,加密后结果如图5-1所示

图5-1
解密:输入密文“I miss you”,密钥为4,解密后结果如图5-2所示

图5-2
2.设计加密解密的操作界面
加密:输入明文“I love you”,密钥为3,点击“加密”按钮后结果如图5-3所示

图5-3
解密:输入密文“I miss you”,密钥为4,点击“解密”按钮后结果如图5-4所示

图5-4
3.实现用户对文件的操作
在work1项目下创建mingwen.txt和miwen.txt两个文件,如图5-5所示。
![]() |
图5-5
在mingwen.txt中输入以下内容,如图5-6所示。
图5-6
在控制台输入input文件,output文件以及密钥,如图5-7所示。
图5-7
在miwen.txt中显示如下内容,如图5-8所示。
图5-8
代码:
package work1;
import java.util.Scanner;
public class Caesar {
@SuppressWarnings("resource")
public static void main(String[] args) {
System.out.println("[1 加密][2 解密],请选择一个");
Scanner c=new Scanner(System.in); // 创建Scanner对象
String s1=c.nextLine(); //获取本行的字符串
if(s1.equalsIgnoreCase("1")) { //判断变量s1与A是否相等,忽略大小
System.out.println("请输入明文:");
Scanner sc=new Scanner(System.in);
String s=sc.nextLine();
System.out.println("请输入密钥:");
Scanner sc1=new Scanner(System.in);
int key=sc1.nextInt(); //将下一输入项转换成int类型
JiaMi(s,key); //调用加密方法
}
else if(s1.equalsIgnoreCase("2")) {
System.out.println("请输入密文:");
Scanner sc=new Scanner(System.in);
String s=sc.nextLine();
System.out.println("请输入密钥:");
Scanner sc1=new Scanner(System.in);
int key=sc1.nextInt();
JieMi(s,key); //调用解密方法
}
}
public static void JiaMi(String str, int k) {
String string="";
for(int i=0;i<str.length();i++) {
char c=str.charAt(i);
if(c>='a'&&c<='z')//如果字符串中的某个字符是小写字母
{
c+=k%26;//移动key%26位
if(c<'a')
c+=26;//向左超界
if(c>'z')
c-=26;//向右超界
}else if(c>='A'&&c<='Z')//如果字符串中的某个字符是大写字母
{
c+=k%26;//移动key%26位
if(c<'A')
c+=26;//向左超界
if(c>'Z')
c-=26;//向右超界
}
string +=c;//将解密后的字符连成字符串
}
System.out.println(str+"加密后为:"+string);
}
public static void JieMi(String str, int n) {
int k=Integer.parseInt("-"+n);
String string="";
for(int i=0;i<str.length();i++) {
char c=str.charAt(i);
if(c>='a'&&c<='z')//如果字符串中的某个字符是小写字母
{
c+=k%26;//移动key%26位
if(c<'a')
c+=26;//向左超界
if(c>'z')
c-=26;//向右超界
}else if(c>='A'&&c<='Z')//如果字符串中的某个字符是大写字母
{
c+=k%26;//移动key%26位
if(c<'A')
c+=26;//向左超界
if(c>'Z')
c-=26;//向右超界
}
string +=c;//将解密后的字符连成字符串
}
System.out.println(str+"解密后为:"+string);
}
}
package work1;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Encryptor {
private int key;
public Encryptor(int aKey) {
key = aKey;
}
public void encryptFile(String inFile, String outFile) throws IOException {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(inFile);
out = new FileOutputStream(outFile);
encrypStream(in,out);
}
finally {
if(in != null ) in.close();
if(out != null ) out.close();
}
}
public void encrypStream(InputStream in, OutputStream out) throws IOException {
boolean done = false;
while (!done) {
int next = in.read();
if (next == -1) done = true;
else {
byte b = (byte) next;
byte c = encrypt(b);
out.write(c);
}
}
}
public byte encrypt(byte b) {
return (byte) (b + key);
}
}
package work1;
import java.io.IOException;
import java.util.Scanner;
public class EncryptorTester {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
try {
System.out.print("Input file: ");
String inFile = in.next();
System.out.print("Output file: ");
String outFile = in.next();
System.out.print("Encryption key: ");
int key = in.nextInt();
Encryptor crypt = new Encryptor(key);
crypt.encryptFile(inFile, outFile);
} catch (IOException e) {
System.out.println("Error processing file : " + e);
}
}
}
package work1;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import java.awt.Font;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.util.Scanner;
import java.awt.event.ActionEvent;
public class CaesarFrame extends JFrame {
private JPanel contentPane;
private JTextField mingwenJTF;
private JTextField keyJTF;
private JTextField miwenJTF;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
CaesarFrame frame = new CaesarFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public CaesarFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
JLabel nameJL = new JLabel("\u607A\u6492\u5BC6\u7801");
nameJL.setFont(new Font("宋体", Font.BOLD, 22));
JLabel mingwenJL = new JLabel("\u660E \u6587\uFF1A");
mingwenJL.setFont(new Font("宋体", Font.PLAIN, 18));
mingwenJTF = new JTextField();
mingwenJTF.setColumns(10);
JLabel keyJL = new JLabel("\u5BC6 \u94A5\uFF1A");
keyJL.setFont(new Font("宋体", Font.PLAIN, 18));
keyJTF = new JTextField();
keyJTF.setColumns(10);
miwenJTF = new JTextField();
miwenJTF.setColumns(10);
JLabel miwenJL = new JLabel("\u5BC6 \u6587\uFF1A");
miwenJL.setFont(new Font("宋体", Font.PLAIN, 18));
JButton jiamiJL = new JButton("\u52A0\u5BC6");
jiamiJL.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String mingwen=mingwenJTF.getText();
String key1=keyJTF.getText();
String string="";
int key = Integer.parseInt(key1);
for(int i=0;i<mingwen.length();i++) {
char c=mingwen.charAt(i);
if(c>='a'&&c<='z')//如果字符串中的某个字符是小写字母
{
c+=key%26;//移动key%26位
if(c<'a')
c+=26;//向左超界
if(c>'z')
c-=26;//向右超界
}
else if(c>='A'&&c<='Z')//如果字符串中的某个字符是大写字母
{
c+=key%26;//移动key%26位
if(c<'A')
c+=26;//向左超界
if(c>'Z')
c-=26;//向右超界
}
string+=c;//将解密后的字符连成字符串
miwenJTF.setText(string);
}
}
});
jiamiJL.setFont(new Font("宋体", Font.PLAIN, 18));
JButton jiemiJB = new JButton("\u89E3\u5BC6");
jiemiJB.addActionListener(new ActionListener() {
//解密
public void actionPerformed(ActionEvent e) {
String miwen=miwenJTF.getText();
String key1=keyJTF.getText();
int key=Integer.parseInt("-"+key1);
String string="";
for(int i=0;i<miwen.length();i++) {
char c=miwen.charAt(i);
if(c>='a'&&c<='z')//如果字符串中的某个字符是小写字母
{
c+=key%26;//移动key%26位
if(c<'a')
c+=26;//向左超界
if(c>'z')
c-=26;//向右超界
}else if(c>='A'&&c<='Z')//如果字符串中的某个字符是大写字母
{
c+=key%26;//移动key%26位
if(c<'A')
c+=26;//向左超界
if(c>'Z')
c-=26;//向右超界
}
string +=c;//将解密后的字符连成字符串
mingwenJTF.setText(string);
}
}
});
jiemiJB.setFont(new Font("宋体", Font.PLAIN, 18));
GroupLayout gl_contentPane = new GroupLayout(contentPane);
gl_contentPane.setHorizontalGroup(
gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addGap(64)
.addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING)
.addComponent(mingwenJL)
.addComponent(keyJL)
.addComponent(miwenJL))
.addComponent(jiamiJL))
.addGap(18)
.addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING)
.addComponent(nameJL)
.addGroup(gl_contentPane.createSequentialGroup()
.addGap(10)
.addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING, false)
.addComponent(keyJTF, GroupLayout.DEFAULT_SIZE, 150, Short.MAX_VALUE)
.addComponent(miwenJTF)
.addComponent(mingwenJTF, GroupLayout.PREFERRED_SIZE, 180, GroupLayout.PREFERRED_SIZE)
.addComponent(jiemiJB, Alignment.TRAILING))))
.addContainerGap(78, Short.MAX_VALUE))
);
gl_contentPane.setVerticalGroup(
gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addGap(22)
.addComponent(nameJL)
.addPreferredGap(ComponentPlacement.UNRELATED)
.addGroup(gl_contentPane.createParallelGroup(Alignment.BASELINE)
.addComponent(mingwenJL)
.addComponent(mingwenJTF, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addGap(18)
.addGroup(gl_contentPane.createParallelGroup(Alignment.BASELINE)
.addComponent(keyJL)
.addComponent(keyJTF, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addGap(29)
.addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addComponent(miwenJL)
.addPreferredGap(ComponentPlacement.RELATED, 20, Short.MAX_VALUE)
.addGroup(gl_contentPane.createParallelGroup(Alignment.BASELINE)
.addComponent(jiemiJB)
.addComponent(jiamiJL)))
.addComponent(miwenJTF, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
contentPane.setLayout(gl_contentPane);
}
}
本文介绍了使用Java实现凯撒密码的加密和解密算法,包括基本的加密解密思路、操作界面设计以及文件操作。实习任务从基础的命令行操作到图形界面交互,再到文件加密,逐步提升难度。此外,还提供了代码示例,展示了如何在Java平台上实现这一系列功能。








