# Why some encryption keys don't work with the jsonwebtoken NPM package

One would think that any DER encoded keypair should work with the [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) package (which I will from now on just call JWT) from Auth0, but annoying, that is not the case.

See, JWT relies upon Node's crypto library to determine if your key is valid or not... Node does not allow certain DER encoding methods for private & public keys.  
  
Luckily, golang's crypto library only really gives us two DER encoding options for RSA keys. `PKCS1` and `PKCS8` for private keys, and `PKCS1` and `PKIX` for public keys.  
Now the `PKCS#` keys work just fine on Node, the issue is the `PKIX` keys.

These keys aren't actually encoded for the same type of use as the `PKCS#` encoded keys are... *they're meant for the internet, specifically, certificates*. At least, according to [this stackoverflow post](https://stackoverflow.com/a/49878687) from April 17th, 2018.

So, the `PKIX` keys are a different structure and use case than the `PKCS` keys.  
  
They're meant for certificates, not simpler keys.  
So, don't use them for anything which just needs a key.

### How did I figure this out

If you're wondering how I figured this out, it's because [Folderr's CLI](https://github.com/Folderr/foldcli) is written in Go, and I tried using it to setup Folderr's database, and it just kept failing. Folderr would say the key was not asymmetrical, which, apparently it wasn't, because it was meant for a certificate.  
There's a simple way to replicate this issue and see it for yourself

1. Clone [https://github.com/Folderr/jwt-keytests](https://github.com/Folderr/jwt-keytests)
    
2. Use something like a modified version of [foldcli's GenKeys function](https://github.com/Folderr/foldcli/blob/6f230784514e57ee30ee8f2e2823939aaa8e4c7d/utilities/keys.go#L12-L47) (modified to put out both PKIX and PKCS1 public keys)
    
3. Try the `jwt-keytest` with the PKCS1 public key, and PKIX public key
    

---

## Replication

Example of a modified GenKeys function (generates 1 private key, and 2 public keys):

```go
import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
)
// returns Private Key, Public Key (PKCS1), Public Key (PKIX), and error
func GenKeys() ([]byte, []byte, []byte, error) {
	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, nil, nil, err
	}
    // Sanity check the privateKey
	if privateKey.Validate() != nil {
		return nil, nil, nil, privateKey.Validate()
	}
    // You can use PKCS1, I'm sure it doesn't matter.
	privBytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
	if err != nil {
		return nil, nil, nil, err
	}
	privBlock := pem.Block{
		Type:    "RSA PRIVATE KEY",
		Headers: nil,
		Bytes:   privBytes,
	}
	privatePem := pem.EncodeToMemory(&privBlock)

    // Works with nodes jsonwebtoken library
	pubBytes := x509.MarshalPKCS1PublicKey(&privateKey.PublicKey)
	pubBlock := pem.Block{
		Type:    "RSA PUBLIC KEY",
		Headers: nil,
		Bytes:   pubBytes,
	}
	publicPem := pem.EncodeToMemory(&pubBlock)

    // Does not work with node's jsonwebtoken library
    pubPKIX, err := x509.MarshalPKIXPublicKey(&privateKey.PublicKey)
    if err != nil {
        return nil, nil, nil, err
    }
    pubPKIXBlock := pem.Block{
        Type:    "RSA PUBLIC KEY",
        Headers: nil,
        Bytes:   pubPKIX,
    }
    pubPKIXPem := pem.EncodeToMemory(&pubPKIXBlock)
	return privatePem, publicPem, pubPKIXPem, nil
}
```

You'll need to manage the saving files yourself, but, this will generate the correct keys

You can use [Folderr's JWT Keytest repo](https://github.com/Folderr/jwt-keytests) to test these keys

---

### Sources

[https://stackoverflow.com/a/49878687](https://stackoverflow.com/a/49878687)
