打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
RSA加密---从后台到客户端实现报文加解密

RSA是当前最流行的非对称加密方式,使用公钥加密使用密钥解密,如何妥善的保管密钥就成了关键。

动态生成密钥

工具类

package com.yitong.utils;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.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import javax.crypto.Cipher;/** * RSA工具类 */public class RSAUtil {    /**     * @description: 随机生成RSA密钥对(密钥默认长度为1024)     * @params:     * @return:     */    public static KeyPair getRSAKeyPair() {        try {            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");            kpg.initialize(1024);            return kpg.genKeyPair();        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        }        return null;    }    /**     * @description: 随机生成RSA密钥对     * @params:     * @return:     */    public static KeyPair getRSAKeyPair(int length) {        try {            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");            kpg.initialize(length);            return kpg.genKeyPair();        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        }        return null;    }    /**     * @description: 用公钥加密     * @params:     * @return: String     */    public static String encryptData(String data, PublicKey publicKey) {        try {            Cipher cipher = Cipher.getInstance("RSA");            cipher.init(Cipher.ENCRYPT_MODE, publicKey);            return HexUtil.encode(cipher.doFinal(data.getBytes()));        } catch (Exception e) {            e.printStackTrace();        }        return null;    }    /**     * @description: 用私钥解密     * @params:     * @return: String     */    public static String decryptData(String encryptedData, PrivateKey privateKey) {        try {            Cipher cipher = Cipher.getInstance("RSA");            cipher.init(Cipher.DECRYPT_MODE, privateKey);            return new String(cipher.doFinal(HexUtil.decode(encryptedData)));        } catch (Exception e) {            e.printStackTrace();        }        return null;    }    /**     * @description: 字符串还原公钥     * @params:     * @return: PublicKey     */    public static PublicKey getPublicKey(String key) {        try {            byte[] keyBytes;            keyBytes = Base64Util.decode(key);            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);            KeyFactory keyFactory = null;            keyFactory = KeyFactory.getInstance("RSA");            PublicKey publicKey = keyFactory.generatePublic(keySpec);            return publicKey;        } catch (Exception e) {            e.printStackTrace();        }        return null;    }    /**     * @description: 字符串还原公钥Base64     * @params:     * @return: String     */    public static String getPublicKey(PublicKey publicKey) {        return Base64Util.encode(publicKey.getEncoded());    }    /**     * @description: 字符串还原私钥     * @params:     * @return: PrivateKey     */    public static PrivateKey getPrivateKey(String key) {        try {            byte[] keyBytes;            keyBytes = Base64Util.decode(key);            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);            KeyFactory keyFactory = null;            keyFactory = KeyFactory.getInstance("RSA");            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);            return privateKey;        } catch (Exception e) {            e.printStackTrace();        }        return null;    }    /**     * @description: 字符串还原私钥Base64     * @params:     * @return: String     */    public static String getPrivateKey(PrivateKey privateKey) {        return Base64Util.encode(privateKey.getEncoded());    }}

使用

    static String plainText = "123456789123456789";// 明文	static String cipherText;// 密文	static PublicKey publicKey;	static PrivateKey privateKey;    private static void RSAEncrypt() {		if (null == publicKey) {			KeyPair aKey = RSAUtil.getRSAKeyPair();			publicKey = aKey.getPublic();			privateKey = aKey.getPrivate();			String pString = RSAUtil.getPublicKey(publicKey);			String pString2 = RSAUtil.getPrivateKey(privateKey);			System.out.println("公钥:"   pString   "\n私钥:"   pString2);		}		for (int i = 0; i < 5; i  ) {			cipherText = RSAUtil.encryptData(plainText, publicKey);			System.out.println("加密密文:"   cipherText);			try {				System.out.println("解密明文:"   RSAUtil.decryptData(cipherText, privateKey));			} catch (Exception e) {				// TODO Auto-generated catch block				e.printStackTrace();			}		}	}

