B4J Question How sign json string with RS256 Algoritm?

behnam_tr

Active Member
Licensed User
Longtime User
hello...

how can i sign json string with my privateKey using RSASSA-PKCS1-v1_5 using SHA-256
i need it for generate jwt token.

document help :
BASE64URL(UTF8(JWS Protected Header))|| '.' ||
BASE64URL(UTF8(JWS Payload()|| '.' ||
BASE64URL(JWS Signature)

Signature :
ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' ||
BASE64URL(JWS Payload))

B4X:
Dim payload As String = $"{"nonce":"942a1ccd-a6a5-47f6-8e80-a92358cc11a1","clientId":"A11226"}"$
 
    Dim privatekey As String = $"
    MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDMuDKTko7r6P13
W53SKUkCutndaHD/D3ATMcH3JfAQ1Frl+bkBtG6QwXlvpUZ4rMPotm4v36190V9b
I9yMj76AY3LDNGYQcqlOfM/W3o3K5cp+bicFUBuWy6BLDxjkMRdF9OoguAFY3+ln
jMaWJ8QAsxwYCzsANyOe/tv+0zbDGv2sfGwK9bge+XNBqwrxCvUKsqBPQQjrqtJc
Id6n+4g40NanRbY56UyVm0zoACNZdEsZyyE8ge4r5kt8AXFa2gaid/qo33KmizYH
XwP8QVrxYc43rZ5gpPSRbeMFVrfI8SRHCR0OMO7/cI/PKaF/dYVjDGlvi3fmhZv+
pRcZUh2/AgMBAAECggEACPpC7YnNzram9ucDosXAt+ftyfHckrLgnVbfRLFbN8G4
QsGSxWpeNublJmo/Due0p63oYx0SBKR75AlMkLV1CzhRPhI8L5h3qEN88dVMrosp
OCYoe+kpbJF9dA0zcD5e4Oh+o/StynH3UF0yED+qLsWsA7nqWnYQj9ZpW2Fz01Z1
i5NRX4YgyIopHfqcLWJWpOR8n4HwDY18BL7tMi31f0sZXz56EUgBPxq5RMi+1iKW
pyZdwy4TrJL/Sj4tWkKJ7ELVd47VunizAqeLDy8bLlPBX0PewRvR37P9axHLjsj/
d1Iw/xvqgVEWZTyUXzg4qgFU5Na5u6xIW8JyqejdEQKBgQD2QlDdoPOtG1URyuuo
4HJlQ85ZfEWWA0vvp8esvJLJ7t73Rz28RkKAMHW/njr23ExxV3eek9J1lGENJUZF
KsNNtjRWMgCxUicO0MGTJuraWHrEma00YNNjpVd3pIi68p51CZNzMRLn2J8F+7CP
eGiynKEvKU43KcJr6KOkWP14FQKBgQDU0T3SNr7af4y3rO3ds2DMaoKEG531tuLu
nrZNnL4a/i2r3AlI5K470UkmAXDD1kgGf235KxrRm7x7VVp5SZLgOPqgJ2OKKk9b
HLvuAdxCeUlnDfJWrAmYcmyLLCSDHBudN/evF6WiNaQi074MhdbaxYdLiiXdS3VV
flQ/8m6/gwKBgD4ijXTeX52V/+j1YnDB8RtL+IzrpkMrocVeeCtFiWQaOXf7KcCP
mcfuckdfDVGsVD1k7HG+qqOwRKykcw6Qs6awCpSVGUekiuZaFf2jHC7rlE522BUX
OT8zQNaXVUiWXxT4zZOLFlIZfkZsMyiAISqwCptzuKCCkOPZVzDoo0vhAoGBAMo8
2XnVyoKLKWc2r4i6OOeo48S1FeP12yuVqXqR1FqEZ1RlMnGR1z1DAjdasRV5oVKD
cDeTzdWZIIE3uFWAJFJt80WUiNQ4ptbXtINWQ0DsT2PebggNTsUPH7UVytDJOjiq
gfZjC2TdgtAR1g3Cdk3J3mtbqeXlGmiXN2rZcIMPAoGADfTonaehrsnscUcH4Dgs
qZdyZm9JRmoNyisLBmbGkTNxoYO9Vm/03u3NMsohkjopt2ly38ZMYXl4FyXKEKcI
977r33JD9PxRcovqFhcPR3WuQrPf6ND3IX6eB5p8d7m6fmFYSe/0NhWoeH99a6/c
csAr2hPMOb/R3GdRewkSGgQ=
    "$

dim cert as string= $"
-----BEGIN CERTIFICATE-----
MIIDejCCAmKgAwIBAgIUV27QXqJjK2EgFy9zeYkpsX+ISPswDQYJKoZIhvcNAQEL
BQAwcTELMAkGA1UEBhMCSVIxDDAKBgNVBAgMA1RlaDEMMAoGA1UEBwwDVGVoMREw
DwYDVQQKDAhNb2hheW1lbjEMMAoGA1UECwwDVGF4MSUwIwYJKoZIhvcNAQkBFhZt
Lm1hbHZlcmRpQG1vaGF5bWVuLmlyMB4XDTIzMDMyNDEzMjgyM1oXDTI0MDMyMzEz
MjgyM1owTTEPMA0GA1UEAwwGQW56YWxpMRcwFQYDVQQKDA5RdW9WYWRpcyBHcm91
cDELMAkGA1UEBhMCSVIxFDASBgNVBAUTCzE0MDAzNzc4OTkwMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzLgyk5KO6+j9d1ud0ilJArrZ3Whw/w9wEzHB
9yXwENRa5fm5AbRukMF5b6VGeKzD6LZuL9+tfdFfWyPcjI++gGNywzRmEHKpTnzP
1t6NyuXKfm4nBVAblsugSw8Y5DEXRfTqILgBWN/pZ4zGlifEALMcGAs7ADcjnv7b
/tM2wxr9rHxsCvW4HvlzQasK8Qr1CrKgT0EI66rSXCHep/uIONDWp0W2OelMlZtM
6AAjWXRLGcshPIHuK+ZLfAFxWtoGonf6qN9ypos2B18D/EFa8WHON62eYKT0kW3j
BVa3yPEkRwkdDjDu/3CPzymhf3WFYwxpb4t35oWb/qUXGVIdvwIDAQABoy4wLDAf
BgNVHSMEGDAWgBSx+Oq+RO3x/FmyCp+jcmfOH+Fn9TAJBgNVHRMEAjAAMA0GCSqG
SIb3DQEBCwUAA4IBAQAgKATXlnS+pPtAiRIYGtydVU5Vi7Aq+D6QW07uFqcB7vBh
ddN3yX2lVVcwpTNJzhv8UCM+mDMvlmsRVKVtMoo5fHfII92/Wo8rUz1RP+yhyCk0
Vz8I11v+bjLwVur/agC/s5Rf0m66pNNjFZ9J3S2N3lChXYwz2vvA8pdAYvWTu9g5
u4FMFqlsaLwMGC+WaA0g3KYzRkdWRy1vd23hLTUcVsWM8wpgZ11wEGE1khca/Sd0
mCU2HG5vIbqFfTjA6to0fY07CE5fD8aR3UcXjNduosVO52ZqCX5SabrhFS3AGHFR
jpFnI5LZespiCXSA8Sv3kOSCSRQKqFbiwSFM8Zjg
-----END CERTIFICATE-----

"$
 
    Dim header As String = $"{"alg":"RS256","x5c":["MIIDejCCAmKgAwIBAgIUV27QXqJjK2EgFy9zeYkpsX+ISPswDQYJ
KoZIhvcNAQELBQAwcTELMAkGA1UEBhMCSVIxDDAKBgNVBAgMA1RlaDEMMAoGA1UEBwwDVGVoMRE
wDwYDVQQKDAhNb2hheW1lbjEMMAoGA1UECwwDVGF4MSUwIwYJKoZIhvcNAQkBFhZtLm1hbHZlcm
RpQG1vaGF5bWVuLmlyMB4XDTIzMDMyNDEzMjgyM1oXDTI0MDMyMzEzMjgyM1owTTEPMA0GA1UEA
wwGQW56YWxpMRcwFQYDVQQKDA5RdW9WYWRpcyBHcm91cDELMAkGA1UEBhMCSVIxFDASBgNVBAUT
CzE0MDAzNzc4OTkwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzLgyk5KO6+j9d1u
d0ilJArrZ3Whw/w9wEzHB9yXwENRa5fm5AbRukMF5b6VGeKzD6LZuL9+tfdFfWyPcjI++gGNywz
RmEHKpTnzP1t6NyuXKfm4nBVAblsugSw8Y5DEXRfTqILgBWN/pZ4zGlifEALMcGAs7ADcjnv7b/
tM2wxr9rHxsCvW4HvlzQasK8Qr1CrKgT0EI66rSXCHep/uIONDWp0W2OelMlZtM6AAjWXRLGcsh
PIHuK+ZLfAFxWtoGonf6qN9ypos2B18D/EFa8WHON62eYKT0kW3jBVa3yPEkRwkdDjDu/3CPzym
hf3WFYwxpb4t35oWb/qUXGVIdvwIDAQABoy4wLDAfBgNVHSMEGDAWgBSx+Oq+RO3x/FmyCp+jcm
fOH+Fn9TAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAgKATXlnS+pPtAiRIYGtydVU5Vi
7Aq+D6QW07uFqcB7vBhddN3yX2lVVcwpTNJzhv8UCM+mDMvlmsRVKVtMoo5fHfII92/Wo8rUz1R
P+yhyCk0Vz8I11v+bjLwVur/agC/s5Rf0m66pNNjFZ9J3S2N3lChXYwz2vvA8pdAYvWTu9g5u4F
MFqlsaLwMGC+WaA0g3KYzRkdWRy1vd23hLTUcVsWM8wpgZ11wEGE1khca/Sd0mCU2HG5vIbqFfT
jA6to0fY07CE5fD8aR3UcXjNduosVO52ZqCX5SabrhFS3AGHFRjpFnI5LZespiCXSA8Sv3kOSCS
RQKqFbiwSFM8Zjg"],"sigT":"2023-05-
13T10:44:47Z","typ":"jose","crit":["sigT"],"cty":"text/plain"}"$

Java Code
Java:
/** Loading Signature Private Key in PKCS#8 format **/

String privateKeyPath = "path/to/private-key.pem";
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
final PEMParser pemParser = new PEMParser(new FileReader(privateKeyPath));
final PrivateKeyInfo pemKeyPair = (PrivateKeyInfo) pemParser.readObject();
final byte[] encoded = pemKeyPair.getEncoded();
PrivateKey privateKey = keyFactory.generatePrivate(new
PKCS8EncodedKeySpec(encoded));
/** Loading Certificate **/
String certificatePath = "path/to/certificate.crt";
CertificateFactory certificateFactory =
CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate)
certificateFactory.generateCertificate(new
FileInputStream(certificatePath));
/** Generate Signature Time **/
String dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'";
DateTimeFormatter dateTimeFormatter =
DateTimeFormatter.ofPattern(dateFormat, Locale.ROOT);
String signatureTime =
LocalDateTime.now(ZoneOffset.UTC).format(dateTimeFormatter);
String payload = "{\"nonce\":\"942a1ccd-a6a5-47f6-8e80-
a92358cc11a1\",\"clientId\":\"A11226\"}";
/** Generating JWT **/
final JsonWebSignature jws = new JsonWebSignature();
jws.setPayload(payload);
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
jws.setKey(privateKey);
jws.setCertificateChainHeaderValue(certificate);
jws.setHeader("sigT", signatureTime);
jws.setHeader("typ", "jose");
jws.setHeader("crit", new String[]{"sigT"});
jws.setContentTypeHeaderValue("text/plain");
jws.sign();
String jwt = jws.getCompactSerialization();
 
