flutterencryptiondartrsapointycastle

How to import randomly generated 4096bit Java RSA public key from String


I have a network app that I'm trying to use with Java and Flutter and encryption. I'm using a 4096 bit RSA randomly generated keypair in Java and I'm using it to encrypt a randomly generated AES 256 bit key

I only need the Dart code as the Java code is already working.

In Java I am using this class

    /**
     * Create a key pair
     * @return The pair
     */
    public static KeyPair generateKeyPairs() {
        KeyPairGenerator keyGen;
        try {
            keyGen = KeyPairGenerator.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
        keyGen.initialize(4096);
        return keyGen.generateKeyPair();
    }

    public static String toBase64(Key publicKey) {
        byte[] encodedPublicKey = publicKey.getEncoded();
        return Base64.getEncoder().encodeToString(encodedPublicKey);
    }

    public static PublicKey toPublicKey(String base64PublicKey){
        PublicKey publicKey;
        try{
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes()));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            publicKey = keyFactory.generatePublic(keySpec);
            return publicKey;
        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return null;
    }

In Dart I am using PointyCastle and this method; however it doesn't work

  static RSAAsymmetricKey rsaPublicKeyFromString(String key) {
    String keyWithHeader = "-----BEGIN RSA PUBLIC KEY-----\n" + utf8.decode(base64Decode(key)) + "\n-----END RSA PUBLIC KEY-----";
    return RSAKeyParser().parse(keyWithHeader);
  }

Solution

  • Use the excellent basic_utils package.

    Dart

    import 'package:pointycastle/export.dart';
    import 'package:basic_utils/basic_utils.dart';
    
    void main() {
      var javaEncoded =
          'MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnitmaCHY8T171EiimoIN8MUg6IMi2JXbZBFioFJK9fiXnX/bo/6+1fuNgk+T/r6fbtk0iCogBCL30j/K7L+3J9p06rhvpM0/XAxi7YhMrIU5zetToZPBStzWt/qS1vOF2WFK6OfloFwFNAJltNljeVl7M7KbAkYcLxhfwyaPZTvmumAsCkkVhQevaVNBD2i6BWbMWb+3aki20FE2+nwzSa0ZgtwA9FJ4AV023eA1sw1ON9KS9eqdz78d/ve4aJJ/pv2Tvvc3iY2HhlvJmzS81tcocO660QediiI3K7rXus1QmGpHNEBvv818ai+RS4sehvyAhZl6dr+HH9zpdV0QESHqsyi7zJaal2GYeILdNGZtyYEsaqEq8K8MiynCvk7HSXHGZsx7zNFtVztc8T6ubN9sBDx4myFj/a1pdDltQ8OJGvomLX6wBwC0ywiroDeMAdbpfU1xNBYUqj8S0dTkrlul+ucbOySTpTpQJOnj9X98kptGnL2ESqi71vQh+qcMALjF/OqbGVOnPzzEqPlUWsR9jykmjBHkgeC9vSoMeGMdx+pUV7D1AXrXGs3ALOuBoUcBR00JPwIQ69wSZ/WFL9C9+gPfIvO802NEuckEYQB1eHVQFnhxdNF+slii+RBZ7UqnH3Fzvai4rPq5Yd/+Enxa8Gd3dqkO0QmkP5OSPzECAwEAAQ==';
    
      var pem =
          '-----BEGIN RSA PUBLIC KEY-----\n$javaEncoded\n-----END RSA PUBLIC KEY-----';
    
      RSAPublicKey public = CryptoUtils.rsaPublicKeyFromPem(pem);
      print(public.modulus);
    }
    

    where the long string was produced by this Java - shown for completeness.

    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
    keyGen.initialize(4096);
    KeyPair pair = keyGen.generateKeyPair();
    
    byte[] encodedPublicKey = pair.getPublic().getEncoded();
    System.out.println(Base64.getEncoder().encodeToString(encodedPublicKey));