这个是动态生成一对密钥的用法,这里存在一个问题,自己生成的一对密钥别人不知道,除了自己任何人都没有办法解密,我们一般都是自己加密给别人解密,这样就得想办法把私钥传给别人,但存在泄露的风险。

利用证书和keystore方式加解密

这种方式是为了解决传递密钥存在泄露风险的问题,keystore拥有完整的一对密钥,既包含公钥也包含私钥,证书只包含公钥,只能利用证书进行加密。

利用keytool生成证书

以win系统为例,打开cmd,输入:
keytool -genkey -alias 你的证书别名 -keyalg 密钥算法 -keystore 证书库文件保存的位置和文件名 -keysize 密钥长度 -validity 证书有效期天数
示例:
keytool -genkey -alias mykey -keyalg RSA -keystore D:/mk.keystore -keysize 1024 -validity 36500
然后按照提示输入密钥库的相关信息:

输入密钥库口令:再次输入新口令:您的名字与姓氏是什么?  [Unknown]:  zhang您的组织单位名称是什么?  [Unknown]:  pc您的组织名称是什么?  [Unknown]:  pc您所在的城市或区域名称是什么?  [Unknown]:  shanghai您所在的省/市/自治区名称是什么?  [Unknown]:  shanghai该单位的双字母国家/地区代码是什么?  [Unknown]:  86CN=zhang, OU=yitong, O=pc, L=shanghai, ST=shanghai, C=86是否正确?  [否]:  是输入 <mykey> 的密钥口令        (如果和密钥库口令相同, 按回车):再次输入新口令:Warning:JKS 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore D:/mk.keystore -destkeystore D:/mk.keystore -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。

这样就在D盘根目录下生成一个密钥库,这个密钥库相当重要一定要妥善保管,接下来就需要生成证书了:

keytool -export -alias mykey -keystore D:/mk.keystore -file D:/mk.cer

这样就能再D盘根目录下看到证书文件了,我们可以根据需要在原有的密钥库添加新的密钥。

加解密

直接上代码:

    static String plainText = "123456789123456789";// 明文	static String cipherText;// 密文	static PublicKey publicKey;	static PrivateKey privateKey;	static String certificatePath = "D:/mk.cer";	static String keystorePath = "D:/mk.keystore";    private static void CerEncrypt() throws Exception {		// 加密		CertificateFactory cff = CertificateFactory.getInstance("X.509");		InputStream in = new FileInputStream(certificatePath);		Certificate cf = cff.generateCertificate(in);		PublicKey pString = cf.getPublicKey(); // 得到证书文件携带的公钥		System.out.println("公钥:"   Base64Util.encode(pString.getEncoded()));		cipherText = RSAUtil.encryptData(plainText, pString);		System.out.println("加密密文:"   cipherText);		// 解密		FileInputStream inputStream = new FileInputStream(keystorePath);		KeyStore ks = KeyStore.getInstance("JKS");		ks.load(inputStream, "000000".toCharArray());		inputStream.close();		String alias = "mykey";		String pswd = "000000";		Certificate cert = ks.getCertificate(alias);		PublicKey publicKey = cert.getPublicKey();		PrivateKey privateKey = (PrivateKey) ks.getKey(alias, pswd.toCharArray());		System.out.println("私钥:"   RSAUtil.getPrivateKey(privateKey)   "\n公钥:"   RSAUtil.getPublicKey(publicKey));		System.out.println(RSAUtil.decryptData(cipherText, privateKey));	}

应用

当我们的报文需要RSA加密的时候就可以将证书放在客户端,keystore放在服务端,这样客户端发送的报文就能自行加密,在服务端利用keystone文件获取私钥进行解密。

来源:https://www.icode9.com/content-4-276251.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
公钥,私钥和数字签名这样最好理解
从PFX文件中获取私钥、公钥证书、公钥
程序员必备基础:加签验签
非对称加密算法---加密学习笔记(四)
RSA加密解密及数字签名Java实现
Java加密技术之RSA
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服