Last edited:

drgottjr

Expert
Licensed User
Longtime User
there are some threads relating to jwt, but i didn't see any libraries.
so i made a small one. it is based on your parameters.

your token was not quite complete. in addition to a payload and a key
you need a header. i've added one based on your parameters.

your payload is a simple one, so it is possible to create a json string by hand,
but there is a correct one to generate and parse json strings with our json
library. i'm sure you know how to use it. for the purposes of creating a jwt
for you, i've left your payload as you built it. if you were making a more
robust jwt, you would need an expanded payload. i think my little library
can handle that.

i've verified the example's output at https://jwt.io/

my example displays the jwt in the log and in a label. if you copy the
1-line output from the log, you can paste it at jwt.io to check the token yourself.

the attached .zip archive includes the example and the library's .jar/.xml
copy the .jar and .xml to your additional libraries folder. the example runs
for me, no problem.
 

Attachments

  • gjwt.zip
    11.7 KB · Views: 115
Upvote 0

behnam_tr

Active Member
Licensed User
Longtime User
there are some threads relating to jwt, but i didn't see any libraries.
so i made a small one. it is based on your parameters.

your token was not quite complete. in addition to a payload and a key
you need a header. i've added one based on your parameters.

your payload is a simple one, so it is possible to create a json string by hand,
but there is a correct one to generate and parse json strings with our json
library. i'm sure you know how to use it. for the purposes of creating a jwt
for you, i've left your payload as you built it. if you were making a more
robust jwt, you would need an expanded payload. i think my little library
can handle that.

