Written by

Integration Engineer at ReStart Consulting
Question William Glover · May 22, 2023

How do you sign a JWT request?

The below code gives a empty string output.

Set secretSigned = ##class(%SYSTEM.Encryption).RSASHA1Sign(512,token,secret)
      

The secret is a valid PEM private key.

Is there any more logic that needs to prefix this method call?

Product version: IRIS 2021.1

Comments

Jeffrey Drumm · May 22, 2023

I believe your argument list is incorrect.

The first argument should be a string containing the data to be signed. The second is the private key, also in the form of a string. If the key is passphrase-protected, the third argument should be a string containing the passphrase.

SHA-1 is deprecated, by the way.

0
William Glover  May 22, 2023 to Jeffrey Drumm

Ah sorry I switched out the method call to see if it worked, i was using RSASHASign before where the first argument is the bitlength and was getting the same result, any ideas in that scenario.

0
Jeffrey Drumm  May 22, 2023 to William Glover

I just tried RSASHASign() myself and a signature was returned, using your call:
 

Set in=##class(%Stream.FileCharacter).%New()
Do in.LinkToFile("/home/jeff/sample.jwt")
Set token=in.Read()
Set key=##class(%Stream.FileCharacter).%New()
Do key.LinkToFile("/home/jeff/sample.pem")
Set secret=key.Read()
Set sig=##class(%SYSTEM.Encryption).RSASHASign(512,token,secret)

The return value will be the signature only, though, not a signed JWT. If you want the latter, see the ObjectToJWT() method in  %OAuth2.JWT - InterSystems IRIS for Health 2021.1.

0
William Glover  May 22, 2023 to Jeffrey Drumm


     Set encodedToken = ..UrlEncoding($System.Encryption.Base64Encode(..header.%ToJSON(),1)_
     "."_ $System.Encryption.Base64Encode(..payload.%ToJSON(),1))
     Set tFile=##class(%Stream.FileBinary).%New()
     Set tFile.Filename=secretLocation
    
     Set pemPrviateKey = tFile.Read($$$MaxLocalLength)
    
     Set secretSigned = ##class(%SYSTEM.Encryption).RSASHASign(512,encodedToken,pemPrviateKey)
    
     Set signature = $Translate($System.Encryption.Base64Encode(secretSigned, 1),"+/=","-_")
    
    Return encodedToken_"."_signature
In my scenario the token is two encrypted JSONs appended together and the signature gets appended to the end.
The code above doesn't produce anything at secretSigned, the PEM encoded private key is valid.

0
Jeffrey Drumm  May 22, 2023 to William Glover

Is your key file passphrase-protected?

I get the output you describe when the key is passphrase-protected and the passphrase is not supplied.

0
William Glover  May 22, 2023 to Jeffrey Drumm

Hi Jeffrey,

No its not and it reads the string in correctly as shown by the watch on the debugger.

0
Jeffrey Drumm  May 22, 2023 to William Glover

Password-protecting the key won't prevent it from being read.

Do you have access to openssl? If yes, try the following:

openssl rsa -in <keyfile-name> -check -noout

You should get "RSA key ok" if it's a good key and has no passphrase.

0
William Glover  May 22, 2023 to Jeffrey Drumm

Hi Jeffrey,

It does respond with RSA Key ok when running that command on it .

0
Jeffrey Drumm  May 22, 2023 to William Glover

Can you try the code I posted above, substituting appropriate paths/filenames in the calls to the LinkToFile() methods? Any file will do for the in stream, as long as file/directory permissions permit. This at least would tell us whether the issue is with the key file or the JWT you're attempting to encrypt.

I've tried this on I4H 2023.1 and Health Connect 2021.1.2 and the RSASHASign() method has not failed to generate a signature unless the key was passphrase-protected or not readable (due to file ownership/permissions) by the process opening it.

0