JAVA加密解密之RSA算法

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

RSA算法简介

RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战。RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

  1. 甲方构建密钥对儿,将公钥公布给乙方,将私钥保留。
  2. 甲方使用私钥加密数据,然后用私钥对加密后的数据签名,发送给乙方签名以及加密后的数据;乙方使用公钥、签名来验证待解密数据是否有效。
  3. 如果有效使用公钥对数据解密。 乙方使用公钥加密数据,向甲方发送经过加密后的数据;甲方获得加密数据,通过私钥解密。

RSA算法实现

package com.jianggujin.codec;

import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import com.jianggujin.codec.util.JCipherInputStream;
import com.jianggujin.codec.util.JCipherOutputStream;
import com.jianggujin.codec.util.JCodecException;

/** * RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard * Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。 * RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。 * 今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长, * 用RSA加密的信息实际上是不能被解破的。但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战。 * RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。 * * 1、甲方构建密钥对儿,将公钥公布给乙方,将私钥保留。 * 2、甲方使用私钥加密数据,然后用私钥对加密后的数据签名,发送给乙方签名以及加密后的数据;乙方使用公钥、签名来验证待解密数据是否有效, * 3、如果有效使用公钥对数据解密。 乙方使用公钥加密数据,向甲方发送经过加密后的数据;甲方获得加密数据,通过私钥解密。 * * @author jianggujin * */
public class JRSA {

   private static final String ALGORITHM = "RSA";

   /** * RSA签名算法 * * @author jianggujin * */
   public static enum JRSASignatureAlgorithm {

      MD2withRSA, MD5withRSA, SHA1withRSA, SHA224withRSA, SHA256withRSA, SHA384withRSA, SHA512withRSA;

      public String getName() {
         return this.name();
      }
   }

   /** * 初始化密钥 * * @return */
   public static KeyPair initKey() {
      return initKey(1024);
   }

   /** * 初始化密钥 * * @param keySize * @return */
   public static KeyPair initKey(int keySize) {
      try {
         KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);
         keyPairGen.initialize(keySize);
         return keyPairGen.generateKeyPair();
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }

   /** * 签名 * * @param data * @param privateKey * @param signatureAlgorithm * @return */
   public static byte[] sign(byte[] data, byte[] privateKey, String signatureAlgorithm) {
      try {
         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);

         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);

         PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);

         Signature signature = Signature.getInstance(signatureAlgorithm);
         signature.initSign(priKey);
         signature.update(data);
         return signature.sign();
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }

   /** * 验签 * * @param data * @param publicKey * @param sign * @param signatureAlgorithm * @return */
   public static boolean verify(byte[] data, byte[] publicKey, byte[] sign, String signatureAlgorithm) {
      try {
         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);

         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);

         PublicKey pubKey = keyFactory.generatePublic(keySpec);

         Signature signature = Signature.getInstance(signatureAlgorithm);
         signature.initVerify(pubKey);
         signature.update(data);

         return signature.verify(sign);
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }

   /** * 公钥加密 * * @param data * @param publicKey * @return */
   public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) {
      Cipher cipher = getEncryptCipherByPublicKey(publicKey);
      try {
         return cipher.doFinal(data);
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }

   /** * 私钥加密 * * @param data * @param privateKey * @return */
   public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) {
      Cipher cipher = getEncryptCipherByPrivateKey(privateKey);
      try {
         return cipher.doFinal(data);
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }

   /** * 包裹输出流,包裹后的输出流为公钥加密输出流 * * @param out * @param publicKey * @return */
   public static OutputStream wrapByPublicKey(OutputStream out, byte[] publicKey) {
      Cipher cipher = getEncryptCipherByPublicKey(publicKey);
      return new JCipherOutputStream(cipher, out);
   }

   /** * 包裹输出流,包裹后的输出流为私钥加密输出流 * * @param out * @param privateKey * @return */
   public static OutputStream wrapByPrivateKey(OutputStream out, byte[] privateKey) {
      Cipher cipher = getEncryptCipherByPrivateKey(privateKey);
      return new JCipherOutputStream(cipher, out);
   }

   /** * 获得公钥加密模式的{@link Cipher} * * @param publicKey * @return */
   public static Cipher getEncryptCipherByPublicKey(byte[] publicKey) {
      return getCipherByPublicKey(publicKey, Cipher.ENCRYPT_MODE);
   }

   /** * 获得私钥加密模式的{@link Cipher} * * @param privateKey * @return */
   public static Cipher getEncryptCipherByPrivateKey(byte[] privateKey) {
      return getCipherByPrivateKey(privateKey, Cipher.ENCRYPT_MODE);
   }

   /** * 公钥解密 * * @param data * @param publicKey * @return */
   public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) {
      Cipher cipher = getDecryptCipherByPublicKey(publicKey);
      try {
         return cipher.doFinal(data);
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }

   /** * 私钥解密 * * @param data * @param privateKey * @return */
   public static byte[] decryptByPrivateKey(byte[] data, byte[] privateKey) {
      Cipher cipher = getDecryptCipherByPrivateKey(privateKey);
      try {
         return cipher.doFinal(data);
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }

   /** * 包裹输入流,原输入流为公钥加密数据输入流 * * @param in * @param publicKey * @return */
   public static InputStream wrapByPublicKey(InputStream in, byte[] publicKey) {
      Cipher cipher = getDecryptCipherByPublicKey(publicKey);
      return new JCipherInputStream(cipher, in);
   }

   /** * 包裹输入流,原输入流为私钥加密数据输入流 * * @param in * @param privateKey * @return */
   public static InputStream wrapByPrivateKey(InputStream in, byte[] privateKey) {
      Cipher cipher = getDecryptCipherByPrivateKey(privateKey);
      return new JCipherInputStream(cipher, in);
   }

   /** * 获得公钥解密模式的{@link Cipher} * * @param publicKey * @return */
   public static Cipher getDecryptCipherByPublicKey(byte[] publicKey) {
      return getCipherByPublicKey(publicKey, Cipher.DECRYPT_MODE);
   }

   /** * 获得私钥解密模式的{@link Cipher} * * @param privateKey * @return */
   public static Cipher getDecryptCipherByPrivateKey(byte[] privateKey) {
      return getCipherByPrivateKey(privateKey, Cipher.DECRYPT_MODE);
   }

   private static Cipher getCipherByPublicKey(byte[] publicKey, int opmode) {
      try {
         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKey);
         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
         Key publicK = keyFactory.generatePublic(x509KeySpec);

         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
         cipher.init(opmode, publicK);
         return cipher;
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }

   private static Cipher getCipherByPrivateKey(byte[] privateKey, int opmode) {
      try {
         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
         Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);

         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
         cipher.init(opmode, privateK);
         return cipher;
      } catch (Exception e) {
         throw new JCodecException(e);
      }
   }

}

测试代码:

package com.jianggujin.codec.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyPair;

import org.junit.Test;

import com.jianggujin.codec.JBase64;
import com.jianggujin.codec.JBase64.JEncoder;
import com.jianggujin.codec.JRSA;
import com.jianggujin.codec.JRSA.JRSASignatureAlgorithm;

public class RSATest {
   String str = "jianggujin";
   File file = new File(getClass().getSimpleName() + ".dat");

