Golang令牌验证错误 [英] Golang token validation error

查看:169
本文介绍了Golang令牌验证错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要验证一个google id_token,并且一步涉及检查令牌签名。

首先,我从以下网址获取证书: https ://www.googleapis.com/oauth2/v2/certs 并从证书中提取模数(n)和指数(e)部分并生成一个公钥,然后拆分令牌(头部,有效载荷然后我将解码的 header.payload 连同Google pKey +摘要一起发送到rsa函数 rsa.VerifyPKCS1v15



我被这个验证错误卡住了: crypto / rsa:验证错误



下面是代码(我评论了 //验证失败失败的代码部分):

  func ValidateIDToken(auth_token string)(err error){
res,err:= http.Get(https://www.googleapis.com/oauth2/ v2 / certs)
if err!= nil {
log.Fatal(err)
return err
}

certs,err:= ioutil .ReadAll(res.Body)
res.Body.Close()
if err!= nil {
log.Fatal(err)
return err
}

//从cert
获取模数和指数var goCertificate接口{}
$ b err = json.Unmarshal(certs,& goCertificate)
k: (b):[b]:[b] = [b] [b] [b] (map [string] interface {})[n]
g:= x。(map [string] interface {})[ e]
e64:= base64.StdEncoding
//建立google pub key
nStr:= h。(string)
decN,err:= base64.StdEncoding。 DecodeString(nStr)
if err!= nil {
log.Println(err)
return
}

n:= big.NewInt(0)
n.SetBytes(decN)
eStr:= g。(string)
decE,err:= base64.StdEncoding.DecodeString(eStr)
if err!= nil {
log.Println(err)
return
}

var eBytes [] byte
if len(decE)< 8 {
eBytes = make([] byte,8-len(decE),8)
eBytes = append(eBytes,decE ...)
} else {
eBytes = decE
}

eReader:= bytes.NewReader(eBytes)
var e uint64
err = binary.Read(eReader,binary.BigEndian,& e )
if err!= nil {
log.Println(err)
return
}

pKey:= rsa.PublicKey {N:n, E:int(e)}
w:= strings.SplitAfter(auth_token,。)
for i,val:= range w {
w [i] = strings.Trim(val, 。)
}
y:= w [0:2]

//只加入头两部分,头部和没有签名的负载
o := bytes.Join(y,。)
headerOauth:= DecodeB64(nil,[] byte(w [0]),e64)
inblockOauth:= DecodeB64(nil,[] byte w [1]),e64)
toHash:= string(headerOauth)+}。 + string(inblockOauth)
digestOauth:= DecodeB64(nil,[] byte(w [2]),e64)
$ b hasherOauth:= sha256.New()
hasherOauth。 Write([] byte(toHash))

//此处验证失败
err = rsa.VerifyPKCS1v15(& pKey,crypto.SHA256,hasherOauth.Sum(nil),digestOauth)

if err!= nil {
log.Printf(错误验证键%s,err.Error())
返回错误
}
返回错误
}

更新1:
这里是包含头部和有效载荷的哈希变量:

  {alg:RS256,kid:d91c503452d0f8849200a321ffbf7dea76f9371d } { ISS: accounts.google.com, 子: 104869993929250743503, AZP: client_email_till _ @ apps.googleusercontent.com。, 电子邮件: test@test.hr at_hash: KAm1M0g-ssMkdjds7jkbVQ, email_verified:真实的, 澳元:client_email_till _ @ apps.googleusercontent.com, HD: test.hr, IAT:1412246551, EXP: 1412250451} 

更新2:
感谢@Florent Morselli的回复,我再次尝试了它并且失败了,这次我只对第三部分(签名)进行了B64解码,但错误仍然存​​在,有人可以测试它与他们的
auth_token,只需将ID标记放在代码中的auth_token变量下面,让我知道它是否工作,谢谢。

  package main 
