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

相关文章

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

使用Python绘制3D堆叠条形图全解析

《使用Python绘制3D堆叠条形图全解析》在数据可视化的工具箱里,3D图表总能带来眼前一亮的效果,本文就来和大家聊聊如何使用Python实现绘制3D堆叠条形图,感兴趣的小伙伴可以了解下... 目录为什么选择 3D 堆叠条形图代码实现:从数据到 3D 世界的搭建核心代码逐行解析细节优化应用场景:3D 堆叠图

深度解析Python装饰器常见用法与进阶技巧

《深度解析Python装饰器常见用法与进阶技巧》Python装饰器(Decorator)是提升代码可读性与复用性的强大工具,本文将深入解析Python装饰器的原理,常见用法,进阶技巧与最佳实践,希望可... 目录装饰器的基本原理函数装饰器的常见用法带参数的装饰器类装饰器与方法装饰器装饰器的嵌套与组合进阶技巧

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

深度解析Spring Boot拦截器Interceptor与过滤器Filter的区别与实战指南

《深度解析SpringBoot拦截器Interceptor与过滤器Filter的区别与实战指南》本文深度解析SpringBoot中拦截器与过滤器的区别,涵盖执行顺序、依赖关系、异常处理等核心差异,并... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现

深度解析Spring AOP @Aspect 原理、实战与最佳实践教程

《深度解析SpringAOP@Aspect原理、实战与最佳实践教程》文章系统讲解了SpringAOP核心概念、实现方式及原理,涵盖横切关注点分离、代理机制(JDK/CGLIB)、切入点类型、性能... 目录1. @ASPect 核心概念1.1 AOP 编程范式1.2 @Aspect 关键特性2. 完整代码实

解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题

《解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题》:本文主要介绍解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4... 目录未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘打开pom.XM