网络安全 —— 网络加密(不可逆加密、对称加密、不对称加密)

一、网络安全

1、网络安全概述

(1)通常的网络安全有SQL注入,XSS脚本攻击,CRSF伪脚本攻击,DDOS拒绝服务攻击。

(2)SQL注入
所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
预防方式:

  • 使用预编译
  • 使用ORM框架
  • 执行sql语句是使用addslashes进行sql语句转换
  • sql语句书写尽量不要省略双引号和单引号
  • 过滤掉sql语句里的关键词 :update insert delete select *
  • PHP配置文件中设置register_global为off,关闭全局变量注册
  • 控制错误信息 不要把错误信息输出到浏览器上 应保存在错误日

(3)XSS攻击
XSS攻击的全称是跨站脚本攻击,指的是攻击者在网页中嵌入恶意脚本程序,如<script>alert(1111)</script>。当用户打开该网页时,脚本程序便开始在客户端的浏览器上执行,以盗取客户端cookie,用户名密码,下载执行病毒密码程序,甚至是获取客户端admin权限等。
预防方式:

  • 在前端进行输入验证,如果发现类似脚本程序的输入,就将其转义。
  • 在后端接收到数据的时候进行验证和转义。

(4) CRSF攻击
CRSF攻击的全称是跨站请求伪造,是一种对网站的恶意利用,XSS利用的是站点内的信任用户,而CRSF则是通过伪装来自受信任用户的请求来利用受信任的网站。
预防方式:

  • Cookie Hashing(所有表单都包含同一个伪随机值):
  • 验证码
  • One-Time Tokens(不同的表单包含一个不同的伪随机值)

(5)DDOS拒绝服务攻击
DDOS流量攻击
预防方式:

  • 使用工具:DDOS deflate . 自动查封IP.e
  • 析域名到127.0.0.1 让攻击方自己攻击自己
  • 把网站做成静态页面
  • 制S YN/ICMP流量
  • 通过提高服务端的配置,比如:宽带,并发量
  • 在服务端限制第二次握手的时间,如果时间超时,就直接把这个连接断开,并从链接列表中清除相关信息。

2、加密,系统安全措施

(1)加密三种方式:不可逆加密、对称加密、不对称加密
(2)不可逆加密
不可逆加密的加密结果没法解密,典型的有:MD5、sha256、HMAC加密

① MD5加密

  • 不可逆运算,对不同的数据加密的结果是定长的32位字符(不管文件多大都一样),对相同的数据加密,得到的结果是一样的(也就是复制)。
  • 抗修改性 : 信息“指纹”,对原数据进行任何改动,哪怕只修改一个字节,所得到的 MD5 值都有很大区别.
  • 弱抗碰撞 : 已知原数据和其 MD5 值,想找到一个具有相同 MD5 值的数据(即伪造数据)是非常困难的.
  • 强抗碰撞: 想找到两个不同数据,使他们具有相同的 MD5 值,是非常困难的
public class EncUtils {
	public static String MD5Enc(String password) {
		return DigestUtils.md5Hex(password);
	}
}

如果想要加密更深,可以用循环再加密。

public class EncUtils {
	public static String MD5Enc(String password) {
		for(int i = 0; i < 1024; i++) {
			password = DigestUtils.md5Hex(password);
		}
		return password;
	}
}

② sha256加密

  • 安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。
  • 对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。当让除了SHA1还有SHA256以及SHA512等。
  • SHA1特性:
    • 不可以从消息摘要中复原信息;
    • 两个不同的消息不会产生同样的消息摘要。
public class EncUtils {
	public static String sha256Enc(String password) {
		for(int i = 0; i < 1024; i++) {
			password = DigestUtils.sha256Hex(password);
		}
		return password;
	}
}

③ HMAC加密

  • HMAC:给定一个密钥,对明文加密,做两次“散列”,得到的结果还是32为字符串。在实际开发中,密钥是服务器生成,客户端发送请求会拿到KEY,一个账号对应一个KEY。
  • 以注册为例:当用户把账号提交给服务器,服务器会验证账号的合法性,如果合法就会生成个KEY给客户端(这个KEY只有在注册的时候会出现一次,一个账号只对应一个KEY);客户端会用拿到的KEY给密码用HMAC方式加密(32位字符串)发给服务器,最终服务器会保存这个HMAC密码。这样就注册成功了!以后再登录就会服务器就会比对这个HMAC密码是否相等决定能否登录成功。

