JWT Token生成与解析 + ECDSA加密技术

2023-11-02 15:18

本文主要是介绍JWT Token生成与解析 + ECDSA加密技术,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

JWT Token生成与解析 + ECDSA加密技术

  • 需要maven依赖
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>
  • 16进制字符串与byte数组互转工具类

/*** 16进制字符串与byte数组转换* @author chenyb**/
public final class HexUtil {private static final char[] HEX = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};public HexUtil() {}/*** byte数组转16进制字符串* @param bytes* @return*/public static String encodeHexString(byte[] bytes) {int nBytes = bytes.length;char[] result = new char[2 * nBytes];int j = 0;byte[] var4 = bytes;int var5 = bytes.length;for(int var6 = 0; var6 < var5; ++var6) {byte aByte = var4[var6];result[j++] = HEX[(240 & aByte) >>> 4];result[j++] = HEX[15 & aByte];}return new String(result);}/*** 16进制字符串转byte数组* @param s 字符串* @return*/public static byte[] decode(CharSequence s) {int nChars = s.length();if (nChars % 2 != 0) {throw new IllegalArgumentException("Hex-encoded string must have an even number of characters");} else {byte[] result = new byte[nChars / 2];for(int i = 0; i < nChars; i += 2) {int msb = Character.digit(s.charAt(i), 16);int lsb = Character.digit(s.charAt(i + 1), 16);if (msb < 0 || lsb < 0) {throw new IllegalArgumentException("Detected a Non-hex character at " + (i + 1) + " or " + (i + 2) + " position");}result[i / 2] = (byte)(msb << 4 | lsb);}return result;}}}
  •  生成密钥对,校验密钥有效性
