1.背景
有个需求 需要在java 使用 非对称加密 RS256 算法,网上博客都翻篇了,基本都是赋值粘贴,没有个是可用的,80%都是粘贴了一篇 c#语言写的代码,
什么风气?以前的博客氛围哪里去了?不开心,我要的是 java ,java ,java !
经过两天测试,终于琢磨透了,但是与网上的介绍却有点出入,
网上的解说是: 说法一:RS256 是公钥加密,私钥解密; 说法二:RS256 是私钥加密。公钥解密,因此只需要保存好私钥即可
可是我的实验结果都推翻了上面的说明,我的结论是
私钥加密得到签名密钥,公钥用来对签名密钥和原始数据做校验是否被篡改过,以达到中途防止被抓包的风险,那么公私钥都不可泄露
2.心得总结
这是私钥加密,公钥验证,发送方保存私钥,接收方保存公钥; 发送方使用私钥加密原始数据后,将得出签名密钥,于是将签名密钥和原始数据一起传给接收方; 接收方得到签名密钥和原始数据后,使用公钥对签名密钥和原始数据做校验是否一致,以确保数据传输过程中没有被抓包, 即便别人得到了传输数据,因为没有私钥,因此无法获取新的密钥签名,密钥签名和原始数据必须一致,因此达到数据无法伪造的效果
类似于https,https是传输中途所有数据乱码加密,到达服务器根据协议解密,而RS256非对称加密是中途不加密,只在发送方根据私钥 对发送的原始数据计算出一个签名密钥,然后与原始数据一起传输到接收方,中途数据是明文的,到达接收方使用公钥验证数据是否被篡改过,检验通过才处理, 当然可以配置https协议一起使用,双重保险
依赖只需要引入jdk 的rt.jar即可,是jdk的基础依赖包
3.完整的java代码
package cn.cenxi.appapi.goods.controller; import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import java.util.HashMap; import java.util.Map; /** * 这是私钥加密,公钥验证,发送方保存私钥,接收方保存公钥; * 发送方使用私钥加密原始数据后,将得出签名密钥,于是将签名密钥和原始数据一起传给接收方; * 接收方得到签名密钥和原始数据后,使用公钥对签名密钥和原始数据做校验是否一致,以确保数据传输过程中没有被抓包, * 即便别人得到了传输数据,因为没有私钥,因此无法获取新的密钥签名,密钥签名和原始数据必须一致,因此达到数据无法伪造的效果 * <p> * 类似于https,https是传输中途所有数据乱码加密,到达服务器根据协议解密,而RS256非对称加密是中途不加密,只在发送方根据私钥 * 对发送的原始数据计算出一个签名密钥,然后与原始数据一起传输到接收方,中途数据是明文的,到达接收方使用公钥验证数据是否被篡改过,检验通过才处理, * 当然可以配置https协议一起使用,双重保险 */ public class mk { //实例密钥对生成器的加密算法键名【非对称加密】 private static final String KEY_ALGORITHM = "RSA"; //密钥长度 private static final int KEY_SIZE = 1024; //实例签名工厂的算法键名【非对称加密】 public static final String SIGNATURE_ALGORITHM = "SHA256withRSA"; //公钥key名 private static final String PUBLIC_KEY = "publicKey"; //私钥key名 private static final String PRIVATE_KEY = "privateKey"; /** * 生成公、私钥 * 根据需要返回String或byte[]类型 */ private static Map<String, String> createRSAKeys() throws NoSuchAlgorithmException { //密钥对生成器 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); //初始化配置,参数:密钥长度,安全随机数 keyPairGenerator.initialize(KEY_SIZE, new SecureRandom()); //生产公钥私钥键值对 KeyPair keyPair = keyPairGenerator.generateKeyPair(); //获取公钥 PublicKey publicKey = keyPair.getPublic(); //获取私钥 PrivateKey privateKey = keyPair.getPrivate(); //将公钥转为字符串【方便存储】 String publicKeyValue = Base64.getEncoder().encodeToString(publicKey.getEncoded()); //将私钥转为字符串【方便存储】 String privateKeyValue = Base64.getEncoder().encodeToString(privateKey.getEncoded()); //存入map返回 Map<String, String> map = new HashMap<>(); map.put(PUBLIC_KEY, publicKeyValue); map.put(PRIVATE_KEY, privateKeyValue); return map; } /** * 将公钥字符串恢复为公钥对象 */ public static PublicKey getPublicKey(String key) throws NoSuchAlgorithmException, InvalidKeySpecException { byte[] byteKey = Base64.getDecoder().decode(key); X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteKey); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); return keyFactory.generatePublic(x509EncodedKeySpec); } /** * 将私钥字符串恢复为私钥对象 */ public static PrivateKey getPrivateKey(String key) throws NoSuchAlgorithmException, InvalidKeySpecException { byte[] byteKey = Base64.getDecoder().decode(key); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(byteKey); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); return keyFactory.generatePrivate(pkcs8EncodedKeySpec); } /** * 签名 * * @param key 私钥字符串 * @param requestData 原始数据 */ public static String sign(String key, String requestData) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { //将私钥字符串恢复为私钥对象 PrivateKey privateKey = getPrivateKey(key); //实例加密工厂对象 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); //设置私钥 signature.initSign(privateKey); //设置原始数据 signature.update(requestData.getBytes()); //执行,获取签名密钥 byte[] signed = signature.sign(); //将签名密钥转字符串 return Base64.getEncoder().encodeToString(signed); } /** * 验签 * * @param key 公钥字符串 * @param requestData 原始数据 * @param signstr 签名密钥 */ public static boolean verifySign(String key, String requestData, String signstr) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { //将公钥字符串恢复为公钥对象 PublicKey publicKey = getPublicKey(key); //实例加密工厂对象 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); //设置验证公钥 signature.initVerify(publicKey); //设置原始数据 signature.update(requestData.getBytes()); //设置签名密钥后做校验,返回校验结果,true为通过,false为失败 return signature.verify(Base64.getDecoder().decode(signstr)); } /** * 测试 */ public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, InvalidKeyException { //生成随机公、私钥 Map<String, String> keyPairMap = createRSAKeys(); String privateKeyStr = keyPairMap.get(PRIVATE_KEY); System.out.println("生成随机私钥: " + privateKeyStr); String publicKeyStr = keyPairMap.get(PUBLIC_KEY); System.out.println("生成随机公钥: " + publicKeyStr); System.out.println("===开始RSA公、私钥测试==="); String str = "你大爷撒娇打啥电话手机卡"; //私钥加密得出签名密钥 String sign = sign(privateKeyStr, str); System.out.println("===签名密钥字符串:" + sign); //公钥验证是否被篡改 boolean res = verifySign(publicKeyStr, str, sign); System.out.println("===验签结果:" + res); } }View Code
4.测试
标签:公钥,私钥,String,签名,RS256,java,原始数据,加密算法,密钥 From: https://www.cnblogs.com/c2g5201314/p/16582926.html