   @Test
   public void test() throws Exception {
      System.out.println("原串:" + str);
      JEncoder encoder = JBase64.getEncoder();
      KeyPair keyPair = JRSA.initKey();
      byte[] privateKey = keyPair.getPrivate().getEncoded();
      byte[] publicKey = keyPair.getPublic().getEncoded();
      System.out.println("私钥:" + encoder.encodeToString(privateKey, "UTF-8"));
      System.out.println("公钥:" + encoder.encodeToString(publicKey, "UTF-8"));
      for (JRSASignatureAlgorithm algorithm : JRSASignatureAlgorithm.values()) {
         System.out.println("-----------------------------------------");
         System.out.println("签名算法:" + algorithm.getName());
         byte[] signed = JRSA.sign(str.getBytes(), privateKey, algorithm.getName());
         System.out.println("签名:" + encoder.encodeToString(signed, "UTF-8"));

         boolean verify = JRSA.verify(str.getBytes(), publicKey, signed, algorithm.getName());
         System.out.println("验签:" + verify);
      }

      byte[] encrypt = JRSA.encryptByPrivateKey(str.getBytes(), privateKey);
      System.out.println("私钥加密:" + encoder.encodeToString(encrypt, "UTF-8"));
      System.out.println("公钥解密:" + new String(JRSA.decryptByPublicKey(encrypt, publicKey)));

      System.out.print("输出流私钥加密:" + file.getAbsolutePath());
      OutputStream out = JRSA.wrapByPrivateKey(new FileOutputStream(file), privateKey);
      out.write(str.getBytes());
      out.flush();
      out.close();
      System.out.println();
      System.out.print("输入流公钥解密:");
      InputStream in = JRSA.wrapByPublicKey(new FileInputStream(file), publicKey);
      byte[] buffer = new byte[1024];
      int len = in.read(buffer);
      System.out.println(new String(buffer, 0, len));

      encrypt = JRSA.encryptByPublicKey(str.getBytes(), publicKey);
      System.out.println("公钥加密:" + encoder.encodeToString(encrypt, "UTF-8"));
      System.out.println("私钥解密:" + new String(JRSA.decryptByPrivateKey(encrypt, privateKey)));

      System.out.print("输出流公钥加密:" + file.getAbsolutePath());
      out = JRSA.wrapByPublicKey(new FileOutputStream(file), publicKey);
      out.write(str.getBytes());
      out.flush();
      out.close();
      System.out.println();
      System.out.print("输入流私钥解密:");
      in = JRSA.wrapByPrivateKey(new FileInputStream(file), privateKey);
      len = in.read(buffer);
      System.out.println(new String(buffer, 0, len));
   }
}