import(
strings
encoding / binary
errors
fmt
日志
编码/ base64
io / ioutil
加密
crypto / sha256
crypto / rsa
字节
encoding / json
net / http
math / big



func main {
auth_token:=
w:= strings.SplitAfter(auth_token,。)
for i,val:= range w {
w [i] = strings.Trim (val,。)
}
headerOauth,err:= base64.URLEncoding.DecodeString(w [0])

res,err:= http.Get( H ttps://www.googleapis.com/oauth2/v2/certs)
if err!= nil {
fmt.Println(err)
}

certs,err:= ioutil.ReadAll(res.Body)
res.Body.Close()
if err!= nil {
fmt.Println(err)
}

//从标头中提取孩子
var header interface {}
$ b err = json.Unmarshal([] byte(string(headerOauth)+}) ,& header)

token_kid:= header。(map [string] interface {})[kid]
fmt.Println(By 1)
/ /获得来自证书

的模数和指数var goCertificate接口{}
$ b err = json.Unmarshal(certs,& goCertificate)

/ / k:= goCertificate。(map [string] interface {})[token_kid。(string)]
k:= goCertificate。(map [string] interface {})[keys]

/// * mod& exp部分
j:= k。([] interface {})
x:= j [0]

if j [0]。(map [string] interface {}) [kid] == token_kid {
x = j [0]
} else {
if j [1]。(map [string] interface {})[kid] = = token_kid {
x = j [1]
} else {
errors.New(Token is not valid,kid from token and certificate do not match)



h:= x。(map [string] interface {})[n]
g:= x。(map [string] interface {})[e ]

//建立google pub key
nStr:= h。(string)
decN,err:= base64.URLEncoding.DecodeString(nStr)
if err!= nil {
fmt.Println(err)
return
}

n:= big.NewInt(0)
n.SetBytes( decN)
eStr:= g。(string)
decE,err:= base64.URLEncoding.DecodeString(eStr)
if err!= nil {
fmt.Println(err )
返回
}

var eBytes [] byte
if len (decE) 8 {
eBytes = make([] byte,8-len(decE),8)
eBytes = append(eBytes,decE ...)
} else {
eBytes = decE
}

eReader:= bytes.NewReader(eBytes)
var e uint64
err = binary.Read(eReader,binary.BigEndian,& e )
if err!= nil {
log.Println(err)
return
}

pKey:= rsa.PublicKey {N:n, E:int(e)}
// inblockOauth:= base64.URLEncoding.DecodeString(w [1])$ ​​b $ b toHash:= w [0] +。 + w [1]
digestOauth,err:= base64.URLEncoding.DecodeString(w [2])

hasherOauth:= sha256.New()
hasherOauth.Write([ ] byte(toHash))

//此处验证失败
err = rsa.VerifyPKCS1v15(& pKey,crypto.SHA256,hasherOauth.Sum(nil),digestOauth)

if err!= nil {
fmt.Printf(Error verifying key%s,err.Error())

}

}


解决方案

正如聊天中所解释的,问题在于如果缺少=,Base64解码器无法解码头和签名。



您只需将它们添加到以下代码:

  if m:= len(h_)%4; m!= 0 {
h_ + = strings.Repeat(=,4-m)
}

以下是完整的代码:

 包主
导入(
字符串
encoding / binary
错误
fmt
log
编码/ base64
io / ioutil
crypto
crypto / sha256
crypto / rsa
bytes
encoding / json
net / http
math / big



func main(){
auth_token:=
w:= strings.Split (auth_token,。)
h_,s_:= w [0],w [2]

if m:= len(h_)%4; m!= 0 {
h_ + = strings.Repeat(=,4-m)
}
if m:= len(s_)%4; m!= 0 {
s_ + = strings.Repeat(=,4-m)
}

headerOauth,err:= base64.URLEncoding.DecodeString(h_)

res,err:= http.Get(https://www.googleapis.com/oauth2/v2/certs)
if err!= nil {
fmt .Println(err)
}

certs,err:= ioutil.ReadAll(res.Body)
res.Body.Close()
if err!=无{
fmt.Println(err)
}

//从标头中提取孩子
var header界面{}

err = json.Unmarshal([] byte(string(headerOauth)),& header)

token_kid:= header。(map [string] interface {})[kid]
fmt.Println(By 1)
//获取来自证书的模数和指数
$ b var goCertificate接口{}

err = json.Unmarshal(certs ,& goCertificate)

// k:= goCertificate。(map [string] interface {})[token_kid。(string)]
k:= goCertificate。(map [string] interface {})[keys]

/// * mod& exp部分
j:= k。([] interface {})
x:= j [0]

if j [0]。(map [string] interface {}) [kid] == token_kid {
x = j [0]
} else {
if j [1]。(map [string] interface {})[kid] = = token_kid {
x = j [1]
} else {
errors.New(Token is not valid,kid from token and certificate do not match)



h:= x。(map [string] interface {})[n]
g:= x。(map [string] interface {})[e ]

//建立google pub key
nStr:= h。(string)
decN,err:= base64.URLEncoding.DecodeString(nStr)
if err!= nil {
fmt.Println(err)
return
}

n:= big.NewInt(0)
n.SetBytes( decN)
eStr:= g。(string)
decE,err:= base64.URLEncoding.DecodeString(eStr)
if err!= nil {
fmt.Println(err )
返回
}

var eBytes [] byte
if len (decE) 8 {
eBytes = make([] byte,8-len(decE),8)
eBytes = append(eBytes,decE ...)
} else {
eBytes = decE
}

eReader:= bytes.NewReader(eBytes)
var e uint64
err = binary.Read(eReader,binary.BigEndian,& e )
if err!= nil {
log.Println(err)
return
}

pKey:= rsa.PublicKey {N:n, E:int(e)}
// inblockOauth:= base64.URLEncoding.DecodeString(w [1])$ ​​b $ b toHash:= w [0] +。 + w [1]
digestOauth,err:= base64.URLEncoding.DecodeString(s_)
$ b $ hasherOauth:= sha256.New()
hasherOauth.Write([] byte toHash))

//验证签名
err = rsa.VerifyPKCS1v15(& pKey,crypto.SHA256,hasherOauth.Sum(nil),digestOauth)


if err!= nil {
fmt.Printf(Error verificationing key%s,err.Error())
}
fmt.Printf(OK! )
}


I need to validate a google id_token and one step involves to check the token signature.

First I obtain the certificate from: https://www.googleapis.com/oauth2/v2/certs and extract the modulus (n) and exponent (e) part from the certificate and generate a public key, then I take apart the token (header, payload and digest), after then I send the decoded header.payload together with the Google pKey + digest to the rsa function rsa.VerifyPKCS1v15.

I am stuck with this verification error: crypto/rsa: verification error

Here's the code (I commented part of code which fails with // validation here fails):

func ValidateIDToken(auth_token string) (err error){    
    res, err := http.Get("https://www.googleapis.com/oauth2/v2/certs")
    if err != nil {
        log.Fatal(err)
        return err
    }

    certs, err := ioutil.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
        log.Fatal(err)
        return err
    }

    //get modulus and exponent from the cert
    var goCertificate interface{}

    err = json.Unmarshal(certs, &goCertificate)    
    k := goCertificate.(map[string]interface{})["keys"]
    j := k.([]interface{})
    x := j[1]
    h := x.(map[string]interface{})["n"]
    g := x.(map[string]interface{})["e"]
    e64 := base64.StdEncoding
    //build the google pub key
    nStr := h.(string)
    decN, err := base64.StdEncoding.DecodeString(nStr)
    if err != nil {
        log.Println(err)
        return
    }

    n := big.NewInt(0)
    n.SetBytes(decN)
    eStr := g.(string)
    decE, err := base64.StdEncoding.DecodeString(eStr)
    if err != nil {
        log.Println(err)
        return
    }

    var eBytes []byte
    if len(decE) < 8 {
        eBytes = make([]byte, 8-len(decE), 8)
        eBytes = append(eBytes, decE...)
    } else {
        eBytes = decE
    }

    eReader := bytes.NewReader(eBytes)
    var e uint64
    err = binary.Read(eReader, binary.BigEndian, &e)
    if err != nil {
        log.Println(err)
        return
    }

    pKey := rsa.PublicKey{N: n, E: int(e)}
    w := strings.SplitAfter(auth_token, ".")    
    for i, val := range w {
        w[i] = strings.Trim(val, ".")
    }
    y := w[0:2]

    //Join just the first two parts, the header and the payload without the signature
    o := strings.Join(y, ".")   
    headerOauth := DecodeB64(nil,[]byte(w[0]),e64)
    inblockOauth := DecodeB64(nil,[]byte(w[1]),e64)
    toHash := string(headerOauth) + "}." + string(inblockOauth)
    digestOauth := DecodeB64(nil, []byte(w[2]),e64)

    hasherOauth := sha256.New()
    hasherOauth.Write([]byte(toHash))

    // validation here fails
    err = rsa.VerifyPKCS1v15(&pKey,crypto.SHA256,hasherOauth.Sum(nil),digestOauth)

    if err != nil {
        log.Printf("Error verifying key %s",err.Error())
        return err
    }
    return err
}

UPDATE 1: Here is toHash var which contains header and payload:

{"alg":"RS256","kid":"d91c503452d0f8849200a321ffbf7dea76f9371d"}.{"iss":"accounts.google.com","sub":"104869993929250743503","azp":"client_email_till_@.apps.googleusercontent.com","email":"test@test.hr","at_hash":"KAm1M0g-ssMkdjds7jkbVQ","email_verified":true,"aud":client_email_till_@.apps.googleusercontent.com","hd":"test.hr","iat":1412246551,"exp":1412250451}

UPDATE 2: Thanks for the reply @Florent Morselli, I tried it again and it failed, I B64decoded this time only the third part (signature) but the error was still there, could someone test it with their auth_token, just put the ID token in auth_token variable below in the code, and let me know if it worked, thank You.

package main
import(
    "strings"
    "encoding/binary"
    "errors"
    "fmt"
    "log"
    "encoding/base64"
    "io/ioutil"
    "crypto"    
    "crypto/sha256"
    "crypto/rsa"
    "bytes"
    "encoding/json"
    "net/http"
    "math/big"  

)

func main() {
    auth_token := ""
    w := strings.SplitAfter(auth_token, ".")    
    for i, val := range w {
        w[i] = strings.Trim(val, ".")
    }
    headerOauth, err := base64.URLEncoding.DecodeString(w[0])

    res, err := http.Get("https://www.googleapis.com/oauth2/v2/certs")
    if err != nil {
        fmt.Println(err)
    }

    certs, err := ioutil.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
        fmt.Println(err)
    }

    //extract kid from token header
    var header interface{}

    err = json.Unmarshal([]byte(string(headerOauth)+"}"), &header)

    token_kid := header.(map[string]interface{})["kid"]
    fmt.Println("By 1")
    //get modulus and exponent from the cert

    var goCertificate interface{}

    err = json.Unmarshal(certs, &goCertificate)    

    //k := goCertificate.(map[string]interface{})[token_kid.(string)]
    k := goCertificate.(map[string]interface{})["keys"]

    ///*mod & exp part
    j := k.([]interface{})
    x := j[0]

    if j[0].(map[string]interface{})["kid"] == token_kid {
        x = j[0]
    }else{
        if j[1].(map[string]interface{})["kid"] == token_kid {
            x = j[1]
        }else{
            errors.New("Token is not valid, kid from token and certificate don't match")

        }
    }
    h := x.(map[string]interface{})["n"]
    g := x.(map[string]interface{})["e"]

    //build the google pub key
    nStr := h.(string)
    decN, err := base64.URLEncoding.DecodeString(nStr)
    if err != nil {
        fmt.Println(err)
        return
    }

    n := big.NewInt(0)
    n.SetBytes(decN)
    eStr := g.(string)
    decE, err := base64.URLEncoding.DecodeString(eStr)
    if err != nil {
        fmt.Println(err)
        return
    }

    var eBytes []byte
    if len(decE) < 8 {
        eBytes = make([]byte, 8-len(decE), 8)
        eBytes = append(eBytes, decE...)
    } else {
        eBytes = decE
    }

    eReader := bytes.NewReader(eBytes)
    var e uint64
    err = binary.Read(eReader, binary.BigEndian, &e)
    if err != nil {
        log.Println(err)
        return
    }

    pKey := rsa.PublicKey{N: n, E: int(e)}
        //inblockOauth := base64.URLEncoding.DecodeString(w[1])
    toHash := w[0] + "." + w[1]
    digestOauth, err := base64.URLEncoding.DecodeString(w[2])

    hasherOauth := sha256.New()
    hasherOauth.Write([]byte(toHash))

    // verification here fails
    err = rsa.VerifyPKCS1v15(&pKey,crypto.SHA256,hasherOauth.Sum(nil),digestOauth)

    if err != nil {
        fmt.Printf("Error verifying key %s",err.Error())

    }

}

解决方案

As explained on the chat, the problem is that the Base64 decoder is unable to decode the header and the signature if they are missing "=".

You just have to add them with the following code:

    if m := len(h_) % 4; m != 0 {
        h_ += strings.Repeat("=", 4-m)
    }

Here is the complete code:

package main
import(
    "strings"
    "encoding/binary"
    "errors"
    "fmt"
    "log"
    "encoding/base64"
    "io/ioutil"
    "crypto"    
    "crypto/sha256"
    "crypto/rsa"
    "bytes"
    "encoding/json"
    "net/http"
    "math/big"  

)

func main() {
    auth_token := ""
    w := strings.Split(auth_token, ".")    
    h_, s_ := w[0], w[2]

    if m := len(h_) % 4; m != 0 {
        h_ += strings.Repeat("=", 4-m)
    }
    if m := len(s_) % 4; m != 0 {
        s_ += strings.Repeat("=", 4-m)
    }

    headerOauth, err := base64.URLEncoding.DecodeString(h_)

    res, err := http.Get("https://www.googleapis.com/oauth2/v2/certs")
    if err != nil {
        fmt.Println(err)
    }

    certs, err := ioutil.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
        fmt.Println(err)
    }

    //extract kid from token header
    var header interface{}

    err = json.Unmarshal([]byte(string(headerOauth)), &header)

    token_kid := header.(map[string]interface{})["kid"]
    fmt.Println("By 1")
    //get modulus and exponent from the cert

    var goCertificate interface{}

    err = json.Unmarshal(certs, &goCertificate)    

    //k := goCertificate.(map[string]interface{})[token_kid.(string)]
    k := goCertificate.(map[string]interface{})["keys"]

    ///*mod & exp part
    j := k.([]interface{})
    x := j[0]

    if j[0].(map[string]interface{})["kid"] == token_kid {
        x = j[0]
    }else{
        if j[1].(map[string]interface{})["kid"] == token_kid {
            x = j[1]
        }else{
            errors.New("Token is not valid, kid from token and certificate don't match")

        }
    }
    h := x.(map[string]interface{})["n"]
    g := x.(map[string]interface{})["e"]

    //build the google pub key
    nStr := h.(string)
    decN, err := base64.URLEncoding.DecodeString(nStr)
    if err != nil {
        fmt.Println(err)
        return
    }

    n := big.NewInt(0)
    n.SetBytes(decN)
    eStr := g.(string)
    decE, err := base64.URLEncoding.DecodeString(eStr)
    if err != nil {
        fmt.Println(err)
        return
    }

    var eBytes []byte
    if len(decE) < 8 {
        eBytes = make([]byte, 8-len(decE), 8)
        eBytes = append(eBytes, decE...)
    } else {
        eBytes = decE
    }

    eReader := bytes.NewReader(eBytes)
    var e uint64
    err = binary.Read(eReader, binary.BigEndian, &e)
    if err != nil {
        log.Println(err)
        return
    }

    pKey := rsa.PublicKey{N: n, E: int(e)}
        //inblockOauth := base64.URLEncoding.DecodeString(w[1])
    toHash := w[0] + "." + w[1]
    digestOauth, err := base64.URLEncoding.DecodeString(s_)

    hasherOauth := sha256.New()
    hasherOauth.Write([]byte(toHash))

    // verification of the signature
    err = rsa.VerifyPKCS1v15(&pKey,crypto.SHA256,hasherOauth.Sum(nil),digestOauth)


    if err != nil {
        fmt.Printf("Error verifying key %s",err.Error())
    }
    fmt.Printf("OK!")
}

这篇关于Golang令牌验证错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