与 public 和私钥以及 JWT 相关的混淆
Confusion relating to public and private keys and JWT
我正在 Go 网络服务中试用 JWT(JSON 网络令牌)。这是我到目前为止所做的:
package jwt
import(
"fmt"
"net/http"
"github.com/gorilla/mux"
"github.com/dgrijalva/jwt-go"
"io/ioutil"
)
var privateKey []byte
var publicKey []byte
func JSONWebTokensHandler(w http.ResponseWriter, r * http.Request){
// Create the token
encodeToken := jwt.New(jwt.SigningMethodHS256)
// Set some claims
encodeToken.Claims["Latitude"] = "25.000"
encodeToken.Claims["Longitude"] = "27.000"
// Sign and get the complete encoded token as a string
tokenString, err := encodeToken.SignedString(privateKey)
decodeToken, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return publicKey,nil
})
if decodeToken.Valid {
fmt.Fprintf(w,"Lat: %s, Lng: %s",decodeToken.Claims["Latitude"],decodeToken.Claims["Longitude"])
} else {
fmt.Fprintf(w,"Couldn't handle this token: %s", err)
}
}
func init(){
privateKey,_ = ioutil.ReadFile("demo.rsa")
publicKey,_ = ioutil.ReadFile("demo.rsa.pub")
r := mux.NewRouter()
r.HandleFunc("/jwt",JSONWebTokensHandler).Methods("GET")
http.Handle("/", r)
}
现在,如果我的理解是正确的,可以使用 public 密钥对使用私钥编码的令牌进行解码。这就是我在上面的代码中假定的,但是当我 运行 我得到错误的代码时:
Couldn't handle this token: signature is invalid
如果我使用相同的密钥进行编码和解码,则代码有效。
我想知道的是,是我的理解有问题还是代码有问题?
JWT 未使用 RSA 等非对称密码进行签名。它使用 HMAC,它使用单个秘密密钥。事实上,这里的重点不是向其他人证明你签署了令牌。向自己证明是你签名的,从而禁止任何没有你的密钥的人修改令牌。
您正在使用 jwt.SigningMethodHMAC.
因此,您正在使用 HMAC 进行签名,签名是由对称密钥(秘密)加密的令牌。
您应使用:jwt.New(jwt.SigningMethodRS256)
使用非对称密钥对进行签名。
非常有趣,因为我有一个类似的问题,当我有微服务和客户端应用程序需要验证来自另一个内部服务器的令牌时,所以如果你建议使用 HMAC 而不是 RSA,那意味着我需要把私钥同时放在微服务和客户端?那不会是一个严重的安全漏洞吗?
我正在 Go 网络服务中试用 JWT(JSON 网络令牌)。这是我到目前为止所做的:
package jwt
import(
"fmt"
"net/http"
"github.com/gorilla/mux"
"github.com/dgrijalva/jwt-go"
"io/ioutil"
)
var privateKey []byte
var publicKey []byte
func JSONWebTokensHandler(w http.ResponseWriter, r * http.Request){
// Create the token
encodeToken := jwt.New(jwt.SigningMethodHS256)
// Set some claims
encodeToken.Claims["Latitude"] = "25.000"
encodeToken.Claims["Longitude"] = "27.000"
// Sign and get the complete encoded token as a string
tokenString, err := encodeToken.SignedString(privateKey)
decodeToken, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return publicKey,nil
})
if decodeToken.Valid {
fmt.Fprintf(w,"Lat: %s, Lng: %s",decodeToken.Claims["Latitude"],decodeToken.Claims["Longitude"])
} else {
fmt.Fprintf(w,"Couldn't handle this token: %s", err)
}
}
func init(){
privateKey,_ = ioutil.ReadFile("demo.rsa")
publicKey,_ = ioutil.ReadFile("demo.rsa.pub")
r := mux.NewRouter()
r.HandleFunc("/jwt",JSONWebTokensHandler).Methods("GET")
http.Handle("/", r)
}
现在,如果我的理解是正确的,可以使用 public 密钥对使用私钥编码的令牌进行解码。这就是我在上面的代码中假定的,但是当我 运行 我得到错误的代码时:
Couldn't handle this token: signature is invalid
如果我使用相同的密钥进行编码和解码,则代码有效。
我想知道的是,是我的理解有问题还是代码有问题?
JWT 未使用 RSA 等非对称密码进行签名。它使用 HMAC,它使用单个秘密密钥。事实上,这里的重点不是向其他人证明你签署了令牌。向自己证明是你签名的,从而禁止任何没有你的密钥的人修改令牌。
您正在使用 jwt.SigningMethodHMAC.
因此,您正在使用 HMAC 进行签名,签名是由对称密钥(秘密)加密的令牌。
您应使用:jwt.New(jwt.SigningMethodRS256)
使用非对称密钥对进行签名。
非常有趣,因为我有一个类似的问题,当我有微服务和客户端应用程序需要验证来自另一个内部服务器的令牌时,所以如果你建议使用 HMAC 而不是 RSA,那意味着我需要把私钥同时放在微服务和客户端?那不会是一个严重的安全漏洞吗?