aes and jwt
This commit is contained in:
parent
d2175ab3c3
commit
e05304b0e3
|
|
@ -21,12 +21,18 @@ spec:
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8080
|
- containerPort: 8080
|
||||||
env:
|
env:
|
||||||
|
- name: URL_PREFIX
|
||||||
|
value: admin
|
||||||
- name: DB_HOST
|
- name: DB_HOST
|
||||||
value: 192.168.131.195
|
value: 192.168.131.195
|
||||||
- name: DB_USER
|
- name: DB_USER
|
||||||
value: app
|
value: app
|
||||||
- name: DB_PASS
|
- name: DB_PASS
|
||||||
value: ???????
|
value: 1PQlNf9*9Ulo
|
||||||
|
- name: JWT_KEY
|
||||||
|
value: !bd832W0@CG
|
||||||
|
- name: ASE_KEY
|
||||||
|
value: A5es$&!0GeoEast
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
|
|
|
||||||
122
main.go
122
main.go
|
|
@ -1,20 +1,41 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/sha1"
|
||||||
"embed"
|
"embed"
|
||||||
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/golang-jwt/jwt/v4"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
m "k8s-manager/src"
|
m "k8s-manager/src"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed template/* static/*
|
//go:embed template/* static/*
|
||||||
var f embed.FS
|
var f embed.FS
|
||||||
|
|
||||||
|
var jwtKey string
|
||||||
|
var aseKey string
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
m.InitClient()
|
m.InitClient()
|
||||||
|
|
||||||
|
jwtKey = os.Getenv("JWT_KEY")
|
||||||
|
aseKey = os.Getenv("ASE_KEY")
|
||||||
|
if jwtKey == "" {
|
||||||
|
panic("No jwt key")
|
||||||
|
}
|
||||||
|
if aseKey == "" {
|
||||||
|
panic("No ase key")
|
||||||
|
}
|
||||||
|
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
|
|
||||||
fp, _ := fs.Sub(f, "static")
|
fp, _ := fs.Sub(f, "static")
|
||||||
|
|
@ -32,6 +53,7 @@ func main() {
|
||||||
r.DELETE("/dep", m.JWTAuthMiddleware, m.CreateDeleteDeployment)
|
r.DELETE("/dep", m.JWTAuthMiddleware, m.CreateDeleteDeployment)
|
||||||
|
|
||||||
r.GET("/login/:username", Test)
|
r.GET("/login/:username", Test)
|
||||||
|
r.Any("/test_token", TestToken)
|
||||||
r.GET("/username", m.JWTAuthMiddleware, m.GetUsername)
|
r.GET("/username", m.JWTAuthMiddleware, m.GetUsername)
|
||||||
err := r.Run(":8000")
|
err := r.Run(":8000")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -39,8 +61,89 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CGJWTClaim struct {
|
||||||
|
jwt.RegisteredClaims
|
||||||
|
Userid string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseCGToken(token string) (string, error) {
|
||||||
|
token = strings.ReplaceAll(token, "-", "+")
|
||||||
|
token = strings.ReplaceAll(token, "_", "/")
|
||||||
|
token = token + []string{"", "===", "==", "="}[len(token)%4]
|
||||||
|
fmt.Println(token)
|
||||||
|
aesEncrypt, err := base64.StdEncoding.DecodeString(token)
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("Parse CG Token 1")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
jwtString := AesDecryptECB(aesEncrypt, []byte(aseKey))
|
||||||
|
|
||||||
|
jwtResult, err := jwt.ParseWithClaims(string(jwtString), &CGJWTClaim{}, func(token *jwt.Token) (i interface{}, err error) {
|
||||||
|
return jwtKey, nil
|
||||||
|
// return hmac.New(sha256.New, []byte(jwtKey)), nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("Parse CG Token 2")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if claims, ok := jwtResult.Claims.(*CGJWTClaim); ok && jwtResult.Valid { // 校验token
|
||||||
|
return claims.Userid, nil
|
||||||
|
}
|
||||||
|
return "", errors.New("jwt parse error")
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateKey(key []byte) (genKey []byte) {
|
||||||
|
genKey = make([]byte, 16)
|
||||||
|
copy(genKey, key)
|
||||||
|
for i := 16; i < len(key); {
|
||||||
|
for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 {
|
||||||
|
genKey[j] ^= key[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return genKey
|
||||||
|
}
|
||||||
|
func AesDecryptECB(encrypted []byte, key []byte) (decrypted []byte) {
|
||||||
|
cipher, _ := aes.NewCipher(generateKey(key))
|
||||||
|
decrypted = make([]byte, len(encrypted))
|
||||||
|
//
|
||||||
|
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||||
|
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||||||
|
}
|
||||||
|
|
||||||
|
trim := 0
|
||||||
|
if len(decrypted) > 0 {
|
||||||
|
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return decrypted[:trim]
|
||||||
|
}
|
||||||
|
|
||||||
|
func AesDecrypt(data []byte, key []byte) ([]byte, error) {
|
||||||
|
sh := sha1.New()
|
||||||
|
sh.Write(key)
|
||||||
|
realKey := sh.Sum(nil)
|
||||||
|
|
||||||
|
fmt.Println(string(realKey))
|
||||||
|
block, err := aes.NewCipher(realKey[:16])
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("AesDecrypt 1")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
blockSize := block.BlockSize()
|
||||||
|
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
|
||||||
|
crypted := make([]byte, len(data))
|
||||||
|
blockMode.CryptBlocks(crypted, data)
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("AesDecrypt 2")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return crypted, nil
|
||||||
|
}
|
||||||
|
|
||||||
func Test(c *gin.Context) {
|
func Test(c *gin.Context) {
|
||||||
username := c.Param("username")
|
//username := c.Param("username")
|
||||||
|
username, _ := ParseCGToken(c.Request.URL.Query().Get("cgtoken"))
|
||||||
if username == "" {
|
if username == "" {
|
||||||
c.JSON(http.StatusNotFound, gin.H{
|
c.JSON(http.StatusNotFound, gin.H{
|
||||||
"code": http.StatusNotFound,
|
"code": http.StatusNotFound,
|
||||||
|
|
@ -56,6 +159,21 @@ func Test(c *gin.Context) {
|
||||||
c.SetCookie("Authorization", "Bearer "+token, 0, "", "", false, false)
|
c.SetCookie("Authorization", "Bearer "+token, 0, "", "", false, false)
|
||||||
c.Header("Authorization", "Bearer "+token)
|
c.Header("Authorization", "Bearer "+token)
|
||||||
c.Header("Cache-Control", "no-store")
|
c.Header("Cache-Control", "no-store")
|
||||||
c.Redirect(http.StatusTemporaryRedirect, "../index")
|
redirectUrl := fmt.Sprintf("/%s/index", os.Getenv("URL_PREFIX"))
|
||||||
|
c.Redirect(http.StatusTemporaryRedirect, redirectUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestToken(c *gin.Context) {
|
||||||
|
token := c.Request.URL.Query().Get("cgtoken")
|
||||||
|
if token == "" {
|
||||||
|
c.JSON(http.StatusForbidden, gin.H{"msg": "No token"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
username, err := ParseCGToken(token)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusForbidden, gin.H{"msg": "token error"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, gin.H{"msg": "ok", "username": username})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,151 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha1"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RealKey(key string) []byte {
|
||||||
|
sh := sha1.New()
|
||||||
|
sh.Write([]byte(key))
|
||||||
|
realKey := sh.Sum(nil)
|
||||||
|
return realKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
origData := []byte("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY2hvb2xpZCI6Ijk5OSIsImV4cCI6MTY3MDcxMzk3OSwidXNlcm5hbWUiOiLllJDlrociLCJjb3Vyc2VzIjoiLDMyLDQsMzgsMzcsNDIsNDMsOSw0MCw0MSwxMSwxMiwxMyw0NCwxNCwxOSwyNiwyOSIsInNjaG9vbG5hbWUiOiLluIzlhoDlnKjnur8iLCJ1c2VyaWQiOiJjZ190YW5neXUiLCJjb2xsZWdlbmFtZSI6IuWtpuefpeahpSIsImhvbWVwYWdlIjoiaHR0cHM6Ly85OTkuYmQuZWR1Y2cubmV0LyJ9.fB3-L-gEOXVlyjjZqphkORtGCRK4ZWI9RNxO4-FULhw") // 待加密的数据
|
||||||
|
key := RealKey("A5es$&!0GeoEast")
|
||||||
|
log.Println("原文:", string(origData))
|
||||||
|
|
||||||
|
// log.Println("------------------ CBC模式 --------------------")
|
||||||
|
// encrypted := AesEncryptCBC(origData, key)
|
||||||
|
// log.Println("密文(hex):", hex.EncodeToString(encrypted))
|
||||||
|
// log.Println("密文(base64):", base64.StdEncoding.EncodeToString(encrypted))
|
||||||
|
// decrypted := AesDecryptCBC(encrypted, key)
|
||||||
|
// log.Println("解密结果:", string(decrypted))
|
||||||
|
|
||||||
|
log.Println("------------------ ECB模式 --------------------")
|
||||||
|
encrypted := AesEncryptECB(origData, key)
|
||||||
|
log.Println("密文(hex):", hex.EncodeToString(encrypted))
|
||||||
|
log.Println("密文(base64):", base64.StdEncoding.EncodeToString(encrypted))
|
||||||
|
decrypted := AesDecryptECB(encrypted, key)
|
||||||
|
log.Println("解密结果:", string(decrypted))
|
||||||
|
|
||||||
|
// log.Println("------------------ CFB模式 --------------------")
|
||||||
|
// encrypted = AesEncryptCFB(origData, key)
|
||||||
|
// log.Println("密文(hex):", hex.EncodeToString(encrypted))
|
||||||
|
// log.Println("密文(base64):", base64.StdEncoding.EncodeToString(encrypted))
|
||||||
|
// decrypted = AesDecryptCFB(encrypted, key)
|
||||||
|
// log.Println("解密结果:", string(decrypted))
|
||||||
|
}
|
||||||
|
|
||||||
|
// =================== CBC ======================
|
||||||
|
func AesEncryptCBC(origData []byte, key []byte) (encrypted []byte) {
|
||||||
|
// 分组秘钥
|
||||||
|
// NewCipher该函数限制了输入k的长度必须为16, 24或者32
|
||||||
|
block, _ := aes.NewCipher(key)
|
||||||
|
blockSize := block.BlockSize() // 获取秘钥块的长度
|
||||||
|
origData = pkcs5Padding(origData, blockSize) // 补全码
|
||||||
|
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) // 加密模式
|
||||||
|
encrypted = make([]byte, len(origData)) // 创建数组
|
||||||
|
blockMode.CryptBlocks(encrypted, origData) // 加密
|
||||||
|
return encrypted
|
||||||
|
}
|
||||||
|
func AesDecryptCBC(encrypted []byte, key []byte) (decrypted []byte) {
|
||||||
|
block, _ := aes.NewCipher(key) // 分组秘钥
|
||||||
|
blockSize := block.BlockSize() // 获取秘钥块的长度
|
||||||
|
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) // 加密模式
|
||||||
|
decrypted = make([]byte, len(encrypted)) // 创建数组
|
||||||
|
blockMode.CryptBlocks(decrypted, encrypted) // 解密
|
||||||
|
decrypted = pkcs5UnPadding(decrypted) // 去除补全码
|
||||||
|
return decrypted
|
||||||
|
}
|
||||||
|
func pkcs5Padding(ciphertext []byte, blockSize int) []byte {
|
||||||
|
padding := blockSize - len(ciphertext)%blockSize
|
||||||
|
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||||
|
return append(ciphertext, padtext...)
|
||||||
|
}
|
||||||
|
func pkcs5UnPadding(origData []byte) []byte {
|
||||||
|
length := len(origData)
|
||||||
|
unpadding := int(origData[length-1])
|
||||||
|
return origData[:(length - unpadding)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// =================== ECB ======================
|
||||||
|
func AesEncryptECB(origData []byte, key []byte) (encrypted []byte) {
|
||||||
|
cipher, _ := aes.NewCipher(generateKey(key))
|
||||||
|
length := (len(origData) + aes.BlockSize) / aes.BlockSize
|
||||||
|
plain := make([]byte, length*aes.BlockSize)
|
||||||
|
copy(plain, origData)
|
||||||
|
pad := byte(len(plain) - len(origData))
|
||||||
|
for i := len(origData); i < len(plain); i++ {
|
||||||
|
plain[i] = pad
|
||||||
|
}
|
||||||
|
encrypted = make([]byte, len(plain))
|
||||||
|
// 分组分块加密
|
||||||
|
for bs, be := 0, cipher.BlockSize(); bs <= len(origData); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||||
|
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||||||
|
}
|
||||||
|
|
||||||
|
return encrypted
|
||||||
|
}
|
||||||
|
func AesDecryptECB(encrypted []byte, key []byte) (decrypted []byte) {
|
||||||
|
cipher, _ := aes.NewCipher(generateKey(key))
|
||||||
|
decrypted = make([]byte, len(encrypted))
|
||||||
|
//
|
||||||
|
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||||
|
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||||||
|
}
|
||||||
|
|
||||||
|
trim := 0
|
||||||
|
if len(decrypted) > 0 {
|
||||||
|
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return decrypted[:trim]
|
||||||
|
}
|
||||||
|
func generateKey(key []byte) (genKey []byte) {
|
||||||
|
genKey = make([]byte, 16)
|
||||||
|
copy(genKey, key)
|
||||||
|
for i := 16; i < len(key); {
|
||||||
|
for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 {
|
||||||
|
genKey[j] ^= key[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return genKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// =================== CFB ======================
|
||||||
|
func AesEncryptCFB(origData []byte, key []byte) (encrypted []byte) {
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
encrypted = make([]byte, aes.BlockSize+len(origData))
|
||||||
|
iv := encrypted[:aes.BlockSize]
|
||||||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
stream := cipher.NewCFBEncrypter(block, iv)
|
||||||
|
stream.XORKeyStream(encrypted[aes.BlockSize:], origData)
|
||||||
|
return encrypted
|
||||||
|
}
|
||||||
|
func AesDecryptCFB(encrypted []byte, key []byte) (decrypted []byte) {
|
||||||
|
block, _ := aes.NewCipher(key)
|
||||||
|
if len(encrypted) < aes.BlockSize {
|
||||||
|
panic("ciphertext too short")
|
||||||
|
}
|
||||||
|
iv := encrypted[:aes.BlockSize]
|
||||||
|
encrypted = encrypted[aes.BlockSize:]
|
||||||
|
|
||||||
|
stream := cipher.NewCFBDecrypter(block, iv)
|
||||||
|
stream.XORKeyStream(encrypted, encrypted)
|
||||||
|
return encrypted
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/golang-jwt/jwt/v4"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
var data = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY2hvb2xpZCI6Ijk5OSIsImV4cCI6MTY3MDcxMzk3OSwidXNlcm5hbWUiOiLllJDlrociLCJjb3Vyc2VzIjoiLDMyLDQsMzgsMzcsNDIsNDMsOSw0MCw0MSwxMSwxMiwxMyw0NCwxNCwxOSwyNiwyOSIsInNjaG9vbG5hbWUiOiLluIzlhoDlnKjnur8iLCJ1c2VyaWQiOiJjZ190YW5neXUiLCJjb2xsZWdlbmFtZSI6IuWtpuefpeahpSIsImhvbWVwYWdlIjoiaHR0cHM6Ly85OTkuYmQuZWR1Y2cubmV0LyJ9.fB3-L-gEOXVlyjjZqphkORtGCRK4ZWI9RNxO4-FULhw"
|
||||||
|
var key = "!bd832W0@CG"
|
||||||
|
|
||||||
|
type CGJWTClaim struct {
|
||||||
|
jwt.RegisteredClaims
|
||||||
|
Userid string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
jwtResult, err := jwt.ParseWithClaims(data, &CGJWTClaim{}, func(token *jwt.Token) (i interface{}, err error) {
|
||||||
|
return []byte(key), nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("err1")
|
||||||
|
}
|
||||||
|
if claims, ok := jwtResult.Claims.(*CGJWTClaim); ok && jwtResult.Valid { // 校验token
|
||||||
|
log.Println("user id", claims.Userid)
|
||||||
|
} else {
|
||||||
|
log.Error("err 2")
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue