Golang Jwt key is of invalid type 錯誤的解決方法

golang-jwt/jwt key is of invalid type 錯誤的解決方法

起因:

無意中在github上看到dgrijalva/jwt-go已經(jīng)不在維護(hù)了,而是替換成了golang-jwt/jwt俘枫,所以考慮更新一下新的jwt包健盒,期間各種復(fù)雜,因為只是掃了一眼jwt的源碼褒傅,以為沒什么太大改動,所以以后還是得多看源碼包蛉谜,特此更新一篇筆記

傳送門:新版本go-jwt

直接上源代碼

package jwt

func GetToken(Id string) (string, error) {
    c := MyClaims{
        jwt.StandardClaims{
            Id : Id,
            ExpiresAt: time.Now().Add(TokenExpiration).Unix(),
        },
    }
        
  // 其實問題出在這里 這里會有很多選項 
  // 例如 ParseRSAPrivateKeyFromPEM rsa pkcs8的私鑰解析
  // ParseEdPrivateKeyFromPEM   ed25519 pkcs8的私鑰解析
  // 還有我用的 ParseECPrivateKeyFromPEM ecdsa pkcs8的私鑰解析
  // 這個方法的目的是還原private 對應(yīng)算法的[]byte 數(shù)據(jù)
    priKey, err := jwt.ParseECPrivateKeyFromPEM(privateKey)
    if err != nil {
        return "xxxx", err
    }

    token := jwt.NewWithClaims(jwt.SigningMethodES256, c)
    return token.SignedString(priKey)
}

我們來看一下 token.SignedString(priKey) 的源碼

// Get the complete, signed token 獲取一個已簽名的token
func (t *Token) SignedString(key interface{}) (string, error) {
    var sig, sstr string
    var err error
  // 生成簽名這里不用管
    if sstr, err = t.SigningString(); err != nil {
        return "", err
    }
  // 主要看這里t.Method.Sign 這里是一個接口
    if sig, err = t.Method.Sign(sstr, key); err != nil {
        return "", err
    }
    return strings.Join([]string{sstr, sig}, "."), nil
}

// t.Method.Sign --> 接口
type SigningMethod interface {
    Verify(signingString, signature string, key interface{}) error  // 驗簽
    Sign(signingString string, key interface{}) (string, error)     // 簽名
    Alg() string                                                        // 簽名的hash方式 例如HS256
}

// 那么 SignedString 的這段代碼就是加簽的流程
// 在最上面的代碼塊 GetToken 中  我使用的是 jwt.SigningMethodES256
// 這個是看一個網(wǎng)上的demo 寫的 所以這里也是跟 ParseECPrivateKeyFromPEM 保持一致的 
// 也就是說可以有很多加密方式的選擇 比如 以下相匹配的
// 也就是說jwt/xxx_utils.go ParseXXXPublicKeyFromPEM 
// 對應(yīng) jwt/xxx.go 下的 SigningMethodXXXX SigningMethodXXX
// 例如 rsa 方式加簽 就是 jwt/rsa_utils.go ParseRSAPrivateKeyFromPEMWithPassword / ParseRSAPublicKeyFromPEM 方法 
// 對應(yīng) jwt/rsa.go 下的集中加簽方式
//  SigningMethodRS256 *SigningMethodRSA
//  SigningMethodRS384 *SigningMethodRSA
//  SigningMethodRS512 *SigningMethodRSA
if sig, err = t.Method.Sign(sstr, key); err != nil {
        return "", err
}




以jwt.SigningMethodES256為例

// Implements the Sign method from SigningMethod
// For this signing method, key must be an ecdsa.PrivateKey struct
func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) {
    // Get the key
    var ecdsaKey *ecdsa.PrivateKey // SigningMethodES256 需要的是 ecdsa 加簽算法的私鑰
                                                                // 所以 再遇到 key is of invalid type 這個問題 直接考慮加密方式是否不匹配
    switch k := key.(type) {
    case *ecdsa.PrivateKey:
        ecdsaKey = k
    default:
        return "", ErrInvalidKeyType
    }

    // Create the hasher
    if !m.Hash.Available() {
        return "", ErrHashUnavailable
    }

    hasher := m.Hash.New()
    hasher.Write([]byte(signingString))

    // Sign the string and return r, s
    if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil {
        curveBits := ecdsaKey.Curve.Params().BitSize

        if m.CurveBits != curveBits {
            return "", ErrInvalidKey
        }

        keyBytes := curveBits / 8
        if curveBits%8 > 0 {
            keyBytes += 1
        }

        // We serialize the outputs (r and s) into big-endian byte arrays
        // padded with zeros on the left to make sure the sizes work out.
        // Output must be 2*keyBytes long.
        out := make([]byte, 2*keyBytes)
        r.FillBytes(out[0:keyBytes]) // r is assigned to the first half of output.
        s.FillBytes(out[keyBytes:])  // s is assigned to the second half of output.

        return EncodeSegment(out), nil
    } else {
        return "", err
    }
}

以下附上生成ecdsa的私鑰生成方法,其他算法同理自行處理吧

package main

import (
    "crypto/ecdsa"
    "crypto/elliptic"
    "crypto/rand"
    "crypto/x509"
    "encoding/base64"
    "fmt"
)

func generateEcdsaPrivateKey() (*ecdsa.PrivateKey, error) {
    return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
}

func generatePkcs8PrivateKey(privateKey *ecdsa.PrivateKey) ([]byte, error) {
    return x509.MarshalPKCS8PrivateKey(privateKey)
}

func main() {

    key, err := generateEcdsaPrivateKey()
    if err != nil {
        panic(err)
    }

    pkcs8PrivateKey, err := generatePkcs8PrivateKey(key)
    if err != nil {
        panic(err)
    }

    privateKeyString := base64.StdEncoding.EncodeToString(pkcs8PrivateKey)
    base64PriKey := FormatPrivateKeyFromString(privateKeyString)
    fmt.Println(base64PriKey)
}

func  FormatPrivateKeyFromString(privateKey string) string{
    return fmt.Sprintf("-----BEGIN RSA PRIVATE KEY-----\n%s\n-----END RSA PRIVATE KEY-----", privateKey)
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末部脚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子峡捡,更是在濱河造成了極大的恐慌,老刑警劉巖诀浪,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棋返,死亡現(xiàn)場離奇詭異,居然都是意外死亡雷猪,警方通過查閱死者的電腦和手機(jī)睛竣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來求摇,“玉大人射沟,你說我怎么就攤上這事∮刖常” “怎么了验夯?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長摔刁。 經(jīng)常有香客問我挥转,道長,這世上最難降的妖魔是什么共屈? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任绑谣,我火速辦了婚禮,結(jié)果婚禮上拗引,老公的妹妹穿的比我還像新娘借宵。我一直安慰自己,他們只是感情好矾削,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布壤玫。 她就那樣靜靜地躺著,像睡著了一般哼凯。 火紅的嫁衣襯著肌膚如雪欲间。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天断部,我揣著相機(jī)與錄音猎贴,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛嘱能,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播虱疏,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼惹骂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了做瞪?” 一聲冷哼從身側(cè)響起对粪,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎装蓬,沒想到半個月后著拭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡牍帚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年儡遮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片暗赶。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡鄙币,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蹂随,到底是詐尸還是另有隱情十嘿,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布岳锁,位于F島的核電站绩衷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏激率。R本人自食惡果不足惜咳燕,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望柱搜。 院中可真熱鬧迟郎,春花似錦、人聲如沸聪蘸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽健爬。三九已至控乾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間娜遵,已是汗流浹背蜕衡。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留设拟,地道東北人慨仿。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓久脯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親镰吆。 傳聞我的和親對象是個殘疾皇子帘撰,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355