(3)对称加密
对称加密算法又称传统加密算法,对称加密跟解密使用的是相同的密钥,加密解密过程:明文->密钥加密->密文,密文->密钥解密->明文。典型的有:DES(80年代)、3DES、AES(目前常用)(相对不安全)

① DES(Data Encryption Standard)
数据加密标准(现在用的比较少,因为它的加密强度不够,能够暴力破解) 。

② 3DES
原理和DES几乎是一样的,只是使用3个密钥,对相同的数据执行三次加密,增强加密强度。(缺点:要维护3个密钥,大大增加了维护成本) 。

③ AES(Advanced Encryption Standard)

  • AES是高级加密标准,目前美国国家安全局使用的,苹果的钥匙串访问采用的就AES加密。是现在公认的最安全的加密方式,是对称密钥加密中最流行的算法。
  • AES的安全性相对RSA较低,但是效率比RAS高,AES应用于https协议的ssl协议的底层实现。

AES加密Demo
AES解密工具 AESUtils 类

public class AESUtils {
    //密钥 (需要前端和后端保持一致)
    private static final String KEY = "abcdefgabcdefg12";
    //算法,ECB定义AES的计算模式,加密算法标准
    private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
    
    //aes解密
    public static String decr(String content) {
        byte[] mes = null;
        try {
            @SuppressWarnings("restriction")
			byte[] base64Content = new BASE64Decoder().decodeBuffer(content);
            Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
            cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(KEY.getBytes(),"AES"));
            mes = new byte[0];
            mes = cipher.doFinal(base64Content);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new String(mes);
    }
   }

控制层 UsersController 类

@RestController
public class UsersController {
	@Resource
	private UsersService us;
	
	@GetMapping("login")
	public String select(String userName, String userPassword) throws Exception {
		System.out.println("AES解密前:" + userPassword);
		userPassword = AESUtils.decr(userPassword);
		System.out.println("AES解密后:" + userPassword);
		System.out.println("userName=" + userName);
		//sha256加密
//		userPassword = EncUtils.sha256Enc(userPassword);
		//MD5加密
		userPassword = EncUtils.MD5Enc(userPassword);
		
		String str = null;
		Users users = us.selectByUserName(userName);
		if(users != null) {
			if(users.getUserPassword().equals(userPassword)) {
				str = "success";
			}else {
				str = "error";
			}
		}else {
			str = "账号不存在";
		}
		return str;
	}
}

前端发送请求网页