i've verified the example's output at https://jwt.io/

my example displays the jwt in the log and in a label. if you copy the
1-line output from the log, you can paste it at jwt.io to check the token yourself.

the attached .zip archive includes the example and the library's .jar/.xml
copy the .jar and .xml to your additional libraries folder. the example runs
for me, no problem.

thanks i tested and done and is ok in b4j!!

In my documentation, the production method is described as follows
The final token consists of 3 parts, marked by "." They are separated

BASE64URL(UTF8(JWS Protected Header))|| '.' ||
BASE64URL(UTF8(JWS Payload()|| '.' ||
BASE64URL(JWS Signature)

Signature :
ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' ||
BASE64URL(JWS Payload))

Does the generated token conform to this pattern?
post 1# updated with real data
 
Last edited:
Upvote 0

behnam_tr

Active Member
Licensed User
Longtime User
there are some threads relating to jwt, but i didn't see any libraries.
so i made a small one. it is based on your parameters.

your token was not quite complete. in addition to a payload and a key
you need a header. i've added one based on your parameters.

your payload is a simple one, so it is possible to create a json string by hand,
but there is a correct one to generate and parse json strings with our json
library. i'm sure you know how to use it. for the purposes of creating a jwt
for you, i've left your payload as you built it. if you were making a more
robust jwt, you would need an expanded payload. i think my little library
can handle that.

i've verified the example's output at https://jwt.io/

my example displays the jwt in the log and in a label. if you copy the
1-line output from the log, you can paste it at jwt.io to check the token yourself.

the attached .zip archive includes the example and the library's .jar/.xml
copy the .jar and .xml to your additional libraries folder. the example runs
for me, no problem.

java sample code attached post#1
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
i remembered your post was for b4j, so i recompiled a version for b4j (attached). i see you edited your initial post, so it is quite different now. i haven't had time to look at it yet.
 

Attachments

  • gjwt-b4j.zip
    2.6 KB · Views: 106
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
my library generates a valid jws (that is, jwt + security).
it follows the pattern:
base64url(header) + "." + base64url(payload) + "." + base64url(signature)
(with signature = hmacSha256(base64url(header) + "." + base64url(payload), secretkey))

i don't know what "jws protected header", "jws payload", and "jws signature" are.
apparently these are all different from "header", "payload", "signature".

as to the method you show for generating a signature, i don't know what the
ASCII() method is. especially since it seems to include a "UTF()" method. i don't know
what that is, either. it is basically not possible to go from utf8 to ascii except if all the bytes
are less than 128. something strange there with that method.

my library does NOT follow these steps:
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
jws.setKey(privateKey);
jws.setCertificateChainHeaderValue(certificate);

if you had included these steps in your original post, i would probably not have responded since
i am not familiar with them. i was responding to the parameters you posted initially. my experience
with jwt relates to decoding them when they are embedded in certain types of qr codes. as part of
that familiarity, i knew how to generate them. your problem (as described initially) was easy to
resolve. those extra steps and strange signature generation method change the game. sorry.
 
Upvote 0

behnam_tr

Active Member
Licensed User
Longtime User
my library generates a valid jws (that is, jwt + security).
it follows the pattern:
base64url(header) + "." + base64url(payload) + "." + base64url(signature)
(with signature = hmacSha256(base64url(header) + "." + base64url(payload), secretkey))

i don't know what "jws protected header", "jws payload", and "jws signature" are.
apparently these are all different from "header", "payload", "signature".

as to the method you show for generating a signature, i don't know what the
ASCII() method is. especially since it seems to include a "UTF()" method. i don't know
what that is, either. it is basically not possible to go from utf8 to ascii except if all the bytes
are less than 128. something strange there with that method.

my library does NOT follow these steps:
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
jws.setKey(privateKey);
jws.setCertificateChainHeaderValue(certificate);

if you had included these steps in your original post, i would probably not have responded since
i am not familiar with them. i was responding to the parameters you posted initially. my experience
with jwt relates to decoding them when they are embedded in certain types of qr codes. as part of
that familiarity, i knew how to generate them. your problem (as described initially) was easy to
resolve. those extra steps and strange signature generation method change the game. sorry.
thank you
You gave me a good idea, I will try to convert the Java code into a library with more research or use it inline if possible.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
that java code you show uses JOSE, which is somewhat different from simply generating jwt. there already is a jose library, so you don't have to write one. you just have to know how to use it. you can just add it to a b4j project, but you have to know how it works. check maven: https://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
You gave me a good idea, I will try to convert the Java code into a library with more research or use it inline if possible.
Before writing everything from scratch, you may want to check out these posts

1) @aeric has a JWT class that could be expanded to support your needs: https://www.b4x.com/android/forum/threads/web-json-web-token-auth0-java-jwt.142125/#content

2) @hatzisn's code shows how to load the keys from file: https://www.b4x.com/android/forum/threads/solved-javaobject-problem-jwt-with-rsa256.143234/#content
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Upvote 0

behnam_tr

Active Member
Licensed User
Longtime User
that java code you show uses JOSE, which is somewhat different from simply generating jwt. there already is a jose library, so you don't have to write one. you just have to know how to use it. you can just add it to a b4j project, but you have to know how it works. check maven: https://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt
Yes, I checked again now and it is mentioned in the document that the jose-4j library version 0.9.3 is used.
 
Last edited:
Upvote 0
Top