B4J Question Web3X - Signature error. r must be positive

jtare

Active Member
Licensed User
Longtime User
Hello, I'm trying to understand the web3 as it seems to potentially have some future, and the new web3X library seems very good.
One problem I'm experiencing is with the "verify signature" function and the "extract public keys from signature" function, both seem to throw an error, apparently at random. The "(RuntimeException) java.lang.RuntimeException: r must be positive" error.

Any idea of what may be going on?

B4X:
main._appstart (java line: 48)
java.lang.RuntimeException: java.lang.RuntimeException: r must be positive
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:137)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:95)
    at anywheresoftware.b4a.keywords.Common$3.run(Common.java:1103)
    at anywheresoftware.b4a.keywords.SimpleMessageLoop.runMessageLoop(SimpleMessageLoop.java:47)
    at anywheresoftware.b4a.StandardBA.startMessageLoop(StandardBA.java:43)
    at anywheresoftware.b4a.keywords.Common.StartMessageLoop(Common.java:170)
    at b4j.example.main._appstart(main.java:48)
    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:108)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:95)
    at b4j.example.main.main(main.java:28)
Caused by: java.lang.RuntimeException: r must be positive
    at org.web3j.utils.Assertions.verifyPrecondition(Assertions.java:26)
    at org.web3j.crypto.Sign.recoverFromSignature(Sign.java:134)
    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 b4j.example.w3utils._extractpublickeysfromsignature(w3utils.java:441)
    at b4j.example.main$ResumableSub_Principal.resume(main.java:229)
    at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:153)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:102)
    ... 13 more

I get the same error with the example code:
B4X:
Dim message() As Byte = "this is the message".GetBytes("utf8")
Dim signature() As Byte = Utils.SignPrefixedMessage(message, Credentials)
Dim IsVerified As Boolean = Utils.VerifySignature(message, signature, Credentials.Address)'"0xbbbbbbbbbbccccc691fb21f07c9f4a66f3bda8da703c158c33fffffff")
Log(IsVerified)

I don't know what causes the error, but once a given set of bytes or string triggers the error, that same bytes or string will always trigger the error. Here below I ran some tests with random messages, some trigger the error and some don't, on average about 50% of the tests get an error.

B4X:
    Utils.Initialize
  
    'Create or load a wallet
    Dim walletPath As String = "set your path here.....\web3j\web3j-demo"
    If File.Exists(walletPath, "walletName.txt") Then
        Dim sf As Object = Utils.LoadWallet(walletPath&"/"&File.ReadString(walletPath, "walletName.txt"), "123456")
        Wait For (sf) Complete (Result As W3AsyncResult)
        If Result.Success Then
            Log("Wallet path (loaded): " & Result.Value)
            Dim Credentials As W3Credentials = Result.Value
            Log(Credentials.Address)
        End If
    Else
        Dim sf As Object = Utils.GenerateNewWallet(walletPath, "123456", True)
        Wait For (sf) Complete (Result As W3AsyncResult)
        If Result.Success Then
            Log("Wallet path: " & Result.Value)
            File.WriteString(walletPath, "walletName.txt", Result.Value)
        End If
    End If
  
    'Test with random messages
    Dim errorsFound As Int = 0
    For i=0 To 10
        Dim message(8) As Byte '= "k".GetBytes("UTF8")
        Dim SR As SecureRandom
        SR.GetRandomBytes(message)
      
        Dim signature() As Byte = Utils.SignPrefixedMessage(message, Credentials)

        Try
            Dim possibleKeys As List = Utils.ExtractPublicKeysFromSignature(message, signature)
            For j= 0 To possibleKeys.Size-1
                Dim IsVerified As Boolean = Utils.VerifySignature(message, signature, Utils.GetAddressFromPublicKey(possibleKeys.Get(j)))'"0xbbbbbbbbbbccccc691fb21f07c9f4a66f3bda8da703c158c33fffffff")
                Log(IsVerified)
            Next
        Catch
            Log(LastException)
            errorsFound = errorsFound + 1
        End Try
        Log("///////////////////////////")
    Next
    Log("Found "&errorsFound&" errors")
  
    'Lib example
    Try
        Dim message() As Byte = "this is the message".GetBytes("utf8")
        Dim signature() As Byte = Utils.SignPrefixedMessage(message, Credentials)
        Dim IsVerified As Boolean = Utils.VerifySignature(message, signature, "0xbbbbbbbbbbccccc691fb21f07c9f4a66f3bda8da703c158c33fffffff")
        Log(IsVerified)
    Catch
        Log(LastException)
    End Try

Maybe I'm missing something, but I appreciate any help.
 
Last edited:
Top