| # 如果小明用自己的私钥加密了一条消息,比如小明喜欢小红,然后他公开了加密消息,由于任何人都可以用小明的公钥解密,从而使得任何人都可以确认小明喜欢小红这条消息肯定是小明发出的,其他人不能伪造这个消息,小明也不能抵赖这条消息不是自己写的 |
| # 私钥加密得到的密文实际上就是数字签名,要验证这个签名是否正确,只能用私钥持有者的公钥进行解密验证。使用数字签名的目的是为了确认某个信息确实是由某个发送方发送的,任何人都不可能伪造消息,并且,发送方也不能抵赖 |
| |
| import java.math.BigInteger; |
| import java.nio.charset.StandardCharsets; |
| import java.security.*; |
| |
| public class Main { |
| public static void main(String[] args) throws GeneralSecurityException { |
| |
| KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA"); |
| kpGen.initialize(1024); |
| KeyPair kp = kpGen.generateKeyPair(); |
| PrivateKey sk = kp.getPrivate(); |
| PublicKey pk = kp.getPublic(); |
| |
| |
| byte[] message = "Hello, I am Bob!".getBytes(StandardCharsets.UTF_8); |
| |
| |
| Signature s = Signature.getInstance("SHA1withRSA"); |
| s.initSign(sk); |
| s.update(message); |
| byte[] signed = s.sign(); |
| System.out.println(String.format("signature: %x", new BigInteger(1, signed))); |
| |
| |
| Signature v = Signature.getInstance("SHA1withRSA"); |
| v.initVerify(pk); |
| v.update(message); |
| boolean valid = v.verify(signed); |
| System.out.println("valid? " + valid); |
| } |
| } |
| |
| # 控制台 |
| signature: 2ae58de22ae68ec52bb5440895bc132b162ef3de8ac487128aaf5f4553d2696f85091ce27eb22505ebd03ecdd32e24ee51f925dcf097dd5360a875a406e96011ae9c336bd9b140f2be48b7f09d23f443ff469c6db12935e046ca668e8c9e1eb03db9327261d71274d4a7977aa68b0fcf03c5a1d653cc8d630d40051ff23e0127 |
| valid? true |
| # 创建证书 |
| keytool -storepass 123456 -genkeypair -keyalg RSA -keysize 1024 -sigalg SHA1withRSA -validity 3650 -alias mycert -keystore my.keystore -dname "CN=www.sample.com, OU=sample, O=sample, L=BJ, ST=BJ, C=CN" |
| |
| keyalg:指定RSA加密算法; |
| sigalg:指定SHA1withRSA签名算法; |
| validity:指定证书有效期3650天; |
| alias:指定证书在程序中引用的名称; |
| dname:最重要的CN=www.sample.com指定了Common Name,如果证书用在HTTPS中,这个名称必须与域名完全一致 |
| |
| 执行上述命令,JDK会在当前目录创建一个my.keystore文件,并存储创建成功的一个私钥和一个证书,它的别名是mycert |
| |
| # 将数字证书放到项目的src路径下 |
| |
| import java.io.InputStream; |
| import java.math.BigInteger; |
| import java.security.*; |
| import java.security.cert.*; |
| import javax.crypto.Cipher; |
| |
| public class Main { |
| public static void main(String[] args) throws Exception { |
| byte[] message = "Hello, use X.509 cert!".getBytes("UTF-8"); |
| |
| KeyStore ks = loadKeyStore("/my.keystore", "123456"); |
| |
| PrivateKey privateKey = (PrivateKey) ks.getKey("mycert", "123456".toCharArray()); |
| |
| X509Certificate certificate = (X509Certificate) ks.getCertificate("mycert"); |
| |
| byte[] encrypted = encrypt(certificate, message); |
| System.out.println(String.format("encrypted: %x", new BigInteger(1, encrypted))); |
| |
| byte[] decrypted = decrypt(privateKey, encrypted); |
| System.out.println("decrypted: " + new String(decrypted, "UTF-8")); |
| |
| byte[] sign = sign(privateKey, certificate, message); |
| System.out.println(String.format("signature: %x", new BigInteger(1, sign))); |
| |
| boolean verified = verify(certificate, message, sign); |
| System.out.println("verify: " + verified); |
| } |
| |
| static KeyStore loadKeyStore(String keyStoreFile, String password) { |
| try (InputStream input = Main.class.getResourceAsStream(keyStoreFile)) { |
| if (input == null) { |
| throw new RuntimeException("file not found in classpath: " + keyStoreFile); |
| } |
| KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); |
| ks.load(input, password.toCharArray()); |
| return ks; |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| static byte[] encrypt(X509Certificate certificate, byte[] message) throws GeneralSecurityException { |
| Cipher cipher = Cipher.getInstance(certificate.getPublicKey().getAlgorithm()); |
| cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey()); |
| return cipher.doFinal(message); |
| } |
| |
| static byte[] decrypt(PrivateKey privateKey, byte[] data) throws GeneralSecurityException { |
| Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm()); |
| cipher.init(Cipher.DECRYPT_MODE, privateKey); |
| return cipher.doFinal(data); |
| } |
| |
| static byte[] sign(PrivateKey privateKey, X509Certificate certificate, byte[] message) |
| throws GeneralSecurityException { |
| Signature signature = Signature.getInstance(certificate.getSigAlgName()); |
| signature.initSign(privateKey); |
| signature.update(message); |
| return signature.sign(); |
| } |
| |
| static boolean verify(X509Certificate certificate, byte[] message, byte[] sig) throws GeneralSecurityException { |
| Signature signature = Signature.getInstance(certificate.getSigAlgName()); |
| signature.initVerify(certificate); |
| signature.update(message); |
| return signature.verify(sig); |
| } |
| } |
| |
| # 控制台 |
| encrypted: 84331667f208bb711abe72d00fa1a9af4b03393cc0bcd53902731c9159cfd2c59f297433d845fb46ff2674064e58b7101502adcc181551f952db973fc6a69d9b214cdb5e443cdac9f1e9a36aa37c5051a9b6f7f929fd6a9aa3c0d4f90046dcf2aed20d8c9aa7efbd8dcfedd960628025ba5587d7dbc39650b75b3b22203ab555 |
| decrypted: Hello, use X.509 cert! |
| signature: 43a8a2cf36a0e398a829806d235a192ff6f6634219d661e87539d365876ab7d14e39534bf3a834b06790c04a34f5d6b0e6476c8ddea54c04b380449f1efa3c71aaccfba7ba7241f91bcf81881a95affa9bd098fa15044da4e95d452914976b2b8be7825491404905ba1a4128cb72ec7611750b7d6b7fd99118bc7aba98bb3beb |
| verify: true |
| |
| 浏览器和服务器建立安全连接: |
| 浏览器向服务器发起请求,服务器向浏览器发送自己的数字证书; |
| 浏览器用操作系统内置的Root CA来验证服务器的证书是否有效,如果有效,就使用该证书加密一个随机的AES口令并发送给服务器; |
| 服务器用自己的私钥解密获得AES口令,并在后续通讯中使用AES加密。 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2021-05-07 vue2.0入门