1

I am trying to use the .jks file to sign the jwt token. The libraries I am using are pyjwt and pyjks. Below is the code snippets:

        userDto = user
        payload = {
            "iss": "test",
            "exp": datetime.now(tz=timezone.utc) + timedelta(days=365),
            "iat": datetime.now(tz=timezone.utc),
            "nbf": datetime.now(tz=timezone.utc),
            "sub": "testUser",
            "auth": userDto
        }
        keystorePath = os.path.abspath("KeyStore.jks")
        keystorePass = "test"
        keyAlias = "test"
        keystore = jks.KeyStore.load(keystorePath, keystorePass)
        pk = keystore.private_keys[keyAlias]

        encoded = jwt.encode(payload, pk, algorithm="RS512")

While executing the last line of code to generate the jwt using jks signature, it throws error saying expecting a PEM-formatted key. I am thinking the pk format is not what the jwk requires. My question is how I could extract pem file formatted file from .jks to sign the jwk token? Thanks.

Felix
  • 23
  • 1
  • 6

1 Answers1

0

"PEM" is nothing more than the base64-encoded key, enclosed in a -----BEGIN XYZ----- header line and an -----END XYZ----- footer line, where XYZ is the key type (e.g. "PRIVATE KEY" or "CERTIFICATE").

Sample from https://pyjks.readthedocs.io/en/latest/examples.html:

Reading a JKS or JCEKS keystore and dumping out its contents in the PEM format:

import sys, base64, textwrap
import jks

def print_pem(der_bytes, type):
    print("-----BEGIN %s-----" % type)
    print("\r\n".join(textwrap.wrap(base64.b64encode(der_bytes).decode('ascii'), 64)))
    print("-----END %s-----" % type)

So in your case, slightly modified to return a text block, instead of printing it:

import sys, base64, textwrap
import jks

def format_pem(der_bytes, type):
    return "\r\n".join([
        "-----BEGIN %s-----" % type,
        "\r\n".join(textwrap.wrap(base64.b64encode(der_bytes).decode('ascii'), 64)),
        "-----END %s-----" % type
    ])

# ...

pk = keystore.private_keys[keyAlias]
pk_pem = format_pem(pk, "PRIVATE KEY")
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • Hey Tomalak, thanks so much for your help. I made a little bit change from your code and it works now. Instead of using pk directly, I use pk.pkey to change it to bytes-like object. I got the final jwt token signed with the private key from jks. Thanks again for your prompt help and insights! Appreciate that! – Felix Nov 19 '21 at 17:49
  • @Felix Yeah as you might have guessed, the code was not really tested. :) Please feel free to make the necessary changes to my answer! – Tomalak Nov 19 '21 at 18:55
  • is there a way to extract the public key using jks? – Tony Oct 15 '22 at 13:47