golang JWT没有签名。 " crypto / rsa:验证错误"

时间:2015-07-02 22:08:59

标签: ssl go rsa token jwt

我正在使用JWT。这就是我创建令牌的方式。

func createToken(user User) (string, error) {
    token := jwt.New(jwt.GetSigningMethod("RS256"))

    token.Claims["Name"] = user.Name
    token.Claims["Email"] = user.Email
    //token.Claims["ExpDate"] = time.Now().Add(time.Hour * 1).Unix()

    tokenString, err := token.SignedString([]byte(config.PrivateKey))
    if err != nil {
        return "", err
    }

    return tokenString, nil
}

这是我验证令牌的方式。

token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {    
        return []byte(config.PublicKey), nil
    })

我用这个python代码

生成了我的公钥和私钥
from Crypto.PublicKey import RSA

private = RSA.generate(1024)
public  = private.publickey()

priv = private.exportKey()
pub = public.exportKey()

我得到crypto/rsa: verification error。当我打印解析后的令牌时,除了token.Valid之外,一切看起来都很好,这是假的,token.Signature是空的。

type Token struct {
    Raw       string                 // The raw token.  Populated when you Parse a token
    Method    SigningMethod          // The signing method used or to be used
    Header    map[string]interface{} // The first segment of the token
    Claims    map[string]interface{} // The second segment of the token
    Signature string                 // The third segment of the token.  Populated when you Parse a token
    Valid     bool                   // Is the token valid?  Populated when you Parse/Verify a token
}

tokenString--> eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJFbWFpbCI6InRlc3RAaG90bWFpbC5jb20iLCJOYW1lIjoidGVzdE5hbWUifQ.fgd1h4LB1zzAiPFLKMOJrQu12rTLeXBDKHdnqiNc04NRn-1v7cHEQpDNawvScMIGrcQLbZo6WrldZQT9ImYWpUyy3CcD2uMO95I5PN6aXOSPb26nNGQpmIi1HNZrq5359hKZ6BWEJnW9iTg7RgmMvZGmIqlGLsOY2a6UiiwBsI0
token.Raw--> eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJFbWFpbCI6InRlc3RAaG90bWFpbC5jb20iLCJOYW1lIjoidGVzdE5hbWUifQ.fgd1h4LB1zzAiPFLKMOJrQu12rTLeXBDKHdnqiNc04NRn-1v7cHEQpDNawvScMIGrcQLbZo6WrldZQT9ImYWpUyy3CcD2uMO95I5PN6aXOSPb26nNGQpmIi1HNZrq5359hKZ6BWEJnW9iTg7RgmMvZGmIqlGLsOY2a6UiiwBsI0
token.Header--> map[alg:RS256 typ:JWT]
token.Claims--> map[Email:test@hotmail.com Name:testName]
token.Signature-->           
token.Valid--> false

PS:我没有任何SSL证书。

1 个答案:

答案 0 :(得分:0)

这对我有用。我使用这些命令生成了private.pem和public.pem。

openssl genrsa -des3 -out private.pem 1024
openssl rsa -in private.pem -outform PEM -pubout -out public.pem

代码:

package main

import (
    "fmt"
    "github.com/dgrijalva/jwt-go"
    "io/ioutil"
    "log"
    "time"
)

//Claims can have user id.. etc for Identification purpose
type AppClaims struct {
    UserId string `json:"userId"`
    jwt.StandardClaims
}

var (
    privateKey []byte
    publicKey  []byte
    err        error
)

const (
    longForm = "Jan 2, 2006 at 3:04pm (MST)"
)

func errLog(err error) {
    if err != nil {
        log.Fatal("Error:", err.Error())
    }
}

func init() {
    privateKey, err = ioutil.ReadFile("../private.pem")
    errLog(err)
    publicKey, err = ioutil.ReadFile("../public.pem")
    errLog(err)
}

func jwtTokenGen() (interface{}, error) {
    privateRSA, err := jwt.ParseRSAPrivateKeyFromPEM(privateKey)
    if err != nil {
        return nil, err
    }
    claims := AppClaims{
        "RAJINIS*",
        jwt.StandardClaims{
            ExpiresAt: time.Now().Add(time.Minute * 15).Unix(),
            Issuer:    "test",
        },
    }
    token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
    ss, err := token.SignedString(privateRSA)
    return ss, err
}

func jwtTokenRead(inToken interface{}) (interface{}, error) {
    publicRSA, err := jwt.ParseRSAPublicKeyFromPEM(publicKey)
    if err != nil {
        return nil, err
    }
    token, err := jwt.Parse(inToken.(string), func(token *jwt.Token) (interface{}, error) {
        if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
            return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
        }
        return publicRSA, err
    })

    if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
        return claims, nil
    } else {
        return nil, err
    }
}

func getTokenRemainingValidity(timestamp interface{}) int {
    expireOffset := 0
    if validity, ok := timestamp.(float64); ok {
        tm := time.Unix(int64(validity), 0)
        remainder := tm.Sub(time.Now())
        if remainder > 0 {
            fmt.Println(remainder)
            return int(remainder.Seconds()) + expireOffset
        }
    }
    return expireOffset
}

func main() {
    signedString, err := jwtTokenGen()
    fmt.Println(signedString, err)
    claims, err := jwtTokenRead(signedString)
    if err != nil {
        errLog(err)
    }
    claimValue := claims.(jwt.MapClaims)
    fmt.Println(claimValue["iss"], claimValue["exp"], claimValue["userId"])
    //  t, _ := time.Parse(longForm, string(claimValue["exp"].(float64)))
    fmt.Println(getTokenRemainingValidity(claimValue["exp"]))
}