<body>
		<form id="login">
	        <input name="userName" id="userName"><br>
	        <input type="password" name="userPassword" id="userPassword"><br>
	        <input type="button" value="登录" onclick="login()">
	    </form>
	    <script type="text/javascript">
	        function login(){
	        	var userName = $("#userName").val();
	        	var userPassword = $("#userPassword").val();
	        	console.log("AES加密前:" + userPassword);
	        	/* 执行加密方法 */
	        	userPassword = encrypt(userPassword);
	        	console.log("AES加密后:" + userPassword);
	            $.ajax({
	                   url:"/login",
	                   type:"get",
	                   data:{"userName":userName, "userPassword":userPassword},
	                   success:function(data){
		                   console.log(data);
		                   if(data == "success"){
		                        location.href="success.html";
		                   }else if(data == "error"){
		                        location.href="error.html";
		                   }
	                   }
	               });
	         }
	        
	        /*加密方法(需要先加载aes.js文件)*/
	        function encrypt(word){
	            var key = CryptoJS.enc.Utf8.parse("abcdefgabcdefg12");
	            var srcs = CryptoJS.enc.Utf8.parse(word);
	            var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
	            return encrypted.toString();
	        }
	
	        /* 解密方法*/
	        function decrypt(word){
	            var key = CryptoJS.enc.Utf8.parse("abcdefgabcdefg12");
	            var decrypt = CryptoJS.AES.decrypt(word, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
	            return CryptoJS.enc.Utf8.stringify(decrypt).toString();
	        }
	    </script>
	</body>

一份比较完整的AES加密工具类

/**
 *AES加密解密工具类
 */
public class AESUtils {
    //密钥 (需要前端和后端保持一致)
    private static final String KEY = "abcdefgabcdefg12";
    //算法,ECB定义AES的计算模式,加密算法标准
    private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
    
    //aes解密
    public static String decr(String content) {
        byte[] mes = null;
        try {
            @SuppressWarnings("restriction")
			byte[] base64Content = new BASE64Decoder().decodeBuffer(content);
            Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
            cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(KEY.getBytes(),"AES"));
            mes = new byte[0];
            mes = cipher.doFinal(base64Content);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new String(mes);
    }

    /**
     * aes解密
     * @param encrypt   内容
     * @return
     * @throws Exception
     */
    public static String aesDecrypt(String encrypt) {
        try {
            return aesDecrypt(encrypt, KEY);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * aes加密
     * @param content
     * @return
     * @throws Exception
     */
    public static String aesEncrypt(String content) {
        try {
            return aesEncrypt(content, KEY);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * base 64 encode
     * @param bytes 待编码的byte[]
     * @return 编码后的base 64 code
     */
    public static String base64Encode(byte[] bytes){
        return Base64.encodeBase64String(bytes);
    }

    /**
     * base 64 decode
     * @param base64Code 待解码的base 64 code
     * @return 解码后的byte[]
     * @throws Exception
     */
    @SuppressWarnings("restriction")
	public static byte[] base64Decode(String base64Code) throws Exception{
        return StringUtils.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);
    }


    /**
     * AES加密
     * @param content 待加密的内容
     * @param encryptKey 加密密钥
     * @return 加密后的byte[]
     * @throws Exception
     */
    public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));

        return cipher.doFinal(content.getBytes("utf-8"));
    }

    /**
     * AES加密为base 64 code
     * @param content 待加密的内容
     * @param encryptKey 加密密钥
     * @return 加密后的base 64 code
     * @throws Exception
     */
    public static String aesEncrypt(String content, String encryptKey) throws Exception {
        return base64Encode(aesEncryptToBytes(content, encryptKey));
    }

    /**
     * AES解密
     * @param encryptBytes 待解密的byte[]
     * @param decryptKey 解密密钥
     * @return 解密后的String
     * @throws Exception
     */
    public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
//        KeyGenerator kgen = KeyGenerator.getInstance("AES");
//        kgen.init(128);

        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
        byte[] decryptBytes = cipher.doFinal(encryptBytes);
        return new String(decryptBytes);
    }

    /**
     * 将base 64 code AES解密
     * @param encryptStr 待解密的base 64 code
     * @param decryptKey 解密密钥
     * @return 解密后的string
     * @throws Exception
     */
    public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
        return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);
    }
}

(4)不对称加密

  • 非对称加密算法又称现代加密算法,非对称加密是计算机通信安全的基石,保证了加密数据不会被破解,典型的有RSA(相对安全)。
  • 非对称加密算法需要两个密钥:公开密钥(publickey) 和私有密(privatekey) ,公开密钥和私有密钥是一对
    • 如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密。
    • 如果用私有密钥对数据进行加密,只有用对应的公开密钥才能解密。
  • 特点:
  • 算法强度复杂,安全性依赖于算法与密钥。
  • 加密解密速度慢。
  • 与对称加密算法的对比:
    • 对称加密只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。
    • 非对称加密有两种密钥,其中一个是公开的。

① RSA加密

  • 由于RSA算法的加密解密速度要比对称算法速度慢很多,在实际应用中,通常采取数据本身的加密和解密使用对称加密算法(AES),用RSA算法加密并传输对称算法所需的密钥。

RSA加密Demo:RSA+时间戳完成登录验证

控制层 UsersController 类

@RestController
public class UsersController {
	//记录日志
	private static final Logger log = LoggerFactory.getLogger(UsersController.class);

