zoukankan      html  css  js  c++  java
  • JAVA 非对称加密算法RSA

    非对称加密算法 RSA过程 : 以甲乙双方为例
      1、初始化密钥 构建密钥对,生成公钥、私钥保存到keymap中
        KeyPairGenerator ---> KeyPair --> RSAPublicKey、RSAPrivateKey
      2、甲方使用私钥加密, 加密后在用私钥对加密数据进行数据签名,然后发送给乙方
        RSACoder.encryptByPrivateKey(data, privateKey);
        RSACoder.sign(encodedData, privateKey);
      3、乙方则通过公钥验证签名的加密数据,如果验证正确则在通过公钥对加密数据进行解密
        RSACoder.verify(encodedData, publicKey, sign);
        RSACoder.decryptByPublicKey(encodedData, publicKey);
       4、乙方在通过公钥加密发送给甲方
        RSACoder.encryptByPublicKey(decodedData, publicKey);
      5、甲方通过私钥解密该数据
        RSACoder.decryptPrivateKey(encodedData, privateKey);
    流程图如下:

    java代码实现如下:

    package com.bank.utils;
    
    import java.security.MessageDigest;
    
    import javax.crypto.KeyGenerator;
    import javax.crypto.Mac;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    
    public abstract class Coder {
    	public static final String KEY_SHA = "SHA";
    	public static final String KEY_MD5 = "MD5";
    	
    	/** 
         * MAC算法可选以下多种算法 
         *  
         * <pre> 
         * HmacMD5  
         * HmacSHA1  
         * HmacSHA256  
         * HmacSHA384  
         * HmacSHA512 
         * </pre> 
         */  
    	public static final String KEY_MAC = "HmacMD5";
    	
    	/**
    	 * BASE64解密
    	 * @param key
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] decryptBASE64( String key ) throws Exception{
    		return (new BASE64Decoder()).decodeBuffer(key);
    	}
    	
    	/**
    	 * BASE64加密
    	 * @param key
    	 * @return
    	 * @throws Exception
    	 */
    	public static String encryptBASE64( byte[] key) throws Exception{
    		return (new BASE64Encoder()).encodeBuffer(key);
    	}
    	
    	/**
    	 * MD5 加密
    	 * @param data
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] encryptMD5( byte[] data) throws Exception {
    		MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
    		md5.update(data);
    		
    		return md5.digest();
    	}
    	
    	/**
    	 * SHA 加密
    	 * @param data
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] encryptSHA( byte[] data) throws Exception {
    		MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
    		sha.update(data);
    		
    		return sha.digest();
    	}
    	
    	/** 
         * 初始化HMAC密钥 
         *  
         * @return 
         * @throws Exception 
         */  
    	public static String initMacKey() throws Exception{
    		KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
    		
    		SecretKey secretKey = keyGenerator.generateKey();
    		return encryptBASE64(secretKey.getEncoded());
    	}
    	
    	/**
    	 * HMAC  加密
    	 * @param data
    	 * @param key
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] encryptHMAC( byte[] data, String key) throws Exception{
    		SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC);
    		Mac mac = Mac.getInstance(secretKey.getAlgorithm());
    		mac.init(secretKey);
    		return mac.doFinal(data);
    	}
    }
    

      

    package com.bank.utils;
    
    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.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.crypto.Cipher;
    
    
    public abstract class RSACoder extends Coder{
    	public static final String KEY_ALGORITHM = "RSA";
    	public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
    	
    	private static final String PUBLIC_KEY = "RSAPublicKey";
    	private static final String PRIVATE_KEY = "RSAPrivatekey";
    	
    	/**
    	 * 用私钥对信息生成数字签名
    	 * @param data 加密数据
    	 * @param privateKey 私钥
    	 * @return
    	 * @throws Exception
    	 */
    	public static String sign(byte[] data, String privateKey) throws Exception {
    		//解密由base64编码的私钥
    		byte[] keyBytes = decryptBASE64(privateKey);
    		
    		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
    		
    		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    		
    		//取私钥对象
    		PrivateKey pKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    		
    		//用私钥生成数字签名
    		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
    		signature.initSign(pKey);
    		signature.update(data);
    		
    		return encryptBASE64(signature.sign());
    	}
    	
    	/**
    	 * 校验数字签名
    	 * @param data 加密数据
    	 * @param publicKey 公钥
    	 * @param sign 数字签名
    	 * @return
    	 * @throws Exception
    	 */
    	public static boolean verify(byte[] data, String publicKey, String sign) throws Exception{
    		
    		//解密有base64编码的公钥
    		byte[] keyBytes = decryptBASE64(publicKey);
    		
    		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
    		
    		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    		
    		//取公钥对象
    		PublicKey pKey = keyFactory.generatePublic(keySpec);
    		
    		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
    		signature.initVerify(pKey);
    		signature.update(data);
    		//验证签名是否正常
    		return signature.verify(decryptBASE64(sign));
    	}
    	
    	/**
    	 * 解密 
    	 * 	用私钥解密
    	 * @param data 加密数据
    	 * @param key
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] decryptPrivateKey(byte[] data, String key) throws Exception{
    		byte[] keyBytes = decryptBASE64(key);
    		
    		//取得私钥
    		PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
    		KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
    		Key pKey = factory.generatePrivate(encodedKeySpec);
    		
    		//对数据解密
    		Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
    		cipher.init(Cipher.DECRYPT_MODE, pKey);
    		
    		return cipher.doFinal(data);
    	}
    	
    	/**
    	 * 用公钥解密
    	 * @param data
    	 * @param key
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] decryptByPublicKey( byte[] data, String key) throws Exception{
    		
    		//解密
    		byte[] keyBytes = decryptBASE64(key);
    		
    		//取得公钥
    		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
    		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    		Key pKey = keyFactory.generatePublic(keySpec);
    		
    		//对数据解密
    		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    		cipher.init(Cipher.DECRYPT_MODE, pKey);
    		
    		return cipher.doFinal(data);
    	}
    	
    	/**
    	 * 用公钥加密
    	 * @param data
    	 * @param key
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] encryptByPublicKey( byte[] data, String key) throws Exception{
    		
    		byte[] keyBytes = decryptBASE64(key);
    		
    		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
    		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    		Key pKey = keyFactory.generatePublic(keySpec);
    		
    		
    		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    		cipher.init(Cipher.ENCRYPT_MODE, pKey);
    		
    		return cipher.doFinal(data);
    	}
    	
    	/**
    	 * 用私钥加密
    	 * @param data
    	 * @param key
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception{
    		
    		byte[] keyBytes = decryptBASE64(key);
    		
    		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
    		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    		Key privateKey = keyFactory.generatePrivate(keySpec);
    		
    		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    		
    		return cipher.doFinal(data);
    	}
    	
    	/**
    	 * 取得私钥
    	 * @param keyMap
    	 * @return
    	 * @throws Exception
    	 */
    	public static String getPrivateKey( Map<String, Object> keyMap) throws Exception{
    
    		Key key = (Key) keyMap.get(PRIVATE_KEY);
    		
    		return encryptBASE64(key.getEncoded());
    	}
    	
    	/**
    	 * 取得公钥
    	 * @param keyMap
    	 * @return
    	 * @throws Exception
    	 */
    	public static String getPublicKey( Map<String, Object> keyMap) throws Exception{
    
    		Key key = (Key) keyMap.get(PUBLIC_KEY);
    		
    		return encryptBASE64(key.getEncoded());
    	}
    	/**
    	 * 初始化密钥
    	 * @return
    	 * @throws Exception
    	 */
    	public static Map<String, Object> initKey() throws Exception{
    		
    		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
    		keyPairGenerator.initialize(1024);
    		
    		KeyPair keyPair = keyPairGenerator.generateKeyPair();
    		//公钥
    		RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    		
    		//私钥
    		RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    		
    		Map<String, Object> keyMap = new HashMap<String, Object>(2);
    		keyMap.put(PRIVATE_KEY, privateKey);
    		keyMap.put(PUBLIC_KEY, publicKey);
    		return keyMap;
    	}
    }
    

      

    package com.bank.test;
    
    import java.util.Map;
    
    import org.junit.Assert;
    import org.junit.Before;
    import org.junit.Test;
    
    import com.bank.utils.RSACoder;
    
    public class RSACoderTest {
    	private String publicKey;
    	private String privateKey;
    	/*
    	 * 非对称加密算法   RSA过程 : 以甲乙双方为例
    	 * 		1、初始化密钥 构建密钥对,生成公钥、私钥保存到keymap中
    	 * 				KeyPairGenerator --->	KeyPair		-->		RSAPublicKey、RSAPrivateKey
    	 * 		2、甲方使用私钥加密, 加密后在用私钥对加密数据进行数据签名,然后发送给乙方
    	 * 				RSACoder.encryptByPrivateKey(data, privateKey);
    	 * 				RSACoder.sign(encodedData, privateKey);
    	 * 		3、乙方则通过公钥验证签名的加密数据,如果验证正确则在通过公钥对加密数据进行解密
    	 * 				RSACoder.verify(encodedData, publicKey, sign);
    	 * 				RSACoder.decryptByPublicKey(encodedData, publicKey);				
    	 * 
    	 * 		4、乙方在通过公钥加密发送给甲方
    	 * 				RSACoder.encryptByPublicKey(decodedData, publicKey);
    	 * 		5、甲方通过私钥解密该数据		
    	 * 				RSACoder.decryptPrivateKey(encodedData, privateKey);				
    	 */
    	@Before
    	public void setUp() throws Exception {
    		
    		Map<String , Object> keyMap = RSACoder.initKey();
    		
    		publicKey = RSACoder.getPublicKey(keyMap);
    		privateKey = RSACoder.getPrivateKey(keyMap);
    		
    		System.out.println("公钥:
    " + publicKey);
    		System.out.println("私钥:
    " + privateKey);
    	}
    	@Test
    	public void test() throws Exception{
    		String inputStr = "abc";
    		byte[] data = inputStr.getBytes();//每次的得到的字节数组是不一样的。
    		//第二步 私钥加密
    		byte[] encodedData = RSACoder.encryptByPrivateKey(data, privateKey);
    		//私钥进行数据签名
    		String sign = RSACoder.sign(encodedData, privateKey);
    		
    		//第三步 公钥验证数字签名
    		boolean flag = RSACoder.verify(encodedData, publicKey, sign);
    		System.out.println("flag:" + flag);
    		//用公钥对数据解密
    		byte[] decodedData = RSACoder.decryptByPublicKey(encodedData, publicKey);
    		
    		System.out.println("data:" + data + "加密数据:" + encodedData + "    解密数据:" + decodedData);
    		System.out.println("加密前数据-:" + new String(data) + "     解密后数据: " + new String(decodedData));
    		
    		//第四步使用公钥加密数据
    		encodedData = RSACoder.encryptByPublicKey(decodedData, publicKey);
    		
    		//第五步 使用私钥解密数据
    		decodedData = RSACoder.decryptPrivateKey(encodedData, privateKey);
    		
    		
    		System.out.println("data:" + data + "加密数据:" + encodedData + "    解密数据:" + decodedData);
    		System.out.println("加密前数据:" + inputStr + "     解密后数据: " + new String(decodedData));
    	}
    	
    	
    	@Test
    	public void test1() throws Exception{
    		System.out.println("私钥加密-----公钥解密");
    		String inputStr = "abc";
    		byte[] data = inputStr.getBytes();
    		System.out.println("data:" + data);
    		
    		byte[] encodedData = RSACoder.encryptByPrivateKey(data, privateKey);
    		byte[] decodedData = RSACoder.decryptByPublicKey(encodedData, publicKey);
    	
    		String outputStr = new String( decodedData );
    		
    		System.out.println("加密前:" + inputStr +"
     解密后:" + outputStr);
    		
    		Assert.assertEquals(inputStr, outputStr);
    		
    		
    		System.out.println("私钥签名---公钥验证签名");
    		//产生签名
    		String sign = RSACoder.sign(encodedData, privateKey);
    		System.out.println("签名:
    " + sign);
    		
    		//验证签名
    		boolean flag = RSACoder.verify(encodedData, publicKey, sign);
    		
    		System.out.println("状态:
    " + flag);
    		
    		Assert.assertTrue(flag);
    	}
    }
    

      

  • 相关阅读:
    windows系统下的文件夹链接功能mklink/linkd
    packetfence 7.2网络准入部署(一)
    packetfence 7.2网络准入部署(二)
    博客园转载其他博客园的文章:图片和源码
    使用ARP欺骗, 截取局域网中任意一台机器的网页请求,破解用户名密码等信息
    Huawei AP3030DN固件升级
    iOS高版本备份恢复到低版本系统的方法
    比较正确的 iPhone7/7+ 的进入DFU的方法是这样的
    使用kbmmw smarthttpservice 简单返回数据库结果
    kbmmw 5.07 正式发布
  • 原文地址:https://www.cnblogs.com/yuanfy008/p/4201168.html
Copyright © 2011-2022 走看看