RSA签名和验签 Demo

RSA

RSA是一种非对称加密的算法,是很早之前就出来的,听说是法国的发明。

算法的核心思想是:加解密  、 验签

加解密是为了数据传递的安全性,验签是为了数据传递过程中防止被篡改

1、加解密

说明:加解密

-------------私钥加密,公钥解密;      公钥加密,私钥解密;---------------

解释:RSA算法,会生成一对密钥,包括私钥和公钥;私钥和公钥一般甲方和乙方只保留一个,甲方拥有公钥,乙方就持有私钥,  反之亦然。

具体实现过程:设:甲方持有私钥,乙方持有公钥。

甲方先将数据用私钥加密之后,通过互联网传送给乙方。(加密后的数据一般是base64格式)。乙方收到数据后,用公钥解密,得到想要的数据。。乙方得到数据后,经过处理,把处理后的数据经过公钥加密,通过互联网传递给甲方,甲方用私钥解密,得到数据。。这样,就实现了数据传递的安全性,因为即便黑客得到的传递的数据,也不过是加密的数据,没有解密的密钥,是得不到有用的数据的。但是问题来了:

              黑客得不到数据,气急败坏,将错误的数据发送给甲方或者乙方,怎么办,甲方或者乙方还以为是正常的数据,正常处理了,这样不是导致数据错误了吗?

 这时候,验签功能很好的解决了这个问题

2、签名 、验证签名

说明:验签

-----------私钥签名,公钥验签;   公钥签名,私钥验签  -------------------------

解释:签名和验证签名 通俗易懂,就是验证传过来的数据是不是原始的,没有被改动过的。。具体的原理不懂,实现还是明白的

具体实现:设:甲方持有私钥,乙方持有公钥

甲方通过 (私钥 + 原始数据 ) 得到 签名 sign , 之后,把 加密数据 、sign 发送给乙方。。。乙方收到之后,解密数据之后,得到原始数据,通过(公钥 + 原始数据 + sign) 判断数据是否被改动过。

true 表示验签通过 ,false 表示失败

3、code

(1)签名和验签

package com.zd.test;


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;
 
public class JavaMD5RSASign {
	
	private static String src = "i look";
	
	public static void main(String[] args) {
		MD5RSASign();
	}
	
	
	
	
	
	public static void MD5RSASign(){
		
		try {
			
			// 生成一对密钥
			KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");  //获取密钥生成器实例
			keyPairGenerator.initialize(512);  // 初始化长度
			KeyPair keyPair = keyPairGenerator.generateKeyPair();  
			RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();//生成公钥
			RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();  // 生成私钥
			
			//用私钥进行签名
			PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());  //私钥转换成pkcs8格式
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); // 用key工厂对象生成私钥
			Signature signature = Signature.getInstance("MD5withRSA");  //  md5 RSA签名对象
			signature.initSign(privateKey);  //初始化签名
			signature.update(src.getBytes());
			byte[] result = signature.sign();  //对消息进行签名
			System.out.println("签名结果:"+result);
			
			
			//用公钥进行验证
			X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
			PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
			signature.initVerify(publicKey);
			signature.update(src.getBytes());
			boolean verify = signature.verify(result);
			System.out.println("验证结果:"+verify);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

(2)RSAUtil.java  工具类

package com.zd.util;

import java.io.ByteArrayOutputStream;
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.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by huangxp on 2017/8/15 0015.
 */

import javax.crypto.Cipher;


public class RsaUtil {
    /**
     * 定义加密方式
     */
    private final static String KEY_RSA = "RSA";

    public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";//加密填充方式
    /**
     * 定义签名算法
     */
    private final static String KEY_RSA_SIGNATURE = "MD5withRSA";
    /**
     * 定义公钥算法
     */
    private final static String KEY_RSA_PUBLICKEY = "RSAPublicKey";
    /**
     * 定义私钥算法
     */
    private final static String KEY_RSA_PRIVATEKEY = "RSAPrivateKey";

    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;


    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK_256 = 256;