	//私钥
	private static final String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJX/0JqAPr0mdq9ZN0XqYEVWYApf\r\n" + 
			"EvoNkmzN0tgQ2CrI0Z8rcmw0CiPH1m1Rp0I/DqiA7XTbqQQMpLLjpUGs11MdLnWvhYqJ04CTK7Bm\r\n" + 
			"0OwqtIUYxnwPcfGjoOYI2tFB6xWqp6QkmqcF8NAKf8P5kL6L5mXLpI/+6hqlqiFNzM13AgMBAAEC\r\n" + 
			"gYBgx0ikJpJUH/j7caiD55BtrCkTB/yKcS9EHBgpZ9TQ5fi5paKRxZG1PD5REhnEWELw3R5YA1Gt\r\n" + 
			"Vyr8cHwzP309GaQVrdrmp5/NnnbuR9Eq7uw9CM+Qovs1Elg77DMh68PNoCbunDsrcOM03+Qm56EL\r\n" + 
			"ZqilosDyuf+T/uTMkK/OAQJBAM6Cg1c9xrKzcc/vf8c0dnfslSWGJSrA+0vwVJ2Tpb3zO/K4q9OT\r\n" + 
			"MTlde5QAvDAyBzcebHYcTgtN5wqq5bcLU8ECQQC58lmkx2kn5h9i2OtMFuKgdB8xDMvlOZhrOZ+n\r\n" + 
			"+Na2qyVr9fO4Zs4koy54t82FdxvVl5YSSifgRVi9Wzy31Y83AkBbndVNGBAV6bxdZsCGjQTd8Wy9\r\n" + 
			"yASnMhSKvSWc/wrx+X4oEbvRUqTs8UdJAwZ6T0eaMXom8CnDpB0TQ3xEN9dBAkBdGAtvZvKrqheu\r\n" + 
			"mmF7L734jQqMuRZfxe0cSbY4F2oP/DF5EqMZgEbWquf6QjNgDZje38yfjYbXToC2FLaaZw4TAkAG\r\n" + 
			"6rBZ4zdmOfkjRRJEpHKZ6ZKlqXW9oe+vqQPUBmBD6wKeBxE2ztdHhhjL4Jit87dxjXOLtP3DsZ0s\r\n" + 
			"vdKA/Eme";
	
	@Resource
	private UsersService us;
	
	@GetMapping("login")
	public String select(String userName, String userPassword) throws Exception {
		System.out.println("私钥解密前:" + userPassword);
		//获取私钥
		PrivateKey priKey = RSAUtils.getPrivateKey(privateKey);
		userPassword = userPassword.replaceAll(" ", "+");
		//解密
		userPassword = RSAUtils.decrypt(userPassword, priKey);
		System.out.println("私钥解密后:" + userPassword);
		
		//拆分密钥和时间戳
		String time = userPassword.substring(userPassword.lastIndexOf("+") + 1);
		userPassword = userPassword.substring(0, userPassword.lastIndexOf("+"));
		System.out.println("userPassword =" +userPassword);
		System.out.println("time =" +time);
		long timeBefore = Long.parseLong(time);
		//获取当前时间戳
		long timeNow = System.currentTimeMillis();
		System.out.println(timeBefore +" " + timeNow);
		
		Users users = us.selectByUserName(userName);
		
		String str = null;
		if(users != null) {
			//MD5加密
			userPassword = EncUtils.MD5Enc(userPassword);
			if(users.getUserPassword().equals(userPassword)) {
				if((timeNow - timeBefore) < 1000) {
					str = "success";
				}else {
					str = "登录超时";
				}
			}else {
				str = "error";
			}
		}else {
			str = "账号不存在";
		}
		return str;
	}
}

前端发送请求代码

