Search code examples
androidbouncycastle

Bouncycastle fails in android API < 21


i am trying to run some spongycastle code in android:

    try {
        Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider());
        ECGenParameterSpec spec = new ECGenParameterSpec("P-256");
        KeyPairGenerator generator = KeyPairGenerator.getInstance("ECDSA", "SC");
        generator.initialize(spec, new SecureRandom());
        KeyPair keyPair = generator.generateKeyPair();
        ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic();
        ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate();
        String publicKeyStr = publicKey.getW().getAffineX().toString() + ":" + publicKey.getW().getAffineY().toString();
        Log.d(TAG, publicKeyStr);
        Calendar c = Calendar.getInstance();
        Date d0 = c.getTime();
        c.add(Calendar.DATE, 1);
        Date expiry = c.getTime();
        String token = Jwts.builder()
                .setIssuedAt(d0)
                .setSubject("00000000-0000-0000-0000-000000000001")
                .setExpiration(expiry)
                .signWith(privateKey, SignatureAlgorithm.ES256).compact();
        Log.d(TAG, token);
    } catch (Exception e) {
        Log.d(TAG, e.toString());
    }

in API version 21+, it works as expected.

in API version 18, it works in debug. in release, it fails in function generator.generateKeyPair() with java.lang.IllegalArgumentException: Invalid point.

in API version 16, it fails in function Jwts.builder().signWith() with io.jsonwebtoken.security.SignatureException: Invalid Elliptic Curve PrivateKey. can't recognise key type in ECDSA based signer.

any idea what i am doing wrong?

edit: i have apparently fixed the problem by switching from spongycastle to bouncycastle.

in my build.gradle i changed this:

implementation 'com.madgag.spongycastle:core:1.58.0.0'
implementation 'com.madgag.spongycastle:prov:1.58.0.0'

to this:

implementation 'org.bouncycastle:bcpkix-jdk15on:1.60'

and in my code i got rid of this line:

Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider());

and added these lines:

import org.bouncycastle.jce.provider.BouncyCastleProvider;

Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
Security.insertProviderAt(new BouncyCastleProvider(), 1);

and i changed the provider from "SC" to "BC".

and now my code works as i would like, for all versions of the android API.

my concern now is the comment at this link...

Spongy Castle: is it obsolete?

...by the author of spongycastle:

Why might Spongy Castle not be obsolete?

...

even on post-Android 3.0 devices, device manufacturers are not above carelessly bundling libraries, it's possible that Bouncy Castle may still be bundled on some obscure devices.

what does that mean exactly? could it cause my code above to malfunction on certain devices?


Solution

  • use bouncy castle:

    dependencies {
        // https://mvnrepository.com/artifact/org.bouncycastle
        implementation "org.bouncycastle:bcprov-jdk15on:1.60"
        implementation "org.bouncycastle:bcpkix-jdk15on:1.60"
    }