package com.jwt.ecdsa;import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;import javax.xml.bind.DatatypeConverter;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Calendar;public class ECDSATest {/*** SIGNALGORITHMS* NONEwithECDSA	112-571	256	128	JDK/BC* RIPEMD160withECDSA	同上	256	160	BC* SHA1withECDSA	...	256	160	JDK/BC* SHA224withECDSA	...	256	224	BC* SHA256withECDSA	...	256	256	JDK/BC* SHA384withECDSA	...	256	384	JDK/BC* SHA512withECDSA	...	256	512	JDK/BC*/private static final String SIGNALGORITHMS = "SHA256withECDSA";private static final String ALGORITHM = "EC";private static final String SECP256K1 = "secp256k1";public static void main(String[] args) throws Exception {//        生成公钥私钥KeyPair keyPair1 = getKeyPair();PublicKey publicKey1 = keyPair1.getPublic();PrivateKey privateKey1 = keyPair1.getPrivate();//密钥转16进制字符串String publicKey = HexUtil.encodeHexString(publicKey1.getEncoded());String privateKey = HexUtil.encodeHexString(privateKey1.getEncoded());System.out.println("生成公钥:"+publicKey);System.out.println("生成私钥:"+privateKey);//16进制字符串转密钥对象PrivateKey privateKey2 = getPrivateKey(privateKey);PublicKey publicKey2 = getPublicKey(publicKey);//加签验签,设计自己的签名JSONObject o = new JSONObject();o.put( "id","sadasdsadsawq2132343243242ds" );o.put( "name","chenyb" );String data=o.toJSONString();String signECDSA = signECDSA(privateKey2, data);System.out.println(signECDSA);boolean verifyECDSA = verifyECDSA(publicKey2, signECDSA, data);System.out.println("验签结果:"+verifyECDSA);}/*** 加签* @param privateKey 私钥* @param data 数据* @return*/public static String signECDSA(PrivateKey privateKey, String data) {String result = "";try {//执行签名Signature signature = Signature.getInstance(SIGNALGORITHMS);signature.initSign(privateKey);signature.update(data.getBytes());byte[] sign = signature.sign();return HexUtil.encodeHexString(sign);} catch (Exception e) {e.printStackTrace();}return result;}/*** 验签* @param publicKey 公钥* @param signed 签名* @param data 数据* @return*/public static boolean verifyECDSA(PublicKey publicKey, String signed, String data) {try {//验证签名Signature signature = Signature.getInstance(SIGNALGORITHMS);signature.initVerify(publicKey);signature.update(data.getBytes());byte[] hex = HexUtil.decode(signed);boolean bool = signature.verify(hex);// System.out.println("验证:" + bool);return bool;} catch (Exception e) {e.printStackTrace();}return false;}/*** 从string转private key* @param key 私钥的字符串* @return* @throws Exception*/public static PrivateKey getPrivateKey(String key) throws Exception {byte[] bytes = DatatypeConverter.parseHexBinary(key);PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);return keyFactory.generatePrivate(keySpec);}/*** 从string转publicKey* @param key 公钥的字符串* @return* @throws Exception*/public static PublicKey getPublicKey(String key) throws Exception {byte[] bytes = DatatypeConverter.parseHexBinary(key);X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);return keyFactory.generatePublic(keySpec);}/*** 生成密钥对* @return* @throws Exception*/public static KeyPair getKeyPair() throws Exception {ECGenParameterSpec ecSpec = new ECGenParameterSpec(SECP256K1);KeyPairGenerator kf = KeyPairGenerator.getInstance(ALGORITHM);kf.initialize(ecSpec, new SecureRandom());KeyPair keyPair = kf.generateKeyPair();return keyPair;}}
  • 测试密钥配对成功截图

  •  jwt生成token与解析
public static void main(String[] args) throws Exception {java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());//获取公钥私钥部分KeyPair keyPair1 = getKeyPair();PublicKey publicKey1 = keyPair1.getPublic();PrivateKey privateKey1 = keyPair1.getPrivate();//密钥转16进制字符串String publicKey = HexUtil.encodeHexString(publicKey1.getEncoded());String privateKey = HexUtil.encodeHexString(privateKey1.getEncoded());System.out.println("生成公钥:"+publicKey);System.out.println("生成私钥:"+privateKey);//16进制字符串转密钥对象PrivateKey privateKey2 = getPrivateKey(privateKey);PublicKey publicKey2 = getPublicKey(publicKey);//生成token部分SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Calendar c = Calendar.getInstance();c.add(Calendar.HOUR_OF_DAY, Integer.valueOf( 1000*60*5 ));//设置Token有效时长JSONObject o = new JSONObject();o.put("principal", "data数据");//封装数据Object类型o.put("exp", sdf.format(c.getTime()));//单纯的记录Token生成时间//SignatureAlgorithm.ES256 这里一定是对应的采用的加密技术String token = Jwts.builder().setClaims(o).setExpiration(c.getTime()).signWith( SignatureAlgorithm.ES256, privateKey2).compact();System.out.println("生成的token:"+token);//解析token部分final Claims claims = Jwts.parser().setSigningKey(publicKey2).parseClaimsJws(token).getBody();String str = (String) claims.get("principal");System.out.println("token解析出来的数据"+str);}
  • 实战中,我们只需要提供生成token接口与解析token接口,将密钥对提前生成好存在文件里,在生成、与解析的时候调用就好
//接口部分
package com.jwt.service;public interface JwtService {String createToken(String str);String getData(String token);}//实现部分
package com.jwt.service.impl;import com.alibaba.fastjson.JSONObject;
import com.jwt.ecdsa.ECDSATest;
import com.jwt.service.JwtService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Service;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;/*** Created by chenyb .*/
@Service
public class JwtServiceImpl implements JwtService {@SuppressWarnings("restriction")private PublicKey getPublicKey() {PublicKey publicKey = null;try {InputStream stream = getClass().getClassLoader().getResourceAsStream("key/public.key");BufferedReader br = new BufferedReader(new InputStreamReader(stream));String line = "";StringBuffer sb = new StringBuffer();while ((line = br.readLine()) != null) {sb.append(line);}publicKey = ECDSATest.getPublicKey(sb.toString());} catch (Exception e) {e.printStackTrace();}return publicKey;}private PrivateKey getPrivateKey(){PrivateKey privateKey = null;try {InputStream stream = getClass().getClassLoader().getResourceAsStream("key/private.key");BufferedReader br = new BufferedReader(new InputStreamReader(stream));String line = "";StringBuffer sb = new StringBuffer();while ((line = br.readLine()) != null) {sb.append(line);}privateKey = ECDSATest.getPrivateKey( sb.toString() );} catch (Exception e) {e.printStackTrace();}return privateKey;}@Overridepublic String createToken(String str){java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());PrivateKey privateKey = this.getPrivateKey();JSONObject data = new JSONObject();data.put("data", str);SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Calendar c = Calendar.getInstance();c.add(Calendar.HOUR_OF_DAY, 1000*60*60*2);//token有效时间JSONObject o = new JSONObject();o.put("principal", data);o.put("exp", sdf.format(c.getTime()));Date timeOut = c.getTime();String token = Jwts.builder().setClaims(o).setExpiration(timeOut).signWith(SignatureAlgorithm.ES256, privateKey).compact();return token;}@Overridepublic String getData(String token) {PublicKey publicKey = getPublicKey();if (publicKey != null) {try {final Claims claims = Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token).getBody();Map<String,String> map = (Map<String,String>) claims.get("principal");return map.get( "data" );}catch (Exception e){e.printStackTrace();}}return null;}
}
  •  Key文件位置

  • 测试代码
@Testpublic void createToken (){String token = jwtServiceImpl.createToken( "被封装的数据" );System.out.println("token:"+token);String s = jwtServiceImpl.getData( token );System.out.println(s);}
  • 测试结果

随笔记录,方便学习

2020-07-03

这篇关于JWT Token生成与解析 + ECDSA加密技术的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/331494

相关文章

SQL 外键Foreign Key全解析

《SQL外键ForeignKey全解析》外键是数据库表中的一列(或一组列),用于​​建立两个表之间的关联关系​​,外键的值必须匹配另一个表的主键(PrimaryKey)或唯一约束(UniqueCo... 目录1. 什么是外键?​​ ​​​​2. 外键的语法​​​​3. 外键的约束行为​​​​4. 多列外键​

Java进行日期解析与格式化的实现代码

《Java进行日期解析与格式化的实现代码》使用Java搭配ApacheCommonsLang3和Natty库,可以实现灵活高效的日期解析与格式化,本文将通过相关示例为大家讲讲具体的实践操作,需要的可以... 目录一、背景二、依赖介绍1. Apache Commons Lang32. Natty三、核心实现代

使用Python自动化生成PPT并结合LLM生成内容的代码解析

《使用Python自动化生成PPT并结合LLM生成内容的代码解析》PowerPoint是常用的文档工具,但手动设计和排版耗时耗力,本文将展示如何通过Python自动化提取PPT样式并生成新PPT,同时... 目录核心代码解析1. 提取 PPT 样式到 jsON关键步骤:代码片段:2. 应用 JSON 样式到

Maven 插件配置分层架构深度解析

《Maven插件配置分层架构深度解析》:本文主要介绍Maven插件配置分层架构深度解析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Maven 插件配置分层架构深度解析引言:当构建逻辑遇上复杂配置第一章 Maven插件配置的三重境界1.1 插件配置的拓扑

SpringBoot实现二维码生成的详细步骤与完整代码

《SpringBoot实现二维码生成的详细步骤与完整代码》如今,二维码的应用场景非常广泛,从支付到信息分享,二维码都扮演着重要角色,SpringBoot是一个非常流行的Java基于Spring框架的微... 目录一、环境搭建二、创建 Spring Boot 项目三、引入二维码生成依赖四、编写二维码生成代码五

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

全解析CSS Grid 的 auto-fill 和 auto-fit 内容自适应

《全解析CSSGrid的auto-fill和auto-fit内容自适应》:本文主要介绍了全解析CSSGrid的auto-fill和auto-fit内容自适应的相关资料,详细内容请阅读本文,希望能对你有所帮助... css  Grid 的 auto-fill 和 auto-fit/* 父元素 */.gri

Maven 依赖发布与仓库治理的过程解析

《Maven依赖发布与仓库治理的过程解析》:本文主要介绍Maven依赖发布与仓库治理的过程解析,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下... 目录Maven 依赖发布与仓库治理引言第一章:distributionManagement配置的工程化实践1

MySQL复合查询从基础到多表关联与高级技巧全解析

《MySQL复合查询从基础到多表关联与高级技巧全解析》本文主要讲解了在MySQL中的复合查询,下面是关于本文章所需要数据的建表语句,感兴趣的朋友跟随小编一起看看吧... 目录前言:1.基本查询回顾:1.1.查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J1.2.按照部门

Spring三级缓存解决循环依赖的解析过程

《Spring三级缓存解决循环依赖的解析过程》:本文主要介绍Spring三级缓存解决循环依赖的解析过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、循环依赖场景二、三级缓存定义三、解决流程(以ServiceA和ServiceB为例)四、关键机制详解五、设计约