<body>
	<form id="login">
        <input name="userName" id="userName"><br>
        <input  name="userPassword" id="userPassword"><br>
        <input type="button" value="登录" onclick="login()">
    </form>
    <script type="text/javascript">
        function login(){
        	var userName = $("#userName").val();
        	var userPassword = $("#userPassword").val();
        	console.log("公钥加密前:" + userPassword);
        	
        	/* 定义公钥 */
        	var publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCV/9CagD69JnavWTdF6mBFVmAKXxL6DZJszdLY" +
        		"ENgqyNGfK3JsNAojx9ZtUadCPw6ogO1026kEDKSy46VBrNdTHS51r4WKidOAkyuwZtDsKrSFGMZ8" +
        		"D3Hxo6DmCNrRQesVqqekJJqnBfDQCn/D+ZC+i+Zly6SP/uoapaohTczNdwIDAQAB";
        	//密码添加时间戳
            var time = Date.parse(new Date());
            time = time + 1000;
            userPassword = userPassword + "+" + time;
            console.log("userPassword:" + userPassword);
            /* 执行公钥加密 */
       	    var enctype = new JSEncrypt();//创建RSA对象
            enctype.setPublicKey(publicKey);//为RSA对象设置公钥
            userPassword = enctype.encrypt(userPassword);
        	console.log("公钥加密后:" + userPassword);
        	
            $.ajax({
                   url:"/login",
                   type:"get",
                   data:{"userName":userName, "userPassword":userPassword},
                   success:function(data){
                	   alert(data);
	                   if(data == "success"){
	                        location.href="success.html";
	                   }else if(data == "error"){
	                        location.href="error.html";
	                   }
                   }
              });
            }
		}
   </script>
</body>

获取公钥私钥字符串

KeyPair keyPair = RSAUtils.getKeyPair();
String publicKey = RSAUtils.getPublicKeyStr(keyPair);
String privateKey = RSAUtils.getPrivateKeyStr(keyPair);
System.out.println(publicKey);
System.out.println(privateKey);
SpringApplication.run(App.class, args);

RSA加密工具类

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

    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;
    
    //获取公钥字符串
    public static String getPublicKeyStr(KeyPair keyPair){
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        byte[] by = publicKey.getEncoded();
        return Base64.encode(by);
    }
    
   //获取私钥字符串
    public static String getPrivateKeyStr(KeyPair keyPair){
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        byte[] by = privateKey.getEncoded();
        return Base64.encode(by);
    }

    /**
     * 获取密钥对
     *
     * @return 密钥对
     */
    public static KeyPair getKeyPair() {
        KeyPairGenerator generator = null;
        try {
            generator = KeyPairGenerator.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        generator.initialize(1024);
        return generator.generateKeyPair();
    }

    /**
     * 获取私钥
     *
     * @param privateKey 私钥字符串
     * @return
     */
    public static PrivateKey getPrivateKey(String privateKey) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] decodedKey = Base64.decode(privateKey.getBytes());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 获取公钥
     *
     * @param publicKey 公钥字符串
     * @return
     */
    public static PublicKey getPublicKey(String publicKey) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] decodedKey = Base64.decode(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
        return keyFactory.generatePublic(keySpec);
    }

    /**
     * RSA加密
     *
     * @param data 待加密数据
     * @param publicKey 公钥
     * @return
     */
    public static String encrypt(String data, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        int inputLen = data.getBytes().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.getBytes(), offset, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        // 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
        // 加密后的字符串
        return new String(Base64.decode(encryptedData));
    }

    /**
     * RSA解密
     *
     * @param data 待解密数据
     * @param privateKey 私钥
     * @return
     */
    public static String decrypt(String data, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] dataBytes = Base64.decode(data);
        int inputLen = dataBytes.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(dataBytes, offset, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        // 解密后的内容
        return new String(decryptedData, "UTF-8");
    }

    /**
     * 签名
     *
     * @param data 待签名数据
     * @param privateKey 私钥
     * @return 签名
     */
    public static String sign(String data, PrivateKey privateKey) throws Exception {
        byte[] keyBytes = privateKey.getEncoded();
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey key = keyFactory.generatePrivate(keySpec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initSign(key);
        signature.update(data.getBytes());
        return new String(Base64.decode(signature.sign()));
    }

    /**
     * 验签
     *
     * @param srcData 原始字符串
     * @param publicKey 公钥
     * @param sign 签名
     * @return 是否验签通过
     */
    public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
        byte[] keyBytes = publicKey.getEncoded();
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey key = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(key);
        signature.update(srcData.getBytes());
        return signature.verify(Base64.decode(sign.getBytes()));
    }
}
发布了40 篇原创文章 · 获赞 0 · 访问量 339

猜你喜欢

转载自blog.csdn.net/baidu_27414099/article/details/104439764