学习JAVA中RSA算法实现

论坛 期权论坛 脚本     
匿名网站用户   2020-12-21 09:33   30   0

package org.java.se.security.rsa;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.java.se.security.base64.Base64;
import org.junit.Before;
import org.junit.Test;

/**
 * RSA加密解密和签名的实现
 * @author xianglj
 */
public class RSACodec {

 /**
  * RSA的签名算法
  */
 private static final String ALGORITHM_RSA = "RSA";
 /**
  * 签名算法
  */
 private static final String ALGORITHM_SIGNATURE = "MD5withRSA";
 
 private static final String RSA_PRIVATE_KEY = "RSAPrivateKey";
 
 private static final String RSA_PUBLIC_KEY = "RSAPublicKey";
 
 /**
  * 生成私钥和私钥对
  * @return
  * @throws NoSuchAlgorithmException 
  */
 public static Map<String, Key> generateKeyPair() throws NoSuchAlgorithmException {
  KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGORITHM_RSA);
  KeyPair keyPair = generator.generateKeyPair();
  PublicKey pk = keyPair.getPublic();
  PrivateKey prK = keyPair.getPrivate();
  Map<String, Key> keyMap = new HashMap<String, Key>();
  keyMap.put(RSA_PRIVATE_KEY, prK);
  keyMap.put(RSA_PUBLIC_KEY, pk);
  return keyMap;
 }
 
 /**
  * 签名。运用私钥进行签名
  * @param data 需要加密的数据
  * @param secretKey 私钥字符串-base64加密字符串
  * @return
  * @throws IOException 
  * @throws NoSuchAlgorithmException 
  * @throws InvalidKeySpecException 
  * @throws InvalidKeyException 
  * @throws SignatureException 
  */
 public static String sign(byte[] data, String secretKey) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
  byte[] bytes = Base64.decript(secretKey);
  //获取私钥
  PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
  KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
  PrivateKey pk = keyFactory.generatePrivate(keySpec);
  //进行签名
  Signature signnature = Signature.getInstance(ALGORITHM_SIGNATURE);
  signnature.initSign(pk);
  signnature.update(data);
  return Base64.encript(signnature.sign());
 }
 
 /**
  * 验证签名
  * @return
  * @throws IOException 
  * @throws NoSuchAlgorithmException 
  * @throws InvalidKeySpecException 
  * @throws InvalidKeyException 
  * @throws SignatureException 
  */
 public static boolean verify(byte[] data, String publicKey, String sign) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
  //生成公钥
  byte[] bytes = Base64.decript(publicKey);
  //构造X509EncodedKeySpec对象
  X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
  KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
  PublicKey pk = keyFactory.generatePublic(keySpec);
  
  //验证签名
  Signature signature = Signature.getInstance(ALGORITHM_SIGNATURE);
  signature.initVerify(pk);
  signature.update(data);
  return signature.verify(Base64.decript(sign));
 }
 
 /**
  * 采用私钥对数据进行加密
  * 
  * @param data
  * @param privateKey
  * @throws IOException 
  * @throws NoSuchAlgorithmException 
  * @throws InvalidKeySpecException 
  * @throws NoSuchPaddingException 
  * @throws InvalidKeyException 
  * @throws BadPaddingException 
  * @throws IllegalBlockSizeException 
  */
 public static String encriptByPrivateKey(byte[] data, String privateKey) 
   throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
  //获取privateKey
  byte[] bytes = Base64.decript(privateKey);
  PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
  KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
  PrivateKey pk = keyFactory.generatePrivate(keySpec);
  
  //对数据进行加密
  Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
  cipher.init(Cipher.ENCRYPT_MODE, pk);
  cipher.update(data);
  return Base64.encript(cipher.doFinal());
 }
 
 /**
  * 通过公钥加密
  * 
  * @param data
  * @param publicKey
  * @return
  * @throws IOException
  * @throws InvalidKeySpecException
  * @throws NoSuchAlgorithmException
  * @throws NoSuchPaddingException 
  * @throws InvalidKeyException 
  * @throws BadPaddingException 
  * @throws IllegalBlockSizeException 
  */
 public static String encriptByPublicKey(byte[] data, String publicKey) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
  byte[] bytes = Base64.decript(publicKey);
  X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
  PublicKey pk = KeyFactory.getInstance(ALGORITHM_RSA).generatePublic(keySpec);
  
  Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
  cipher.init(Cipher.ENCRYPT_MODE, pk);
  cipher.update(data);
  return Base64.encript(cipher.doFinal());
 }
 
 /**
  * 使用私钥进行解密。
  * @param data 采用PublicKey进行加密的字节数组
  * @param privateKey 私钥的Base64字符串。
  * @return 采用私钥解密后的byte数组
  * @throws IOException 
  * @throws NoSuchAlgorithmException 
  * @throws InvalidKeySpecException 
  * @throws NoSuchPaddingException 
  * @throws InvalidKeyException 
  * @throws BadPaddingException 
  * @throws IllegalBlockSizeException 
  */
 public static byte[] decriptByPrivateKey(byte[] data, String privateKey) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
  //获取私钥
  byte[] pkBytes = Base64.decript(privateKey);
  //构造PKCS8EncodedKeySpec对象
  PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkBytes);
  PrivateKey pk = KeyFactory.getInstance(ALGORITHM_RSA).generatePrivate(keySpec);
  
  //进行解密
  Cipher cipher = Cipher.getInstance(ALGORITHM_RSA); //构建Cipher对象
  //设置cipher的模式
  cipher.init(Cipher.DECRYPT_MODE, pk);
  //解密数据
  cipher.update(data);
  return cipher.doFinal();
 }
 
 /**
  * 根据公钥进行解密
  * 
  * @param data 经过私钥加密的字节数组
  * @param publicKey 公钥字符串
  * @return 解密后的字节数组
  * @throws IOException 
  * @throws NoSuchAlgorithmException 
  * @throws InvalidKeySpecException 
  * @throws NoSuchPaddingException 
  * @throws InvalidKeyException 
  * @throws BadPaddingException 
  * @throws IllegalBlockSizeException 
  */
 public static byte[] decriptByPublicKey(byte[] data, String publicKey) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
  //获取公钥
  byte[] pkBytes = Base64.decript(publicKey);
  X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pkBytes);
  PublicKey pk = KeyFactory.getInstance(ALGORITHM_RSA).generatePublic(keySpec);
  
  Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
  cipher.init(Cipher.DECRYPT_MODE, pk);
  cipher.update(data);
  return cipher.doFinal();
 }
 
 /**
  * 获取公钥字符串
  */
 public static String getPublicKey() {
  Key publicKey = keyMap.get(RSA_PUBLIC_KEY);
  return Base64.encript(publicKey.getEncoded());
 }
 
 /**
  * 获取私钥
  * @return
  */
 public static String getPrivateKey() {
  Key privateKey = keyMap.get(RSA_PRIVATE_KEY);
  return Base64.encript(privateKey.getEncoded());
 }
 
 private static Map<String, Key> keyMap ;
 
 @Before
 public void setUp() throws NoSuchAlgorithmException {
  keyMap = generateKeyPair();
 }
 
 @Test
 public void testSign() throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, IOException {
  String privateKey = getPrivateKey();
  String publicKey = getPublicKey();
  System.out.println("私钥:" + privateKey);
  System.out.println("公钥:" + publicKey);
  
  //需要签名的数据
  String data = "这个数据需要签名";
  String signData = sign(data.getBytes(), privateKey);
  System.out.println("签名的数据为:" + signData);
  //验证签名
  boolean isSuc = verify(data.getBytes(), publicKey, signData);
  System.out.println("签名是否成功:" + isSuc);
 }
 
 /**
  * 测试使用公钥加密,私钥解密
  * @throws IOException 
  * @throws BadPaddingException 
  * @throws IllegalBlockSizeException 
  * @throws NoSuchPaddingException 
  * @throws NoSuchAlgorithmException 
  * @throws InvalidKeySpecException 
  * @throws InvalidKeyException 
  */
 @Test
 public void testCript() throws InvalidKeyException, InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, IOException {
  String privateKey = getPrivateKey();
  String publicKey = getPublicKey();
  
  //设置需要加密的字符串
  String str = "我将要被公钥加密,私钥解密哦。。。。";
  System.out.println("明文为:\r\n" + str);
  
  //利用公钥加密
  String encriptStr = encriptByPublicKey(str.getBytes(), publicKey);
  System.out.println("采用公钥加密后的密文为:\r\n" + encriptStr);
  
  //采用私钥解密
  byte[] pkBytes = decriptByPrivateKey(Base64.decript(encriptStr), privateKey);
  String decriptStr = new String(pkBytes);
  System.out.println("采用公钥解密后的明文为:\r\n" + decriptStr);
  
  //比较
  System.out.println("明文和密文是否一致:\r\n" + (str.equals(decriptStr)));
 }
 
 /**
  * 测试采用私钥加密,公钥解密
  * 
  * @throws InvalidKeyException
  * @throws NoSuchAlgorithmException
  * @throws InvalidKeySpecException
  * @throws NoSuchPaddingException
  * @throws IllegalBlockSizeException
  * @throws BadPaddingException
  * @throws IOException
  */
 @Test
 public void encriptTest() throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, IOException {
  String privateKey = getPrivateKey();
  String publicKey = getPublicKey();
  
  //设置需要加密的字符串
  String str = "我将要被私钥加密,用公钥解密....";
  System.out.println("明文:" + str);
  
  //利用私钥加密
  String ecriptStr = encriptByPrivateKey(str.getBytes(), privateKey);
  System.out.println("利用公钥加密后的密文为:" + ecriptStr);
  
  //利用公钥解密
  byte[] pkBytes = decriptByPublicKey(Base64.decript(ecriptStr), publicKey);
  String decriptStr = new String(pkBytes);
  System.out.println("解密后的明文为:" + decriptStr);
  
  //比较
  System.out.println("是否一致:" + (str.equals(decriptStr)));
 }
}

RSA为非对称加密算法,主要实现步骤:

1. 生成密钥对。私钥和公钥。公钥可以对外公布,或者发布于客户端使用。

2. RSA的加密和解密,都需要密钥的参与。如果采用PublicKey进行加密,则需要对应的 PrivateKey 进行解密。如果采用PrivateKey加密,则需要PublicKey进行解密。因此为了数据的安全性,需要妥善保管密钥

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP