Checking RSA signature with Bouncycastle

79 views
Skip to first unread message

Matej Kral

unread,
Jun 30, 2020, 11:58:20 AM6/30/20
to CodenameOne Discussions
Hi,

I'm working on a project which involves JWT tokens signed via RSA SHA256.
After some tinkering I came up with code which should work, but
the verification came out negative. 

I've created a simplified example - in with a plain text 12345 is
signed by the private RSA key using SHA256. The public key is 
created via modulus and exponent and the signature is a BASE65
encoded string. So the example code works as it is.

The problem is, that in standard Java 8 environment this example works and
verifies the signature, but it fails in codenameone environment. Is there something
I'm missing here?

public void test() {
       String smod = "00967ddfd775d5b3e85cba1a94d92b207667920240813f91439afa33e0ef1d66ccebce78edc6327481cb8db94210afe0bc989d7e0512ded7812fd68b0e544c77fecb2346f6b09440f162fccf927c01e539a5f168d51d1992f890f8e341658ddb9ee719849562f60397512f90365098c33fb523cc1cefcd201f4e371869c55c8d052e0eb3f8386b3900ebd92321b70f403a6b98c1ad39f9e471793a4275b6fdd40929b60e9ee053eaef54228a1ca91d0d0de0481422866b5b215af2d7312db0244cfc97999738cc0040ac87c31dc0bda1247969c4def4edfdd60e5dbf6fbce17a971361ad9af9cd63b69d2cc33b65fb8cd33a34733d7584cce05da383d9b5ced7ad";

        BigInteger modulus = new BigInteger(smod, 16);
        BigInteger exponent = BigInteger.valueOf(65537);

        String data = "12345";
        String sig = "iaklDCcd+CjxdDMM/IKOJluTLIk3pN5zQ3nYdyVya3DjWFOsyJTkw7ofkt15Ly2+yOR0Z6+fIFgCLEuZZTvdYssVubAk6srwClav2OlxpK5zmqgJ7NqYKBFRo7YSyvFFAIwlhiL4dxl76BhCTSJTIFYAGCQFCOAVl8AoJ0pip/yeRCNC8+lv0gb0D6VQ/jm7uKJaddkc/7NxfaH4g80NggOYYifi6Rdc1Aj+WeituKr/b2qjwBictix/zA7N/0LlLA5mro9RfgBOwp3Prenwe0XGLVg4XRyvhRHYYvs+mO//hWzfM82FqwEGNmIxY0HxaQRg8uWDwxgN8ZUO0EwihQ==";

        byte[] sigDecode = Base64.decode(sig);

        RSADigestSigner signer = new RSADigestSigner(new SHA256Digest());
        signer.init(false, new RSAKeyParameters(false, modulus, exponent));
        
        try {
            signer.update(data.getBytes("UTF-8"), 0, data.getBytes("UTF-8").length);
        } catch (UnsupportedEncodingException ex) {
            Log.e(ex);
        }

        boolean verified = signer.verifySignature(sigDecode);

        Log.p("Signature verified: "+verified, Log.INFO);
    }

Regards

Shai Almog

unread,
Jun 30, 2020, 11:12:05 PM6/30/20
to CodenameOne Discussions
Hi,
which imports are you using?
You need to be careful about importing unsupported java packages.

Matej Kral

unread,
Jul 1, 2020, 4:18:51 AM7/1/20
to CodenameOne Discussions
Hi,

I'm using imports from the Bouncy Castle crypto api for Codename One. 

import javabc.BigInteger;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.signers.RSADigestSigner;
import org.bouncycastle.util.encoders.Base64;

The BigInteger import surprised me a bit since there is com.codename1.util.BigInteger  version, but that one 
isn't compatible with the RSAKeyParameters object. 

The program compiles and runs, the problem is the result - for some reason it won't verify the signature,  while
in standard Java environment it does. 
 

Dátum: streda 1. júla 2020, čas: 5:12:05 UTC+2, odosielateľ: Shai Almog

Shai Almog

unread,
Jul 1, 2020, 11:25:53 PM7/1/20
to CodenameOne Discussions
Hi,
the BC BigInteger predated our own implementation.
Which code did you use to verify a signature?
Did you try the code from Francesco

Matej Kral

unread,
Jul 2, 2020, 8:47:00 AM7/2/20
to CodenameOne Discussions
Hi,

I've checked the SHA256 function from bouncycastle and it seems generate the hash correctly. At least from the few
experiments I've done. 

But since I need to verify RSA signature with SHA256 I would have to replace the SHA256Digest() implementation from
bouncycaste with a new one. So even if I would try to use example from Francesco, it would have to change it to provide
org.bouncycastle.crypto.Digest interface.  That would require proper tests if the implementation works as intended. 

The code for verifying the signature  looks like this:
RSADigestSigner signer = new RSADigestSigner(new SHA256Digest());
        signer.init(false, new RSAKeyParameters(false, modulus, exponent));
        
        try {
            signer.update(data.getBytes("UTF-8"), 0, data.getBytes("UTF-8").length);
        } catch (UnsupportedEncodingException ex) {
            Log.e(ex);
        }

        boolean verified = signer.verifySignature(sigDecode);

(it's from the example in the first post)



Dátum: štvrtok 2. júla 2020, čas: 5:25:53 UTC+2, odosielateľ: Shai Almog

Shai Almog

unread,
Jul 3, 2020, 12:02:25 AM7/3/20
to CodenameOne Discussions
Hi,
sorry I didn't spend too much time with that specific library so I was only able to follow your requirements part of the way.

The library is pretty old by now so it's probably due a refresh. You can submit a PR to the library if you know what needs doing.
Reply all
Reply to author
Forward
0 new messages