B4J Question [SOLVED] - Javaobject Problem - JWT with RSA256

hatzisn

Well-Known Member
Licensed User
Longtime User
Good morning everyone, I am trying to mess with @aeric 's JWT (as seen in the following post) to create JWT with RSA256. I am stack in Java


Starting I created an RSA256 pair of keys private and public creating this shell file (.sh) and running it.

B4X:
ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key
# Don't add passphrase
openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub
cat jwtRS256.key
cat jwtRS256.key.pub

Then I downloaded with ftp the keys in the files folder of the project and have added them in the files tab.

Then searching the web I found the code needed and tried to implement it in B4J. Here is what I have got until now. In the remed lines is the java code and some explanations. It is finished by 95%. Can somebody help with this.

B4X:
Public Sub InitializeRSA256
 
    '        String privateKeyContent = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("private_key_pkcs8.pem").toURI())));
    '        String publicKeyContent = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("public_key.pem").toURI())));
    '
    '        privateKeyContent = privateKeyContent.replaceAll("\\n", "").replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "");
    '        publicKeyContent = publicKeyContent.replaceAll("\\n", "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");
    '
    '        KeyFactory kf = KeyFactory.getInstance("RSA");
 
    Dim KeyFactory As JavaObject
    KeyFactory.InitializeStatic("java.security.KeyFactory")
 
    Dim publicKeyStr As String = File.ReadString(File.DirAssets, "jwtRS256.key.pub")
    publicKeyStr = publicKeyStr.replace(Chr(10), "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "")
    Log(publicKeyStr)
 
    Dim privateKeyStr As String = File.ReadString(File.DirAssets, "jwtRS256.key")
    privateKeyStr = privateKeyStr.replace(Chr(10), "").replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("-----END RSA PRIVATE KEY-----", "")
    Log(privateKeyStr)


    '        KeyFactory kf = KeyFactory.getInstance("RSA");
    '
    '        PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyContent));
    '        X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyContent));
    '         RSAPrivateKey key = (RSAPrivateKey) kf.generatePrivate(keySpecPKCS8);
    '        RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(keySpecX509);
 
 
    'TODO CHECK META
    Dim KF As JavaObject
    KF = KeyFactory.RunMethod("getInstance",Array("RSA"))

    Dim su As StringUtils
    Dim keySpecPKCS8 As JavaObject
    keySpecPKCS8.InitializeNewInstance("java.security.spec.PKCS8EncodedKeySpec", Array(su.DecodeBase64(privateKeyStr)))

    Dim keySpecX509 As JavaObject
    keySpecX509.InitializeNewInstance("java.security.spec.X509EncodedKeySpec", Array(su.DecodeBase64(publicKeyStr)))

 
    '============================================================
    'THE PROBLEM IS HERE (I may also have done something wrong also in the KF initialization
    '============================================================

    Dim RSAPrivateKey As JavaObject
    'I tried both with those two options but no luck
 
    'RSAPrivateKey.InitializeNewInstance("java.security.interfaces.RSAPrivateKey", Array(KF.RunMethod("generatePrivate", Array(keySpecPKCS8))))
    RSAPrivateKey = KF.RunMethod("generatePrivate", Array(keySpecPKCS8))
 
    Dim RSAPublicKey As JavaObject
    'RSAPublicKey.InitializeNewInstance("java.security.interfaces.RSAPublicKey", Array(KF.RunMethod("generatePublic", Array(keySpecX509))))
    RSAPublicKey = KF.RunMethod("generatePublic", Array(keySpecX509))
 


    Private AO As JavaObject
    AO.InitializeStatic("com.auth0.jwt.algorithms.Algorithm")
 
'    Algorithm Algorithm = Algorithm.RSA256(publicKey, privateKey);
    '    String token = JWT.create()
    '        .withIssuer("auth0")
    '        .sign(algorithm);
 
    ALG = AO.RunMethod("RSA256", Array (RSAPublicKey, RSAPrivateKey))
 
    JWT.InitializeStatic("com.auth0.jwt.JWT")
    builder = JWT.RunMethodJO("create", Null)
    verifier = JWT.RunMethodJO("require", Array(ALG)).RunMethodJO("build", Null)
    m_Initialized = True
End Sub


Here is the error:
Error occurred on line: 193 (JSONWebToken)
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:132)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:629)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:234)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
at b4j.example.main.main(main.java:29)
Caused by: java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:251)
at java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:390)
... 20 more
Caused by: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
at java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:350)
at java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:355)
at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.java:130)
at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:80)
at java.base/sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:356)
at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:247)
... 21 more
 
Last edited:

hatzisn

Well-Known Member
Licensed User
Longtime User
Solved! Just replace the sh file instructions with these:

B4X:
#!/usr/bin/env bash
openssl genrsa -out private_key.pem 4096
openssl rsa -pubout -in private_key.pem -out public_key.pem
# convert private key to pkcs8 format in order to import it from Java
openssl pkcs8 -topk8 -in private_key.pem -inform pem -out private_key_pkcs8.pem -outform pem -nocrypt

The new code will be the following (replaced keys filenames with the new ones and removed the REMed lines and removed RSA form the text being replaced in privateKeyStr):

B4X:
Public Sub InitializeRSA256
 
    Dim KeyFactory As JavaObject
    KeyFactory.InitializeStatic("java.security.KeyFactory")
 
    Dim publicKeyStr As String = File.ReadString(File.DirAssets, "public_key.pem")
    publicKeyStr = publicKeyStr.replace(Chr(10), "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "")
 
    Dim privateKeyStr As String = File.ReadString(File.DirAssets, "private_key_pkcs8.pem")
    privateKeyStr = privateKeyStr.replace(Chr(10), "").replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "")

    Dim KF As JavaObject
    KF = KeyFactory.RunMethod("getInstance",Array("RSA"))

    Dim su As StringUtils
    Dim keySpecPKCS8 As JavaObject
    keySpecPKCS8.InitializeNewInstance("java.security.spec.PKCS8EncodedKeySpec", Array(su.DecodeBase64(privateKeyStr)))

    Dim keySpecX509 As JavaObject
    keySpecX509.InitializeNewInstance("java.security.spec.X509EncodedKeySpec", Array(su.DecodeBase64(publicKeyStr)))
 

    Dim RSAPrivateKey As JavaObject
    RSAPrivateKey = KF.RunMethod("generatePrivate", Array(keySpecPKCS8))
 
    Dim RSAPublicKey As JavaObject
    RSAPublicKey = KF.RunMethod("generatePublic", Array(keySpecX509))

    Private AO As JavaObject
    AO.InitializeStatic("com.auth0.jwt.algorithms.Algorithm")
 
    ALG = AO.RunMethod("RSA256", Array (RSAPublicKey, RSAPrivateKey))
 
    JWT.InitializeStatic("com.auth0.jwt.JWT")
    builder = JWT.RunMethodJO("create", Null)
    verifier = JWT.RunMethodJO("require", Array(ALG)).RunMethodJO("build", Null)
    m_Initialized = True
End Sub
 
Last edited:
Upvote 0
Top