2

I'm trying to generate a token with a rsa key using the jwt-go package in golang.

Here there is a blog explaining how to do it but that code will always be validating all tokens because is using the public key stored in the server and is not obtaining it from the token. How do you put the complete public key in the token? I was trying this:

var secretKey, _ = rsa.GenerateKey(rand.Reader, 1024)
token := jwt.New(jwt.SigningMethodRS256)
token.Claims["username"] = "victorsamuelmd"
token.Claims["N"] = secretKey.PublicKey.N
token.Claims["E"] = secretKey.PublicKey.E

tokenString, err := token.SignedString(secretKey)

nt, err := jwt.Parse(tokenString, func(t *jwt.Token) (interface{}, error) {
    // here I need to recover the public key from the token
    // but N is a big.Int and the token stores N as int64
})

Sorry about my english. Thanks.

Grokify
  • 15,092
  • 6
  • 60
  • 81
victorsamuelmd
  • 39
  • 1
  • 1
  • 3
  • 1
    The example in the blog in incomplete. When he calls jwt.ParseFromRequest he would actually verify the signatures match. Do you want to have a use JWT for symmetric key signature authentication? If you do, then in the KeyFunc passed into jwt.ParseFromRequest you should extract the publickey from the claims.. look up the private key in your datastore.. recreate the signature and then compare it to the one in the jwt – icchanobot Mar 20 '15 at 06:01
  • 1
    Nop, I wanted asymetric key signature using the crypto/rsa package from go. – victorsamuelmd Mar 20 '15 at 13:48
  • 1
    oh ok.. i dont think that strictly jwt anymore then.. but you need to remember that the claims are sent inside json i.e. its not really stored as int64.. its just parsed as int64, so you can probably just cast it – icchanobot Mar 22 '15 at 08:41

1 Answers1

3

I think storing the public key in the claims is not good idea because we can verify the JWT with that key technically, but it means it is not a signed JWT anymore. If anyone can generate the JWT with their own private key and storing the public key in JWT, we cannot sure who is signer.

Anyway, you can convert the public key into PEM format which is just a string, and store it in claims. In client side, you can also simply parse it again into public key format. The sample code is below:

privateKey, _ := rsa.GenerateKey(rand.Reader, 1024)
bytes, _ := x509.MarshalPKIXPublicKey(&privateKey.PublicKey)
pem := pem.EncodeToMemory(&pem.Block{
    Type:  "RSA PUBLIC KEY",
    Bytes: bytes,
})
claim["publickey"] = string(pem)

and

pem := []byte(claims["publickey"].(string))
return jwt.ParseRSAPublicKeyFromPEM(pem)

jwt is dgrijalva's jwt-go.

sio4
  • 413
  • 1
  • 5
  • 15
  • 1
    Not always. It's a widespread practice to put a public key as a header or a claim inside jwt token. Validation service needs to validate an issuer or use, for example, using CA center. A good example of that is PASSporTs STIR/SHAKEN protocol that is being used with any phone call around the USA – kkost Jun 17 '21 at 17:02