使用java进行SSL证书的签名与签验
一、签名与签验的含义
签名:客户端使用私钥对字符串加密,得到一个加密后的字符串
签验(签名验证):服务端使用公钥对字符串加密,验证加密后的字符串是否和客户端签名后一样
二、创建私钥、证书等文件
在linux中执行一下命令,生成所需的各个文件
1.手动生成私钥pri.key
openssl genrsa -des3 -passout pass:123456 -out pri.key 20482.生成pkcs8
openssl pkcs8 -topk8 -in pri.key -out pkcs8.pem -nocrypt -passin pass:1234563.生成pkcs10申请书P10.key //C国家,ST省,L市,O组织,OU部门,CN域名或ip
openssl req -new -key pri.key -passin pass:123456 -out P10.key -subj "/C=CN/ST=GUANGZHOU/L=GUANGZHOU/O=A/OU=B/CN=xxx"4.生成公钥pub.key
openssl rsa -in pri.key -passin pass:123456 -pubout -out pub.key5.生成证书server.crt
openssl x509 -req -days 365 -in P10.key -signkey pri.key -passin pass:123456 -out server.crt6.生成pk12文件
openssl pkcs12 -export -in server.crt -inkey pri.key -passin pass:123456 -passout pass:123456 -out tomcat.p127.生成keystore文件
keytool -importkeystore -v -srckeystore tomcat.p12 -srcstoretype pkcs12 -srcstorepass 123456 -destkeystore tomcat.keystore -deststoretype jks -deststorepass 123456
以上生成的文件,我们需要用到pkcs8和server.crt
生成后的pkcs8内容如下
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC7Uv7cOJ0oCsKV
Ous6SL9GcYUlfuuZUJfJVggCYU6peL53ZKv/DzP6FSQMO8W+VRFT+nBDpLntsMBd
mnH2hP0Jz/06d8RCJhRQxn2l8/4lqAZwFhyWvd+r4bkp6nfnY4sk0/ymtC2tp31l
WgTjXKIVtMfO9Km0bNxPIV206YdC9G9IIR65NSx8AyOCmwOp3mc028+9HE/OnT5s
mw2mJB5txVUUeVZYcOq0jaNs5Z/cwzOLuaZEcTPxLHoUAbJ0cDncO6j55/8r+zZg
hkois20k4kGVDUSYKeTH2MGKc62PJVyWRYgaaE+MuU+3tGgGW+/QWR/qShpOj/VA
QDSCVM1BAgMBAAECggEBAI8T6Hg6gccY2OD03MBq2jYq9QDbvYYf6Z+tp3Zx7oxB
HnHBIiIx8YhdZ2g0q2giP5b+HYt9IUpsi7GzCsK5dzBsfcWPvwarYS8FPOlpwL/w
Y+Ju8S0uH86AHVbnsOe6v4fEpyCJVK5j1MJ6DGvA0Eh2CXuIoqqdz3RdTt6k1FyN
Wmr5xYwVq/fnG7HECWpLT1RiZZjqqU7YHlJhdRfIHLEFxsuTrBeEcl2iAt6OTYgw
4QIVJ7DQ5n7cGd2nBgodM081dA8zNrJ5833alPI04pLiu7zNM4fewZuS1ThlnG2G
rJl07IeLjZSwz9dX6Ior/xihOkOqrOqf2rQgnXJQaLECgYEA38k6ijgdGizsXWhU
qeo1TY9XzTF7kh6FWFGNsBtlPC+UmOotkF590ApitZbVnVMg1h4ruruM5Z96K/w2
jL2WahwKjTH2pT1VmsPwXra5RgWPQTEH86VD8DQvYGoIxrqaD8zlgCZuCaj6BCNZ
k6jtsV+zsK2lUUNvoVDHzm7yymUCgYEA1kobLTlu469rSE4P8KP768TWE74mQrRw
LxUTKuUnI4jr3QmMLYMDATS6pRbeUKi/KryKuZB3zqZ0qQYuUAnWVOvwjQ0qsm87
+Y9ZivGtggSGP1fpJUnuA0svvWu+u+qjB3AUO+kdXaTKMNjRySYwk2yRjmiGCTRN
N+eeUT79+60CgYEA2j9bGy/MmhmTzykP4MJsh56zh4eptwCTFWY747NkEMVqi5Nf
KnwtATcPu39GB2/qB0hXZ36/07WrpbgMz0eaqRN96uP+YnqlwRE0nHphyHtlkbOq
yKC12E5cog/nTUDxPVWbwVY5XKxyYJTFKK/IWIM4MKe5Ib694Lpyks47dM0CgYAI
89uizg118bQ3txsvYIp71SNke8M5cjRloynD1wMFlwjTmTyEAj8z47IQh54OHJ6v
+GSLUB/RQF8LWLjCm0abEahhHDW2crM8v+JrzaEEF5BMQS36YtZQyOlbro6vZyQc
gXA2+IxDh0jzNXu+PZw17IlAO9mttMOtHD4fAtS1mQKBgQCg3fuw4KyZcw4XaCCN
KlAYJhnQ5Xk79XL6xAjRyKsSG7GfE1V4tvgkHnoxnAAIPeIqxqACi/VhGXSyxH2/
cfHuXtbdcPJ5XfBnloHOZX7PLEB70SIjxy2/L1lPJUh7e7onc9QVj+PB5Wf7j3J+
bqBhY+Rk1pJ9/9Z5zU7eIN/YcA==
-----END PRIVATE KEY-----
server.crt内容如下
-----BEGIN CERTIFICATE-----
MIIDMjCCAhoCCQCs0EkSIt7T/jANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJD
TjESMBAGA1UECAwJR1VBTkdaSE9VMRIwEAYDVQQHDAlHVUFOR1pIT1UxCjAIBgNV
BAoMAUExCjAIBgNVBAsMAUIxDDAKBgNVBAMMA3h4eDAeFw0yMjAxMDcwMzI0MzNa
Fw0yMzAxMDcwMzI0MzNaMFsxCzAJBgNVBAYTAkNOMRIwEAYDVQQIDAlHVUFOR1pI
T1UxEjAQBgNVBAcMCUdVQU5HWkhPVTEKMAgGA1UECgwBQTEKMAgGA1UECwwBQjEM
MAoGA1UEAwwDeHh4MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1L+
3DidKArClTrrOki/RnGFJX7rmVCXyVYIAmFOqXi+d2Sr/w8z+hUkDDvFvlURU/pw
Q6S57bDAXZpx9oT9Cc/9OnfEQiYUUMZ9pfP+JagGcBYclr3fq+G5Kep352OLJNP8
prQtrad9ZVoE41yiFbTHzvSptGzcTyFdtOmHQvRvSCEeuTUsfAMjgpsDqd5nNNvP
vRxPzp0+bJsNpiQebcVVFHlWWHDqtI2jbOWf3MMzi7mmRHEz8Sx6FAGydHA53Duo
+ef/K/s2YIZKIrNtJOJBlQ1EmCnkx9jBinOtjyVclkWIGmhPjLlPt7RoBlvv0Fkf
6koaTo/1QEA0glTNQQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBk3o9BIggMhKdX
+wEIJ3piMnwXudLC2rUs2gP4EUaW/JuOotxVB+fRGNEBeHWyx8EupKEna5ho0IuN
WoqlFKyd7luqjUItbNyQ6IWoG8+bemhXWC6zg2jrPpHvwbhb9625Oo28XgNA5lsl
Lf+ybF7wpW7gMzLVK3z+vzOnvaunbjtASde7bLmL25qfm1K08iBQUOk0+EUCXY4q
efkRrVTh1aWwVSN51QhM3lMn0wGkPl2ww34zik5dA5RzXMlrOmHoGxzmd8oAJf7g
lJIQPrFyMv+mSo54TECkWSJeRAZNa+KZ0DKskcBPgE4SDZTlkCrZa3kEganTkE5F
/SO9kc0D
-----END CERTIFICATE-----
三、在Java代码中读取这些文件,然后调用对应类进行签名和签验
public class SslUtil {/*** 签验,返回签验是否通过* @param certificate 证书* @param signStr 签名的字符串* @param unSignStr 原字符串* @return* @throws NoSuchAlgorithmException* @throws InvalidKeyException* @throws SignatureException*/public static boolean verifySign(X509Certificate certificate, String signStr, String unSignStr)throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {byte[] data = Base64.getDecoder().decode(signStr);Signature signature = Signature.getInstance(certificate.getSigAlgName());signature.initVerify(certificate.getPublicKey());signature.update(unSignStr.getBytes(StandardCharsets.UTF_8));return signature.verify(data);}/*** 使用私钥对字符串进行签名,返回Base64编码后的字符串* @param str 原始字符串* @param privateKey 私钥* @param certificate 公钥* @return* @throws NoSuchAlgorithmException* @throws InvalidKeyException* @throws SignatureException*/public static String signString(String str, PrivateKey privateKey, X509Certificate certificate)throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {Signature signature = Signature.getInstance(certificate.getSigAlgName());signature.initSign(privateKey);signature.update(str.getBytes(StandardCharsets.UTF_8));byte[] data = signature.sign();return Base64.getEncoder().encodeToString(data);}/*** 读取证书文件* @param certFile* @return* @throws CertificateException*/public static X509Certificate getCertificate(String certFile) throws CertificateException, IOException {byte[] cert = readCertFile(certFile);CertificateFactory factory = CertificateFactory.getInstance("X.509");InputStream inputStream = new ByteArrayInputStream(cert);X509Certificate certificate = (X509Certificate) factory.generateCertificate(inputStream);return certificate;}/*** 读取私钥文件* @param pkcs8File* @return* @throws NoSuchAlgorithmException* @throws InvalidKeySpecException*/public static PrivateKey getPrivateKey(String pkcs8File)throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {byte[] prikey = readPkcs8File(pkcs8File);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(prikey);PrivateKey privateKey = keyFactory.generatePrivate(keySpec);return privateKey;}/*** 读取私钥文件,返回字节数组* 去掉开头结尾注释行,保留中间的数据* @param pkcs8File* @return* @throws IOException*/private static byte[] readPkcs8File(String pkcs8File) throws IOException {StringBuilder stringBuilder = new StringBuilder();try(BufferedReader br = new BufferedReader(new FileReader(pkcs8File))){String line;while((line=br.readLine())!=null){if(line.startsWith("-")){continue;}stringBuilder.append(line);}return Base64.getDecoder().decode(stringBuilder.toString());}}/*** 读取Cert证书文件,返回字节数组* 把命令生成的证书文件全部读取到内存* @param certFile* @return* @throws IOException*/private static byte[] readCertFile(String certFile) throws IOException{try(InputStream is = new FileInputStream(certFile)){return is.readAllBytes();}}
}
调用方法验证,最后会返还true
public class Main {public static void main(String[] args) {String pkcs8File = "pkcs8.pem";String certFile = "server.crt";String str = "这是原文字符串";try{PrivateKey privateKey = SslUtil.getPrivateKey(pkcs8File);X509Certificate certificate = SslUtil.getCertificate(certFile);String signStr = SslUtil.signString(str, privateKey, certificate);System.out.println("字符串 ["+str+"] ---签名--->["+signStr+"]");boolean result = SslUtil.verifySign(certificate, signStr, str);System.out.println("签验结果:"+result);}catch (Exception e){e.printStackTrace();}}
}
四、不使用java来签名,而是使用openssl命令来生成签名,然后使用java来签验
openssl签名的命令
1.创建需要签名的文件
echo "这是原文字符串" > a.txt2.对文件进行签名
openssl dgst -sha256 -passin pass:123456 -sign pri.key a.txt > b.txt3.对签名后的文件进行base64编码
base64 b.txt > c.txt/**
上面需要注意的是,不能使用openssl rsautl来生成签名
因为rsault生成的签名结果,只包含字符串body,而使用dgst生成的签名结果,是一个结构体,包含了结构体的信息(类型、长度、body)
java的Signature类解析会按照结构体进行解析,如果去解析rsault生成签名就会因为结构不对
报错javax.crypto.BadPaddingException: Decryption error
*/
命令生成的c.txt内容如下
BTG52NfjVx6v7yHq4OzCbuzeA4bvlWSPHI4N4yHSDzErmB8nWsQsJ97fKOTbeH7pdLzTuO2RS832
3wbEBo+FFTyOgUENa0J+I22SVVmCAzuPGzATRdvk6rM7kTbeMJZSIiBq/v4hX6btvAOuJ0f0/ZG5
m1bbbr3SZe26DiNl7TKgWpMhFW2OyRmaTq6fPfhOx+1/zWHFiMWrVl5WO3vJpRt2We3/wRwNzgBj
e6M+BlcQvND+gSS//ix/6avvAaNjudXU8r8/T0MKMAsuRk0zPbOjqbNudZrN4aDRf3GUkYiFzp86
5F9kkyqhapISVnpNWDEpSQz14cyoDAFUcd0yDw==
然后Java中直接拿到这个字符串进行签验
public class Main {public static void main(String[] args) {String pkcs8File = "pkcs8.pem";String certFile = "server.crt";//注意,文件方式加密的字符串,后面多了一个回车符号String str = "这是原文字符串\n";try{X509Certificate certificate = SslUtil.getCertificate(certFile);String signStr = "BTG52NfjVx6v7yHq4OzCbuzeA4bvlWSPHI4N4yHSDzErmB8nWsQsJ97fKOTbeH7pdLzTuO2RS8323wbEBo+FFTyOgUENa0J+I22SVVmCAzuPGzATRdvk6rM7kTbeMJZSIiBq/v4hX6btvAOuJ0f0/ZG5m1bbbr3SZe26DiNl7TKgWpMhFW2OyRmaTq6fPfhOx+1/zWHFiMWrVl5WO3vJpRt2We3/wRwNzgBje6M+BlcQvND+gSS//ix/6avvAaNjudXU8r8/T0MKMAsuRk0zPbOjqbNudZrN4aDRf3GUkYiFzp865F9kkyqhapISVnpNWDEpSQz14cyoDAFUcd0yDw==";boolean result = SslUtil.verifySign(certificate, signStr, str);System.out.println("签验结果:"+result);}catch (Exception e){e.printStackTrace();}}
}
使用java进行SSL证书的签名与签验相关推荐
- 沃通“SSL证书+代码签名证书”,防范高仿“钓鱼网站+钓鱼软件”攻击
近日,360发布威胁预警,因监测发现多起利用钓鱼网站对特定用户进行攻击的安全事件,呼吁警惕"高仿"软件安装程序暗藏钓鱼木马."钓鱼网站+钓鱼软件"是非常典型的钓 ...
- java 忽略SSL证书
** java 忽略SSL证书 ** 代码如下:(网上借鉴了很多大神的写法,都不能实现,最终使用以下代码亲测可行,侵联删) ```java import org.apache.http.Header; ...
- java生成ssl证书和部署
自签名SSL证书的生成 自签证书虽然提示:不安全.但还是有很多的好处,所以下面先说说自签证书的生成,主要使用Java JDK下的:keytool.exe 2:安装完后,根据实际的路径找到keytool ...
- Java管理SSL证书
SSL证书结构 根证书的生成分为三个部分: 生成根证书的公钥和私钥 构建证书的原始证书,包括公钥.加密算法.生效时间.过期时间等信息. 用根证书私钥对原始证书进行签名,生成合法的根证书. 根证书安装, ...
- JAVA通过SSL证书创建MS AD账户及设置密码
近期由于工作需要整理一下自动化的东西,因为公司去年上线了OA,所以公司的入职系统会提交用户的信息到IT部门,最早的做法是入职到了,IT部门收集用户信息在AD中创建对应的用户信息,所以为了提高管理员的工 ...
- jdk导入ssl证书(信任自签https证书)
前言 工作对接EMS,给的测试地址是https. 调接口的时候发现ssl证书认证不通过,就猜测是自签的证书了 1. 导出ssl证书 浏览器输入https链接,打开后提示证书不安全. 再打开地址栏左侧不 ...
- python sanic 设置ssl证书_配置自签https ssl证书
由于人们越来越重视网络安全,所以很多平台及系统都要求使用https方式接入.而且一些开源服务框架在调用时也只接受https请求,这将导致平时开发/测试时需要用到ssl证书的地方越来越多. 在2016年 ...
- Java生成SSL证书
1. 背景 2. 演示环境 3. 命令 4. 创建证书 5. 查看证书 5.1. 显示详细 5.2. 编码打印 6. 导入导出证书 6.1. 导出 6.2. 导入 7. 修改密码 7.1. 修改密钥库 ...
- java无视ssl证书构建post/get请求【伸手党福利】
首先上其他人写的工具类(看原理) java忽略证书验证(兼容http,https)进行get/post请求–使用(org.apache.httpcomponents httpclient客户端) ht ...
最新文章
- opensuse11.4 apache2 403 错误.
- History操作历史记录
- python为text添加滚动条_动态创建小部件pythontkinter并在画布中添加滚动条
- 用Unity3D实现简单的牧师与魔鬼游戏
- 刪除github上的一個repository
- 软件测试实验报告下载 实验一到实验五
- Livebos--流程结束触发事件(修改表和表里的表格字段)
- C#看书笔记_02 核心C#
- uniapp打包H5与uniapp打包apk交互,实现扫码功能。
- word模板生成利器poi-tl
- Ameya:蔡司激光共聚焦显微镜的优势特点及应用领域
- html怎么调用node.js,nodejs如何调用函数?
- [2017-08-28]Abp系列——业务异常与错误码设计及提示语的本地化
- centos8安装和启动中文智能拼音
- qsnctf 哥哥打篮球 wp
- UML需求分析步骤实例解析
- 【LeetCode】初级算法:数组
- BMP图片加马赛克C语言C++超简单
- python安装包下载及安装教程
- 输入某年某月某日,判断这一天是这一年的第几天?(JS实现)