I'm trying to construct an RS256 JWT token using only bash and openSSL (I have limited development tools at my disposal).
I've devised a script which takes the header and payload from txt files (stripping out newlines etc), base-64URL encodes them and concatenates them together with a '.' separator.
I'm then attempting to sign the output, which I also base-64URL encode and append to the end (with another '.' separator). I believe this accurately reflects the JWT model.
My private key and certificate were generated using openSSL:
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout ./privateKey2.key -out ./certificate2.crt
My public key was generated from the private key using:
openssl rsa -pubout -in ./privateKey2.key > ./publicKey2.key
I then have the following bash script that process the job:
cat header.txt | tr -d '\n' | tr -d '\r' | openssl base64 | tr +/ -_ | tr -d '=' > header.b64
cat payload.txt | tr -d '\n' | tr -d '\r' | openssl base64 | tr +/ -_ |tr -d '=' > payload.b64
printf "%s" "$(<header.b64)" "." "$(<payload.b64)" > unsigned.b64
rm header.b64
rm payload.b64
openssl rsautl -sign -inkey privateKey2.key -in unsigned.b64 -out sig.txt
cat sig.txt | openssl base64 | tr +/ -_ | tr -d '=' > sig.b64
printf "%s" "$(<unsigned.b64)" "." "$(<sig.b64)" > jwt.txt
rm unsigned.b64
rm sig.b64
rm sig.txt
I believe the script itself is working, but whenever I upload the final output into jwt.io's testing tool, it tells me the signature is invalid (it can read the content and header and payload are correct).
Is my use of openssl rsautl incorrect?
Happy to include keys / sample data if they'd help
Example output:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2
MjM5MDIyfQ.fE-btiyskyDrO1mQXcICP0udbCkdV9D_50CYNbpRVgod6EPjKmbOJK-EA7vn7s5l
TtkvKw0m1r45poGApBT4SA_ChmEgsPzhGwxd2xpInesRon-mWTzsUqqz0C1CcegT
n9Z19JzGJ7wUjomg7viKI1OP7Ei6TptINE8hPqEBPPpeO2PfT5IevMb1XytaCuTO
R1JMurgwsIa0Kq3LaFoAk1stUnTtJRI8-NHzWqmUiQpq-K1eteBtT9ZvKXJ_6ReY
_AetoeqmEDVQO_UV2ae_dKd4QHSV8D-ryJFc-OEYWzgwGeqXSBMNVMzsXKSUIR8C
sfvZ2hvwbQI2f0J6gZQw0w
Corresponding public key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1YbvZ3CPPr3X47J/pqCD
ciE0AhRbiBrybu4T3GbbHfGYROaPSKx2LfXCwAlayln5zNaZ14cvlDHEpCIQviPk
Qv5Ux16R2QouhF0ZugyMHLQkusVXG6Va14eFVKkcO2g1c25bOMAk4V3vSsVnMMQS
fTPunpGVrBUBo2We5P+cKldBNXKBlXEAIRGc4/fTcTB4F8opP+x5ACIZ04SWKafJ
MSvujIfpBxs476bvxA5xlPQiOhbOIo/bhPMJI6AlaDTJ03pGTOYjR5jZlB03j4YD
EF/2hhidvvFnLHdPkewzDsn0aZi+fqBNvQhS0hutnvp6F8hGL9e5hh8G7a2AXy9F
2QIDAQAB
-----END PUBLIC KEY-----