当前位置: 首页 > article >正文

【JWT】jwt实现HS、RS、ES、ED签名与验签

JWT 实现 HSRSESED 签名与验签

签名方式算法密钥类型签名要点验签要点
HSHMAC-SHA256对称密钥- 使用 crypto/hmac 和对称密钥生成 HMAC 签名
- 将 header.payload 作为数据输入
- 使用同一密钥重新计算 HMAC 签名
- 比较计算结果与接收到的签名是否一致
RSRSA-SHA256公钥 + 私钥- 使用 crypto/rsa 生成 RSA 签名
- 私钥签名,输入为 header.payload 的哈希值
- 使用 crypto/rsa 验证 RSA 签名
- 公钥解密签名后,验证是否与输入哈希值匹配
ESECDSA-P256公钥 + 私钥- 使用 crypto/ecdsa 生成 ECDSA 签名
- 签名结果为 (r, s),序列化并编码为 Base64URL
- 使用 crypto/ecdsa 验证签名
- 解析签名为 (r, s),验证其与 header.payload 的哈希匹配
EDEd25519公钥 + 私钥- 使用 crypto/ed25519 私钥直接签名完整的 header.payload 数据
- 签名结果无需额外哈希处理
- 使用 crypto/ed25519 公钥直接验证签名是否匹配完整数据

签名与验签实现重点

  • es算法签名和验签时算法位数必须相同:ES算法在验签时必须严格使用与签名时相同位数的算法进行验证,这一点与其他算法有所不同。(其他算法不必相同) 说明如下:

  • 加密在这里插入图片描述

  • 验签 在这里插入图片描述

  • Base64URL 编码:JWT 的 HeaderPayload 都需编码。

  • 数据输入:签名计算与验证的输入数据始终是 Base64URL(Header) + "." + Base64URL(Payload)

  • 密钥管理:对称密钥 (HS) 要妥善分发,公私钥对 (RS/ES/ED) 要安全存储。


go案例

hs.go

package jwtex

import (
	"github.com/golang-jwt/jwt/v5"
	"log"
)

type HS struct {
	Key        string
	SignMethod HSSignMethod
}

type HSSignMethod string

const (
	HS256 HSSignMethod = "HS256"
	HS384 HSSignMethod = "HS384"
	HS512 HSSignMethod = "HS512"
)

// hs HMAC(Hash-based Message Authentication Code)用的hash-based
func (hs *HS) getSignMethod() *jwt.SigningMethodHMAC {
	// *jwt.SigningMethodHMAC 是 jwt.SigningMethod 接口的具体实现之一。通过返回具体的实现类型,
	// 可以确保你使用的是 HMAC 签名方法,而不是其他类型的签名方法(如 RSA 或 ECDSA)。
	switch hs.SignMethod {
	case HS256:
		return jwt.SigningMethodHS256
	case HS384:
		return jwt.SigningMethodHS384
	case HS512:
		return jwt.SigningMethodHS512
	default:
		return jwt.SigningMethodHS256
	}
}

// Sign 签名
func (hs *HS) Sign(data jwt.Claims) (string, error) {
	token := jwt.NewWithClaims(hs.getSignMethod(), data)
	sign, err := token.SignedString([]byte(hs.Key))
	if err != nil {
		log.Println(err)
		return "", err
	}
	return sign, nil
}

// Verify 验签,获取数据
func (hs *HS) Verify(sign string, data jwt.Claims) error {
	_, err := jwt.ParseWithClaims(sign, data, func(token *jwt.Token) (interface{}, error) {
		return []byte(hs.Key), nil
	})
	return err
}


rsa.go 私钥签名、公钥验证

package jwtex

import (
	"github.com/golang-jwt/jwt/v5"
	"log"
)

type RS struct {
	SignMethod RSSignMethod
	PublicKey  string
	PrivateKey string
}

type RSSignMethod string

const (
	RS256 RSSignMethod = "RS256"
	RS384 RSSignMethod = "RS384"
	RS512 RSSignMethod = "RS512"
)

func (rs *RS) getSignMethod() *jwt.SigningMethodRSA {
	switch rs.SignMethod {
	case RS512:
		return jwt.SigningMethodRS512
	case RS384:
		return jwt.SigningMethodRS384
	case RS256:
		return jwt.SigningMethodRS256
	default:
		return jwt.SigningMethodRS256
	}
}

// Sign 签名	私钥签名、公钥验证
func (rs *RS) Sign(data jwt.Claims) (string, error) {
	token := jwt.NewWithClaims(rs.getSignMethod(), data)
	pKey, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(rs.PrivateKey))
	sign, err := token.SignedString(pKey)
	if err != nil {
		log.Println(err)
		return "", err
	}
	return sign, nil
}

// Verify 验签,获取数据
func (rs *RS) Verify(sign string, data jwt.Claims) error {
	_, err := jwt.ParseWithClaims(sign, data, func(token *jwt.Token) (interface{}, error) {
		return jwt.ParseRSAPublicKeyFromPEM([]byte(rs.PublicKey))
	})
	return err
}


es.go 私钥签名、公钥验证

package jwtex

import (
	"github.com/golang-jwt/jwt/v5"
	"log"
)

type ES struct {
	SignMethod ESSignMethod
	PublicKey  string
	PrivateKey string
}

type ESSignMethod string

const (
	ES256 ESSignMethod = "ES256"
	ES384 ESSignMethod = "ES384"
	ES512 ESSignMethod = "ES512"
)

func (es *ES) getSignMethod() *jwt.SigningMethodECDSA {
	switch es.SignMethod {
	case ES512:
		return jwt.SigningMethodES512
	case ES384:
		return jwt.SigningMethodES384
	case ES256:
		return jwt.SigningMethodES256
	default:
		return jwt.SigningMethodES256
	}
}

// Sign 签名	私钥签名、公钥验证
func (es *ES) Sign(data jwt.Claims) (string, error) {
	token := jwt.NewWithClaims(es.getSignMethod(), data)
	pKey, err := jwt.ParseECPrivateKeyFromPEM([]byte(es.PrivateKey))
	if err != nil {
		log.Println(err)
		return "", err
	}
	sign, err := token.SignedString(pKey)
	if err != nil {
		log.Println(err)
		return "", err
	}
	return sign, nil
}

// Verify 验签,获取数据
func (es *ES) Verify(sign string, data jwt.Claims) error {
	_, err := jwt.ParseWithClaims(sign, data, func(token *jwt.Token) (interface{}, error) {
		return jwt.ParseECPublicKeyFromPEM([]byte(es.PublicKey))
	})
	return err
}


ed.go 私钥签名、公钥验证

package jwtex

import (
	"github.com/golang-jwt/jwt/v5"
	"log"
)

type ED struct {
	PrivateKey string
	PublicKey  string
}

// Sign 签名
func (ed *ED) Sign(data jwt.Claims) (string, error) {
	token := jwt.NewWithClaims(jwt.SigningMethodEdDSA, data)
	pKey, err := jwt.ParseEdPrivateKeyFromPEM([]byte(ed.PrivateKey))
	if err != nil {
		log.Println(err)
		return "", err
	}
	sign, err := token.SignedString(pKey)
	if err != nil {
		log.Println(err)
		return "", err
	}
	return sign, err
}

// Verify 验签,并获取数据
func (ed *ED) Verify(sign string, data jwt.Claims) error {
	_, err := jwt.ParseWithClaims(sign, data, func(token *jwt.Token) (interface{}, error) {
		return jwt.ParseEdPublicKeyFromPEM([]byte(ed.PublicKey))
	})
	return err
}


jwt.go

package jwtex

import (
	"github.com/golang-jwt/jwt/v5"
)

type Data struct {
	Name   string
	Age    int
	Gender int
	jwt.RegisteredClaims
}

type Jwt interface {
	Sing(data jwt.Claims) (string, error)
	Verify(sign string, data jwt.Claims) error
}


https://github.com/0voice


http://www.kler.cn/a/518130.html

相关文章:

  • 力扣算法题——283.移动零【系统讲解】
  • Kotlin开发(三):编程趣事,变量、判断和循环的三角恋
  • C++ 复习总结记录十
  • transformers报错:‘GenerationConfig‘ object has no attribute ‘_eos_token_tensor‘
  • INCOSE需求编写指南-第1部分:介绍
  • 基于Hadoop的汽车大数据分析系统设计与实现【爬虫、数据预处理、MapReduce、echarts、Flask】
  • 【GO】Context
  • 亚博microros小车-原生ubuntu支持系列:11手指控制与手势识别
  • 活动回顾和预告|微软开发者社区 Code Without Barriers 上海站首场活动成功举办!
  • Queries Acceleration -Tuning- Tuning Execution 学习笔记
  • 在Android中通过JNI实现Java与C++的交互:Hello World示例
  • C++中static和const的区别和用法
  • leetcode——相交链表(java)
  • Spring Boot - 数据库集成02 - 集成JPA
  • DSP实验七 综合实验与考查
  • 数据库之PostgreSQL详解
  • 构建基于知识图谱的语义化问答系统
  • ray.rllib 入门实践-2:配置算法
  • Lua 初级教程
  • Android BitmapShader简洁实现马赛克,Kotlin(二)