JAVA加密解密之凯撒加密(Caesar cipher)算法

x33g5p2x  于2021-12-25 转载在 其他  
字(2.9k)|赞(0)|评价(0)|浏览(363)

凯撒加密算法简介

凯撒加密(Caesar cipher)是一种简单的消息编码方式:它根据字母表将消息中的每个字母移动常量位k。举个例子如果k等于3,则在编码后的消息中,每个字母都会向前移动3位:a会被替换为d;b会被替换成e;依此类推。字母表末尾将回卷到字母表开头。于是,w会被替换为z,x会被替换为a。

凯撒加密算法实现

package com.jianggujin.codec;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/** * 凯撒加密 * * @author jianggujin * */
public class JCaesar {

   /** * 加密 * * @param str * @param k * @return */
   public static String encrypt(String str, int k) {
      StringBuilder result = new StringBuilder();
      for (char c : str.toCharArray()) {
         result.append(encrypt(c, k));
      }
      return result.toString();
   }

   /** * 解密 * * @param str * @param k * @return */
   public static String decrypt(String str, int k) {
      // 取相反数
      k = 0 - k;
      return encrypt(str, k);
   }

   /** * 包裹输入流,原输入流为加密数据输入流 * * @param in * @param k * @return */
   public static InputStream wrap(InputStream in, int k) {
      return new DecInputStream(in, k);
   }

   /** * 包裹输出流,包裹后的输出流为加密输出流 * * @param out * @param k * @return */
   public static OutputStream wrap(OutputStream out, int k) {
      return new EncOutputStream(out, k);
   }

   /** * 加密输出流 * * @author jianggujin * */
   private static class EncOutputStream extends OutputStream {
      private final OutputStream out;
      private final int k;

      EncOutputStream(OutputStream out, int k) {
         this.out = out;
         this.k = k;
      }

      @Override
      public void write(int b) throws IOException {
         out.write(encrypt((char) b, k));
      }
   }

   /** * 解密输入流 * * @author jianggujin * */
   private static class DecInputStream extends InputStream {

      private final InputStream in;
      private final int k;

      DecInputStream(InputStream in, int k) {
         this.in = in;
         this.k = 0 - k;
      }

      @Override
      public int read() throws IOException {
         int i = in.read();
         if (i == -1) {
            return i;
         }
         return encrypt((char) i, k);
      }

   }

   /** * 加密 * * @param c * @param k * @return */
   private static char encrypt(char c, int k) {
      // 如果字符串中的某个字符是小写字母
      if (c >= 'a' && c <= 'z') {
         c += k % 26; // 移动key%26位
         if (c < 'a') {
            c += 26; // 向左超界
         } else if (c > 'z') {
            c -= 26; // 向右超界
         }
      }
      // 如果字符串中的某个字符是大写字母
      else if (c >= 'A' && c <= 'Z') {
         c += k % 26; // 移动key%26位
         if (c < 'A') {
            c += 26;// 同上
         } else if (c > 'Z') {
            c -= 26;// 同上
         }
      }
      return c;
   }
}

测试代码:

package com.jianggujin.codec.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.junit.Test;

import com.jianggujin.codec.JCaesar;

public class CaesarTest {
   String str = "jianggujin";
   File file = new File(getClass().getSimpleName() + ".dat");
   int k = 10;

   @Test
   public void test() throws IOException {
      System.out.println("原串:" + str + ", 偏移:" + k);
      String encrypt = JCaesar.encrypt(str, k);
      System.out.println("加密:" + encrypt);
      System.out.println("解密:" + JCaesar.decrypt(encrypt, k));
      System.out.print("输出流加密:" + file.getAbsolutePath());
      OutputStream out = JCaesar.wrap(new FileOutputStream(file), k);
      out.write(str.getBytes());
      out.flush();
      System.out.println();
      System.out.print("输入流解密:");
      InputStream in = JCaesar.wrap(new FileInputStream(file), k);
      byte[] buffer = new byte[1024];
      int len = in.read(buffer);
      System.out.println(new String(buffer, 0, len));
   }
}

测试结果:
原串:jianggujin, 偏移:10
加密:tskxqqetsx
解密:jianggujin
输出流加密:F:\workspace\java\eclipse\JCodec\CaesarTest.dat
输入流解密:jianggujin

相关文章