Skip to content

Instantly share code, notes, and snippets.

@raypendergraph
Created November 2, 2021 14:32
Show Gist options
  • Save raypendergraph/86c24e47cd6959e933435d17e21a9003 to your computer and use it in GitHub Desktop.
Save raypendergraph/86c24e47cd6959e933435d17e21a9003 to your computer and use it in GitHub Desktop.
Simple JWT demo in Go
package main
import (
"crypto"
"crypto/rsa"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"math/big"
"math/rand"
"strings"
)
type jo = map[string]interface{}
func Encode(bytes []byte) string {
return strings.TrimRight(base64.URLEncoding.EncodeToString([]byte(bytes)), "=")
}
func asJwk(k rsa.PublicKey) jo {
// https://tools.ietf.org/html/rfc7518#section-6.3.1
jwk := make(jo)
jwk["kty"] = "RSA"
jwk["use"] = "sig"
n := base64.RawURLEncoding.EncodeToString(k.N.Bytes())
jwk["n"] = n
e := base64.RawURLEncoding.EncodeToString(big.NewInt(int64(k.E)).Bytes())
jwk["e"] = e
hasher := crypto.SHA256.New()
// The format of this string is not specified in the spec
// it just needs to identify the key uniquely.
hasher.Write([]byte("RSA"+ n + e ))
jwk["kid"] = base64.RawURLEncoding.EncodeToString(hasher.Sum(nil))
return jwk
}
func main() {
header := Encode([]byte(`
{
"alg": "RS256",
"typ": "JWT"
}
`))
claims := Encode([]byte(`
{
"kid": "hvYX6j4L6nVFn08QR12g_co_x9MhpjLP4ymdUCoqB-k",
"sub": "1234567890",
"name": "Jane Doe",
"iat": 1516239022
}`))
prng := rand.New(rand.NewSource(42))
rsaKey, err := rsa.GenerateKey(prng, 2048)
if err != nil {
print(err)
}
hasher := sha256.New()
signedStr := strings.Join([]string{header, claims}, ".")
hasher.Write([]byte(signedStr))
if sigBytes, err := rsa.SignPKCS1v15(prng, rsaKey, crypto.SHA256, hasher.Sum(nil)); err == nil {
jwk := asJwk(rsaKey.PublicKey)
if jwkBytes, err := json.Marshal(&jwk); err == nil {
println(string(jwkBytes))
}
println("-------------")
println(strings.Join([]string{signedStr, Encode(sigBytes)}, "."))
} else {
print(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment