1

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);
  }
Richard Heap
  • 48,344
  • 9
  • 130
  • 112
Fern
  • 93
  • 6
  • 16
  • Instead of encrypting the AES key, you should prefer RSA-KEM. Generate a random element in [1..n] with a good random source, then use a Key Derivation Function like HKDF and use this AES key. Encrypt the random element with the public key. send both to the receiver. In this case, RSA don't need a padding. – kelalaka Jan 01 '20 at 13:44

1 Answers1

3

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));
Richard Heap
  • 48,344
  • 9
  • 130
  • 112
  • Thanks! You've been super helpful with my encryption problems. Have a happy new decade :D – Fern Jan 01 '20 at 02:53