测试结果:
原串:jianggujin
私钥:MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIg0EUOutbMRJDuNNCJT97QPK2rrTYFBLBu9vXk6upCvTCn9yZA2M2wNrCv39hVGbXXHSxs2zXpYlWR1IKUvWppQfIscckB3sXJIvvR25xWJWKJSOrbddNKXyvdLjDgor13QVaXJECZJMXsDLFw9kJ+GXz5nzQ43qHyefzLC2YkdAgMBAAECgYAPdlm/ZUYbXgbO++i/POkR9+bl7HCQC+YGADRSXuhvJHdxDO6lAII18hdppmy5XZVvmYBdRottKEFNdj6OgiG22GT2qe0voBaTFpnMEtTNJWJsDjRfnl369XQFC8uPfYF9Qn1nYBSTS+1pxyJSybZkkmAv99sKh1WTHFd+CdhZwQJBANBty698Yy5IXyHHs56EMC81DJjmmZ+WYpRqmUJTSyoCmW9KTztVStX42RMG0tLYOPstbJ0M6rr0G9JVWjJJ3OcCQQCnSjz8hKzu6LC0Arj6fVKPAWboHAjHCQ8AG71JEFkjhvXKYW7dJYua1ePYm4+b8+rr7Ovw6Mvesl36mCWYDIVbAkBkNKU8lTzJv5mdD/nXOA5CY+rOh+9Lvm1elXFhZdI5PE6wJrW4/OShwqX6c8lf/PxIJiqVxuQDReEqWkam7sP5AkA19u/HcbErfGqMFxi+zTCVqxkcJPb75cMuAMTFzf1DRaUCPP37XsIzF25hkIT6BOwyYQIXe7FQTG+eh/gQnXFjAkAGRVxiTmzpSchUjuKOXgS1zjVd4oYqiP4UXQRrrCTmhldkLIEVhm+zsf+t6o01aS/Bc5pJcAUElYvW2AiNFDRx
公钥:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCINBFDrrWzESQ7jTQiU/e0Dytq602BQSwbvb15OrqQr0wp/cmQNjNsDawr9/YVRm11x0sbNs16WJVkdSClL1qaUHyLHHJAd7FySL70ducViViiUjq23XTSl8r3S4w4KK9d0FWlyRAmSTF7AyxcPZCfhl8+Z80ON6h8nn8ywtmJHQIDAQAB
—————————————–
签名算法:MD2withRSA
签名:U1gqODkxXTwQJOqLqHRV3S4gbhIxC036k+LpG4W4kcxhZogDrZxtfFpisXSqgp3DSw+PGgKy6rT7RLIExCi1Qvdh23vmB2Fe7F6yHQ34rhm1NNnbye9ELro7m45t3DP3doY/6qXtGW8N/M5aBs2Mwh2r8uB0KZxE53VvXdWJVac=
验签:true
—————————————–
签名算法:MD5withRSA
签名:AHd5QQTqZgDlXFmS1YF8PSZI7d4gGB50vMnFELwdADZ49PVuMKkiPDHsao5g//6p6e5f13PIuUgZYrOPSyifSSKSy7kT/zhjh7quMUtK3xeNspOQH2pXI1PlU8duY3aejeYfqBQ5rc+L+tFk/B29H/WmtlGVImWV62aCvt8YduY=
验签:true
—————————————–
签名算法:SHA1withRSA
签名:g0bsq25OrrngrAntLNdsXDixO3Zo+DZOe1xdT4n1FLiQDkvv5NvS/HM5jyl8pkZa2VV+536oyRKDrqyLQR8bkbsnjWae9aBF2JweRIXGo4sVm1csQglrz52t4W4/gF0oWqlJhHucTClPdX1XGMBMnRjfXHM01F7QdN1Rezc+1xk=
验签:true
—————————————–
签名算法:SHA224withRSA
签名:QeD1a4s6gaEee9bDTakjergCfwqKfX7x89D8e7GY6rroMf8d3g9JCZkt4PePbhWdorVsUiDexTkHTCXcAGXHu6l9Lxh97O7S/H090i24JLThhVLKBLRZDHidLzfclbvqBky7Fk2PSSlpuxARmxbbc3N5J1a0Sqk9NnMO0AMvgMI=
验签:true
—————————————–
签名算法:SHA256withRSA
签名:FQAliYG2d1rJi+iShdrTuxAQ+TYaghbCcQ0WuvYwmMHf5mz8ilMgGXxuRM75TRLy/LX/Si6uec+gnfB3vC8ep+qWOPh/HXdmofEOpKih+Z3/iy8zvRH+PpuNSwwCifqgGXHzA/thaw93hTx+Ji5qnl8PUn6Rt/cHYsx5takQXGQ=
验签:true
—————————————–
签名算法:SHA384withRSA
签名:ZuD/Cg8DFHZUzj3h61kLHDDU30xBjgq9x4xvwmSkqyEddQfyr2MPAIj4PpiAXhSNpkmKtm+tC0VQseXzfH2tE0Ylzilwun3rfl/Th83bwB9uG4i0xU0vYQkN7flCS7LwbTc/XQc+i3bpSYdJ7/x34kSYEC+K9KMI3n55CNOEEiw=
验签:true
—————————————–
签名算法:SHA512withRSA
签名:euYju1srslIb3yWTM7sAQZIARvgTPKlfd7hCWQ3a6GMK9272kLQWi4b4TQe4gKbMBh6KmMhXJNdRYrEk1AM61d46YHyGqh0TvsaLrk66wemtILBogJzmEFiOpXbPbEtIuOfQMzc+NPDoLDhdCcLJ1ZhSid6a7eR0mb4aYqdJbfY=
验签:true
私钥加密:a4HdJteeI56m1aYbulriTzyvheKlarumWNEesksoO6iQqWNUPHtqe6GfZJuAdu6YOcmf9xctPdRAnTmTTC9pwKlfr0FcIdsheV05ZmdnkfkW5jd73aeP5MCVSiS/gZ74sECB/q3ByJxu+1kHy4dGx920lra7K9iwT0KtaRFFnwI=
公钥解密:jianggujin
输出流私钥加密:F:\workspace\java\eclipse\JCodec\RSATest.dat
输入流公钥解密:jianggujin
公钥加密:FD8wt6qDlmEdGt58ez0YnbZom9+756BOIF701NosVtpYTnG7agyfxdsq486PV5BTeiFU9zH+KKJkh4bXBDFUA0UV+YiLaeX+a/mScG5R7teoqiYpQ63pLhRnD6eFBbbcM+i5oEW3maM9si5nbWjEZ4aYxxQaz4C16Tl9Yeg9OPY=
私钥解密:jianggujin
输出流公钥加密:F:\workspace\java\eclipse\JCodec\RSATest.dat
输入流私钥解密:jianggujin

相关文章