Skip to content

madaster97/openssl-jws

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Overview

I'm attempting to use openssl for JWS ES256 signature creation and validation.

I've not been able to properly sign, so as a first step I'm trying to validate the example signature from RFC 7515.

For reference, JWT.IO properly validates that signature, but when I try to do the same with openssl I get the following errors:

Error Verifying Data
139722910762304:error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long:../crypto/asn1/asn1_lib.c:101:
139722910762304:error:0D068066:asn1 encoding routines:asn1_check_tlen:bad object header:../crypto/asn1/tasn_dec.c:1118:
139722910762304:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:290:Type=ECDSA_SIG

For signature creation, I attempted the methods in these articles (1,2,3), but was not able to succesfully validate the signatures in JWT.IO (however, openssl is able to validate the signatures it creates).

Openssl CLI ECDSA Signing Procedure

Generate ES256 key pair

Generates the key pair to be used. Replace prime256v1 with your target curve.

openssl ecparam -name prime256v1 -genkey -noout -out privatekey.pem
openssl ec -in privatekey.pem -pubout > publickey.pem

To list other curves, use openssl ecparam -list_curves. Ex: ES384 is secp384r1.

Store JWT payload

echo -n "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJFUzI1NmluT1RBIiwibmFtZSI6IkpvaG4gRG9lIn0" > data

Remember to switch out the alg header for different signing algorithms. Here is an example ES384 JOSE header: eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.

Sign data with the private key

Note the default digest is sha256. Use openssl dgst -list to list digest types, and replace the -sha256 flag with your needed digest (ex: -sha384 for ES384).

openssl dgst -sha256 -sign privatekey.pem -out signature.bin data

Parse DER encoded signature to valid JWS Signature

Openssl's dgst output is not sufficient for JWS signatures. There is extra processing needed to prepare that payload as a proper signature.

See this Issue and this SO Post for more explanation.

openssl asn1parse -in signature.bin -inform DER > asn1
cat asn1 | perl -n -e'/INTEGER           :([0-9A-Z]*)$/ && print $1' > signature.hex
cat signature.hex | xxd -p -r | base64 | tr -d '\n=' | tr -- '+/' '-_' > signature.sig

These are the processing steps I used:

  1. Use openssl's asn1parse to parse the DER signature. Here's an example output:
    0:d=0  hl=2 l=  69 cons: SEQUENCE
    2:d=1  hl=2 l=  33 prim: INTEGER           :DBA805DFAC77A488FD42DFB2649EE5CC989AD4989104B171680CB11BA44FF465
   37:d=1  hl=2 l=  32 prim: INTEGER           :578B760F5427BA70CC9025A4730DFBE624497B381E451C0627F1EE4E4A705183
  1. Use a regex to extract the R and S big-endian integers from that output.
  2. Use xxd to parse the integers as hex (that's how asn1parse outputs them) and then base64url encode the binary output.

Validate at JWT.IO

echo "$(cat data).$(cat signature.sig)" > token
echo "https://jwt.io/#debugger-io?token=$(cat token)"
echo "Paste public key into jwt.io"
cat publickey.pem

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published