Java 实现常见的非对称加密算法
作者:布禾 发布时间:2023-11-27 18:51:03
标签:Java,非对称,加密算法
概述
非对称加密算法与对称加密算法的主要差别在于非对称加密算法用于加密和解密的密钥不相同,非对称加密算法密钥分为公钥和私钥,公钥加密只能用私钥解密,反之私钥加密只能用公钥解密。相比对称加密算法,非对称加密算法加/解密效率低,但安全性高,这两种算法一般结合使用。常见非对称加密算法有RSA、ECC、Elgamal等。
使用RSA实现加密解密
公钥加密,私钥解密。
package com.ss.utils;
import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class RsaUtil {
public static final String KEY_TYPE_PRIVATE_KEY = "privateKey";
public static final String KEY_TYPE_PUBLIC_KEY = "publicKey";
/**
* 生成公钥和私钥
*
* @return
* @throws NoSuchAlgorithmException
*/
public static Map<String, String> generateKey() throws NoSuchAlgorithmException {
Map<String, String> resultMap = new HashMap<>();
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
Base64.Encoder encoder = Base64.getEncoder();
resultMap.put(KEY_TYPE_PRIVATE_KEY, encoder.encodeToString(keyPair.getPrivate().getEncoded()));
resultMap.put(KEY_TYPE_PUBLIC_KEY, encoder.encodeToString(keyPair.getPublic().getEncoded()));
return resultMap;
}
/**
* RSA加密
* @param key
* @param content
* @param keyType
* @return
* @throws Exception
*/
public static String rsaEncrypt(String key, String content, String keyType) throws Exception {
return rsa(key, content.getBytes(), keyType, Cipher.ENCRYPT_MODE);
}
/**
* RSA解密
* @param key
* @param content
* @param keyType
* @return
* @throws Exception
*/
public static String rsaDecrypt(String key, String content, String keyType) throws Exception {
return rsa(key, Base64.getDecoder().decode(content), keyType, Cipher.DECRYPT_MODE);
}
private static String rsa(String key, byte[] content, String keyType, int mode) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
if (KEY_TYPE_PRIVATE_KEY.equals(keyType)) {
cipher.init(mode, keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(key))));
} else {
cipher.init(mode, keyFactory.generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(key))));
}
byte[] bytes = cipher.doFinal(content);
return mode == Cipher.DECRYPT_MODE ? new String(bytes) : Base64.getEncoder().encodeToString(bytes);
}
public static void main(String[] args) throws Exception {
String content = "大王叫我来巡山呐";
//生成密钥对
Map<String, String> keyMap = generateKey();
System.out.println("私钥:" + keyMap.get(KEY_TYPE_PRIVATE_KEY));
System.out.println("公钥:" + keyMap.get(KEY_TYPE_PUBLIC_KEY));
//私钥加密,公钥解密
String privateKeyData = rsaEncrypt(keyMap.get(KEY_TYPE_PRIVATE_KEY), content, KEY_TYPE_PRIVATE_KEY);
System.out.println("私钥加密:" + privateKeyData);
System.out.println("公钥解密:" + rsaDecrypt(keyMap.get(KEY_TYPE_PUBLIC_KEY), privateKeyData, KEY_TYPE_PUBLIC_KEY));
//公钥加密,私钥解密
String publicKeyData = rsaEncrypt(keyMap.get(KEY_TYPE_PUBLIC_KEY), content, KEY_TYPE_PUBLIC_KEY);
System.out.println("公钥加密:" + publicKeyData);
System.out.println("私钥解密:" + rsaDecrypt(keyMap.get(KEY_TYPE_PRIVATE_KEY), publicKeyData, KEY_TYPE_PRIVATE_KEY));
}
}
输出
私钥:MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDQPZnj0+/uh5jG0/rqVsXKLve7wTw2LVEwdBhm+SPrLoHYb4+6idNeF4bWgTqNRs2hfewq5cyiwXujT+eqp0g1ebSLWSUWzBsktynQMggxb8IwtnFYzmZX7BSAUudrfTre74RtKS0krYY5PCXCGR/EGbbXMVv1m2S59BrkWEI8c/iORhRAJ5/pqRW/51cIimPx9iTYx/QZC4VsCRi8ZrBaXcJhEi4Y/YzOFhfITID4ATis0Z3yw3FVybKzJo3Nexupcec5qaLBlwuDkY6E4NgQq51bjBCUB78RgXFLdaVtfBu9Vr7pRdqrh7sD//kpiicjiLJvmcLG9egXrkHRlm2TAgMBAAECggEAes75hM0mwOujBA9b+Pu3pedRHp91XRYYvZSaF5ByyG4jEXuprf8+ck05riOEXnEVMFpM/3eK2al1uviSzafeA/uEqHGoV+uDToHe3PPEtTMNuSC/c/o1jUCjTpKV/GRcZcGnvaD9CJZ1hCeetPuQKlxn4j0v2IcOPkRh36zVU0SZJKu5Ltt6iyGbpk6qqlpLnX93Ez5weWLnuolgjF34JBDQpc/zZjHwC8/avE81cJ3dUQR55l9QiwZUoMQ2eDWO1UcPAEqRssNAwEHbQJFSJmqtvg1yuSSvPIGB5ATPlTu7EoOLFMOQm3qoAxX7/FR9uU50wHivyZrRyKV4CdiLcQKBgQDuj6bh1WUQRIBU5ZOtljbs73RdYYbS1uUHubizQ3rqrNo3+TmaVu+7H3DPPI0L21YVpjXuPMUVkix+KA7HiDqULxx0yZMsdqXmggOT2QFEjGdueMFAJw09jAHnCIwuxmn3f94XAvV6N+Hfhjy31RGPQhjFGn6QQ16a3NI46CD6VwKBgQDfdorB9Wm0H6QJ8AYAQuHAiFJnXeOzN0q2407F5kx8XkAKwKaI7ybGZbiYESxFTe0AdVQlYRJbAby1iUW/OGOS+Ia5buzCo+BqrP6RxzLDYVClyXS3WFSLPKko6WIscS+uOF36mWWn34YYH/ktT8B/hUNFUD+PEctkrklONkZZJQKBgQCsn9hTbHYgKmFujV2qa5s9IhzjAZJs+MFsMLD9TuQf8opJnJdZHnWEw0B/RUKPBN0q90XpKaI3dLmrZFMlgWdaGSkPPVm4//YWcZgjIREwyCSEJO85+8gx9CDgTCgcJMlDJgzQO/zjvpI8i8deAtkc/+gqoHxa6dUIXKfmM9rBKwKBgFxIv0sUh5+8hWkZN9E5zbNOWQGZM6Tai791ph1yW1ntLnOCVgQtB41dits6FFdWtC7BRYveR89Pq1gpJaWvqueSPUktNxe2x8ImSUd4xU0Mzlp5FPt2vgt2dMGRiFqkL7W6T41jdija1az231fIHM5NAZgJaQYzqhSdKWbkYS8FAoGBAOciP4bEln64PnvuZtYnZNvt/5PHB4ssZ3S1WExyTtI7328ZKAsi3F7PjxCh7gviXfEI2t3AcVwpPaJYveL3Zg/jl2x6zNSLDW8kgNhAJE221u3pZefeidvIWwki/OXWtRqyoACteLnEb6lbM3tKdltWZOryQTiXqGdTluLEQLE0
公钥:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0D2Z49Pv7oeYxtP66lbFyi73u8E8Ni1RMHQYZvkj6y6B2G+PuonTXheG1oE6jUbNoX3sKuXMosF7o0/nqqdINXm0i1klFswbJLcp0DIIMW/CMLZxWM5mV+wUgFLna3063u+EbSktJK2GOTwlwhkfxBm21zFb9ZtkufQa5FhCPHP4jkYUQCef6akVv+dXCIpj8fYk2Mf0GQuFbAkYvGawWl3CYRIuGP2MzhYXyEyA+AE4rNGd8sNxVcmysyaNzXsbqXHnOamiwZcLg5GOhODYEKudW4wQlAe/EYFxS3WlbXwbvVa+6UXaq4e7A//5KYonI4iyb5nCxvXoF65B0ZZtkwIDAQAB
私钥加密:V9kG4o3nceI4a19t/V5431v9Ek1PiV3FZokfnRNBor/RBymwDX4rsGNHEYuyN6/sbbD56r3ij5tUpShXFlcHrzVH4IfD4ySbvNNeMs2FrZLF3zvQmwRKDPH6SJ0DEczi5N97Vfh4b2tfyLT8iX3t9LPWgEj5mB7MXiYPc56mza+ZAqDduxWWsm6Emm81uKn97wZnasg8zXlDbhRttVTWhszbDhrFqsgd2sb8ZZUZIuiGTaIg7U6Slc5x9uS3UVACXXVyMCmxiVutQtg3Z4kt80ruh7xO0hl4cWk6P2Tg0ncaIQn/5vKsO2UXr/EsCb2rchWN3ZBHTVyQ83v/EHDtQw==
公钥解密:大王叫我来巡山呐
公钥加密:aartOyClfEIz1JT5nghpTbXxLZEOovm+vwvg+u3Tw8t5LOF+C7Gg/uxUP8Hm5jEkN6JfBHaMWTKg0RQ2xf3CCuXcLIpYVCOUwADwd05E8guEfZBT8FIp8jghCz2j+lAIiTfGZvsK9qUdZEmwTAEjV6uP4avF6njriglGJ4KhcYXEO66tOJWe2nQ1hyYXEHS43h9F0dtlWDjF6Xr6wdmUALnhprHDwKPdT/1T8p7+M5Fz7fUC7TJulBHWCSZvhgl405PvN+iTv7VysBJKRPks1JnmMe6BxFyhxXZfNRHmUyQvTMSfWt/A5gOy8ao/SOwWv0QMSh5NbocSd/tpjn27kw==
私钥解密:大王叫我来巡山呐
使用RSA实现数字签名
私钥签名,公钥验证。
package com.ss.utils;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class SignatureUtil {
public static final String KEY_TYPE_PRIVATE_KEY = "privateKey";
public static final String KEY_TYPE_PUBLIC_KEY = "publicKey";
/**
* 生成公钥和私钥
*
* @return
* @throws NoSuchAlgorithmException
*/
public static Map<String, String> generateKey() throws NoSuchAlgorithmException {
Map<String, String> resultMap = new HashMap<>();
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
Base64.Encoder encoder = Base64.getEncoder();
resultMap.put(KEY_TYPE_PRIVATE_KEY, encoder.encodeToString(keyPair.getPrivate().getEncoded()));
resultMap.put(KEY_TYPE_PUBLIC_KEY, encoder.encodeToString(keyPair.getPublic().getEncoded()));
return resultMap;
}
/**
* 私钥签名
* @param privateKeyStr
* @param content
* @return
* @throws Exception
*/
public static String generateSignature(String privateKeyStr, String content) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Signature signature = Signature.getInstance("SHA1withRSA");
PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyStr)));
signature.initSign(privateKey);
signature.update(content.getBytes());
return Base64.getEncoder().encodeToString(signature.sign());
}
/**
* 公钥验证
* @param publicKeyStr
* @param content
* @param sign
* @return
* @throws Exception
*/
public static boolean verifySignature(String publicKeyStr, String content, String sign) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Signature signature = Signature.getInstance("SHA1withRSA");
PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyStr)));
signature.initVerify(publicKey);
signature.update(content.getBytes());
return signature.verify(Base64.getDecoder().decode(sign));
}
public static void main(String[] args) throws Exception {
String content = "大王叫我来巡山呐";
//生成密钥对
Map<String, String> keyMap = generateKey();
//私钥签名
String sign = generateSignature(keyMap.get(KEY_TYPE_PRIVATE_KEY), content);
System.out.println("私钥签名:" + sign);
//公钥验证
boolean verifyResult = verifySignature(keyMap.get(KEY_TYPE_PUBLIC_KEY), content, sign);
System.out.println("公钥验证:" + verifyResult);
//将内容做下修改,再进行公钥验证
boolean verifyResult2 = verifySignature(keyMap.get(KEY_TYPE_PUBLIC_KEY), content + "啦啦啦啦", sign);
System.out.println("公钥验证:" + verifyResult2);
}
}
输出
私钥签名:XDWeOUVZhXNPl58mcmRK8ht9TAhnREc+NlnSs2b6PCJuj29ABuoXsjZeJqSspGw8hm9ckHVSTrUt8pX4BFBFzrINDRBsx3TdLp2L8nMkhjFUfo0qcyZo8ReEGFCNr0ergkq2W1Me/5W40GrQz4cJcQ4KV/QWzD8YHWcnDvKg9Q0nXJSngyhJTzUB8o/pgo/tmkA9+bWW212UD9nzEXu5aoPEcYyoo3iFWRX5o9Jgg6ZF+exmWizwZHkg4eD1zC5IN3m4yRS6GRbnZInEuDsOMp9W7HouDLUirkFZiSkyW+DVto+L6CE5eNBrWC52zxiNkVBlkyYKOatSpcrQrtnyiQ==
公钥验证:true
公钥验证:false
来源:https://www.cnblogs.com/seve/p/13992587.html


