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图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

关于WebSocket协议状态码解析

《关于WebSocket协议状态码解析》:本文主要介绍关于WebSocket协议状态码的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录WebSocket协议状态码解析1. 引言2. WebSocket协议状态码概述3. WebSocket协议状态码详解3

Java利用docx4j+Freemarker生成word文档

《Java利用docx4j+Freemarker生成word文档》这篇文章主要为大家详细介绍了Java如何利用docx4j+Freemarker生成word文档,文中的示例代码讲解详细,感兴趣的小伙伴... 目录技术方案maven依赖创建模板文件实现代码技术方案Java 1.8 + docx4j + Fr

CSS Padding 和 Margin 区别全解析

《CSSPadding和Margin区别全解析》CSS中的padding和margin是两个非常基础且重要的属性,它们用于控制元素周围的空白区域,本文将详细介绍padding和... 目录css Padding 和 Margin 全解析1. Padding: 内边距2. Margin: 外边距3. Padd

Oracle数据库常见字段类型大全以及超详细解析

《Oracle数据库常见字段类型大全以及超详细解析》在Oracle数据库中查询特定表的字段个数通常需要使用SQL语句来完成,:本文主要介绍Oracle数据库常见字段类型大全以及超详细解析,文中通过... 目录前言一、字符类型(Character)1、CHAR:定长字符数据类型2、VARCHAR2:变长字符数

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.