    private RsaUtil() {
    }

    /**
     * 创建密钥
     *
     * @return
     */
    public static Map<String, Object> generateKey() {
        Map<String, Object> map = null;
        try {
            KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_RSA);
            generator.initialize(1024);
            KeyPair keyPair = generator.generateKeyPair();
            // 公钥
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            // 私钥
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            // 将密钥封装为map
            map = new HashMap<String, Object>();
            map.put(KEY_RSA_PUBLICKEY, publicKey);
            map.put(KEY_RSA_PRIVATEKEY, privateKey);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        return map;
    }

    /**
     * 用私钥对信息生成数字签名
     *
     * @param data       加密数据
     * @param privateKey 私钥
     * @return
     */
    public static String sign(String privateKey, byte[] data) {
        String str = "";
        try {
            // 解密由base64编码的私钥
            byte[] bytes = decryptBase64(privateKey);
            // 构造PKCS8EncodedKeySpec对象
            PKCS8EncodedKeySpec pkcs = new PKCS8EncodedKeySpec(bytes);
            // 指定的加密算法
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            // 取私钥对象
            PrivateKey key = factory.generatePrivate(pkcs);
            // 用私钥对信息生成数字签名
            Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);
            signature.initSign(key);
            signature.update(data);
            str = encryptBase64(signature.sign());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return str;
    }


    /**
     * 用私钥对信息生成数字签名
     *
     * @param privateKey
     * @param dataStr
     * @return
     */
    public static String sign(String privateKey, String dataStr) {
        String str = "";
        try {
            byte[] data = dataStr.getBytes("UTF-8");
            return sign(privateKey, data);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public static String signPublicKey(String publicKey, String dataStr) {
        String str = "";
        try {
            byte[] data = dataStr.getBytes("UTF-8");
            return signPublicKey(publicKey, data);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 用私钥对信息生成数字签名
     *
     * @param data       加密数据
     * @param publicKey 私钥
     * @return
     */
    public static String signPublicKey(String publicKey, byte[] data) {
        String str = "";
        try {

            // 对公钥解密
            byte[] bytes = decryptBase64(publicKey);
            // 取得公钥
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PublicKey key = factory.generatePublic(keySpec);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return str;
    }
    /**
     * 校验数字签名
     *
     * @param data      加密数据
     * @param publicKey 公钥
     * @param sign      数字签名
     * @return 校验成功返回true,失败返回false
     */
    public static boolean verify(String publicKey, byte[] data, String sign) {
        boolean flag = false;
        try {
            // 解密由base64编码的公钥
            byte[] bytes = decryptBase64(publicKey);
            // 构造X509EncodedKeySpec对象
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            // 指定的加密算法
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            // 取公钥对象
            PublicKey key = factory.generatePublic(keySpec);
            // 用公钥验证数字签名
            Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);
            signature.initVerify(key);
            signature.update(data);
            flag = signature.verify(decryptBase64(sign));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return flag;
    }


    public static boolean verify(String publicKey, String dataStr, String sign) {

        try {
            byte[] data = dataStr.getBytes("UTF-8");
            return verify(publicKey, data, sign);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 公钥加密
     *
     * @param key  公钥
     * @param data 待加密数据
     * @return
     */
    public static byte[] encryptByPublicKey(String key, byte[] data) {
        byte[] result = null;
        try {
            // 获取公钥字符串时,进行了encryptBase64操作,因此此处需对公钥钥解密
            byte[] bytes = decryptBase64(key);
            // 取得公钥
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PublicKey publicKey = factory.generatePublic(keySpec);
            // 对数据加密
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            return encryptedData;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String encryptByPublicKey(String key, String dataStr) {
        try {
            byte[] result = encryptByPublicKey(key, dataStr.getBytes("UTF-8"));
            return encryptBase64(result);

        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }


    /**
     * 私钥解密
     *
     * @param data 加密数据
     * @param key  私钥
     * @return
     */
    public static byte[] decryptByPrivateKey(String key, byte[] data,int maxDecryptBlock) {
        byte[] result = null;
        try {
            // 获取私钥字符串时,进行了encryptBase64操作,因此此处需对私钥解密
            byte[] bytes = decryptBase64(key);
            // 取得私钥
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PrivateKey privateKey = factory.generatePrivate(keySpec);
            // 对数据解密
            Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > maxDecryptBlock) {
                    cache = cipher
                            .doFinal(data, offSet, maxDecryptBlock);
                } else {
                    cache = cipher
                            .doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * maxDecryptBlock;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            return decryptedData;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    public static String decryptByPrivateKey256(String key, String dataStr) {
        try {
            byte[] result = decryptByPrivateKey(key, decryptBase64(dataStr),MAX_DECRYPT_BLOCK_256);
            return new String(result);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    public static String decryptByPrivateKey(String key, String dataStr) {
        try {
            byte[] result = decryptByPrivateKey(key, decryptBase64(dataStr),MAX_DECRYPT_BLOCK);
            return new String(result);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * 私钥加密
     *
     * @param data 待加密数据
     * @param key  私钥
     * @return
     */
    public static byte[] encryptByPrivateKey(String key, byte[] data) {
        byte[] result = null;
        try {
            byte[] bytes = decryptBase64(key);
            // 取得私钥
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PrivateKey privateKey = factory.generatePrivate(keySpec);
            // 对数据加密
            Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);

            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            return encryptedData;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    public static String encryptByPrivateKey(String key, String dataStr) {
        try {
            byte[] result = encryptByPrivateKey(key, dataStr.getBytes("UTF-8"));
            return encryptBase64(result).replace("\n","");
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * 公钥钥解密
     *
     * @param key  公钥
     * @param data 加密数据
     * @return
     */
    public static byte[] decryptByPublicKey(String key, byte[] data) {
        byte[] result = null;
        try {
            // 对公钥解密
            byte[] bytes = decryptBase64(key);
            // 取得公钥
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PublicKey publicKey = factory.generatePublic(keySpec);
            // 对数据解密
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, publicKey);

            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher
                            .doFinal(data, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher
                            .doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            return decryptedData;
            //result = cipher.doFinal(data);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // return result;
    }

    public static String decryptByPublicKey(String key, String dataStr) {
        try {
            byte[] result = decryptByPublicKey(key, decryptBase64(dataStr));
            return new String(result,"UTF-8");
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * 获取公钥
     *
     * @param map
     * @return
     */
    public static String getPublicKey(Map<String, Object> map) {
        String str = "";
        try {
            Key key = (Key) map.get(KEY_RSA_PUBLICKEY);
            str = encryptBase64(key.getEncoded());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return str;
    }

    /**
     * 获取私钥
     *
     * @param map
     * @return
     */
    public static String getPrivateKey(Map<String, Object> map) {
        String str = "";
        try {
            Key key = (Key) map.get(KEY_RSA_PRIVATEKEY);
            str = encryptBase64(key.getEncoded());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return str;
    }

    /**
     * BASE64 解密
     *
     * @param key 需要解密的字符串
     * @return 字节数组
     * @throws Exception
     */
    public static byte[] decryptBase64(String key) {
        //  return javax.xml.bind.DatatypeConverter.parseBase64Binary(key);
//        return Base64.decode(key, Base64.DEFAULT);
    	return Base64.getDecoder().decode(key);

    }

    /**
     * BASE64 加密
     *
     * @param key 需要加密的字节数组
     * @return 字符串
     * @throws Exception
     */
    public static String encryptBase64(byte[] key) {
    	
        return Base64.getEncoder().encodeToString(key);
    }

}

 总结:数据如果敏感,建议使用RSA加密,比较安全。。设置初始的字节为1024很安全,听说一般人破解不了。2048,贼安全

送给自己:人总要有点理想,就算没有用,起码算个信仰,这个信仰在一些时候总会莫名其妙的给你一股力量。坚持你走完最难的路。。即便感动不了别人,也能感动自己。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章