猜你喜欢
- 最近帮朋友做了一个动画菜单,感觉有一定的实用价值,就在此给大家分享一下,先看看效果:实现思路:从图中可以看出,这三个(或更多,需要自己再实现
- 说明在学习jvm相关知识时,一般会讲到类字节码相关内容,为了更清晰的了解类字码具体内容,一般我们会使用javap命令进行查看,但是仍然不够直
- 员工管理系统要求如下:通过面向对象的编程思想,实现员工信息的增删改查,存储结构为数组。限定数组长度为100。实现页面:添加员工查找员工修改员
- 本文实例讲述了Android编程实现禁止系统锁屏与解锁亮屏的方法。分享给大家供大家参考,具体如下:需求:某个时刻任务执行完毕,关闭屏幕,某时
- 很多时候在进行C#项目的实际开发中,会需要根据条件来设置节点不可勾选,查看DevExpress文档发现通过其CustomDrawNodeCh
- 在一些音乐类应用中, 经常会展示随着节奏上下起伏的波纹信息, 这些波纹形象地传达了声音信息, 可以提升用户体验, 那么是如何实现的呢? 可以
- 同学们应该都去麦当劳或肯德基吃过快餐吧?请同学们参考肯德基官网的信息模拟肯德基快餐店的收银系统,合理使用C++/python/Java,结合
- 前言OpenCVSharp是OpenCV的.NET wrapper,是一名日本工程师开发的,项目地址为:https://github.com
- 研究其父类时候发现,可以设置这么一条属性,在AlertDialog.Builder.create()之后才能调用这两个方法方法一:setCa
- 分类1.简单工厂模式2.工厂方法模式3.抽象工厂模式案例需求根据蛋糕的不同口味,分别创建苹果味和香蕉味的蛋糕实例方案一:简单工厂模式定义蛋糕
- java导出Excel通用方法的实例详解Java导出Excel通用方法,只需要一个list 集合。通用方法改进之处踊跃提出package o
- 使用 WebView 时,我们通常会重写以下方法:shouldOverrideUrlLoading() onPageStarted()onP
- package com.happyelements.athene.game.util;import static com.google.co
- 主要目的是按后退键的时候,让程序能够退出。 实现起来的思路: 1.捕获到后退键事件就触发。@Override public bo
- 最近一直都在学习Java,发现目前Java招聘中,mybatis出现的频率挺高的,可能是目前Java开发中使用比较多的数据库ORM框架。于是
- //去title requestWindowFeature(Window.FEATURE_NO_TITLE); //隐藏状态栏 getWin
- 如果项目需求是从某些复杂的json里面取值进行计算,用jsonpath+IK(ik-expression)来处理十分方便,jsonpath用
- 结构体概念在C#中,结构体是值类型,一般适用于表示类似Point、Rectangle、Color的对象值类型能够降低对堆的管理、使用。降低垃
- Spring p和c标签注入方式1.编写实体类package com.ming04.pojo;import lombok.AllArgsCo
- 在android开发中,我们时常会遇到对字符串中某些固定的字段实现可点击和颜色的设置,现粘贴处我在开发中如何设置这些属性的。代码如下:pri