Convert Java RSA Asymmetric encryption to Flutter Dart

3,017

Try this:

import 'dart:math';
import 'dart:convert';
import 'dart:typed_data';

import 'package:convert/convert.dart';
import 'package:pointycastle/api.dart';
import 'package:pointycastle/asymmetric/api.dart';
import 'package:pointycastle/asymmetric/rsa.dart';

String encrypt(String plaintext, String publicKey) {
  var modulusBytes = base64.decode(publicKey);
  var modulus = BigInt.parse(hex.encode(modulusBytes), radix: 16);
  var exponent = BigInt.parse(hex.encode(base64.decode('AQAB')), radix: 16);
  var engine = RSAEngine()
    ..init(
      true,
      PublicKeyParameter<RSAPublicKey>(RSAPublicKey(modulus, exponent)),
    );

  //PKCS1.5 padding
  var k = modulusBytes.length;
  var plainBytes = utf8.encode(plaintext);
  var paddingLength = k - 3 - plainBytes.length;
  var eb = Uint8List(paddingLength + 3 + plainBytes.length);
  var r = Random.secure();
  eb.setRange(paddingLength + 3, eb.length, plainBytes);
  eb[0] = 0;
  eb[1] = 2;
  eb[paddingLength + 2] = 0;
  for (int i = 2; i < paddingLength + 2; i++) {
    eb[i] = r.nextInt(254) + 1;
  }

  print(plainBytes.length);
  print(eb);

  return base64.encode(
    engine.process(eb),
  );
}
Share:
3,017
ibnhamza
Author by

ibnhamza

Updated on December 11, 2022

Comments

  • ibnhamza
    ibnhamza over 1 year

    I'm trying to port our android mobile app to Flutter. It was written in Java. However, there is this part where I need to encrypt the login credential and card details with RSA encryption before posting to the server which I've not been able to get right.

    I've tried several flutter packages which doesn't work. According to the Java developer, there is a public key which is base64 encoded that needs to be used in encrypting the password.

    Here is the Java code

    public  static  String Encrypt(String plaintext, String publicKey ) throws Exception {
      try
      {
    
          if(StringUtils.isEmpty(plaintext)) return "";
          byte[] modulusBytes = Base64.decode(publicKey.getBytes("UTF-8"),Base64.DEFAULT);
          byte[] exponentBytes = Base64.decode("AQAB".getBytes("UTF-8"),Base64.DEFAULT);
          BigInteger modulus = new BigInteger(1, modulusBytes );
          BigInteger exponent = new BigInteger(1, exponentBytes);
          RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent);
          KeyFactory fact = KeyFactory.getInstance("RSA");
          PublicKey pubKey = fact.generatePublic(rsaPubKey);
    
          Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
          cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    
          byte[] plainBytes = new String(plaintext).getBytes("UTF-8");
          byte[] cipherData = cipher.doFinal( plainBytes );
    
    
          String outputEncrypted = Base64.encodeToString(cipherData,Base64.NO_WRAP);
    
          return  outputEncrypted;
    
      }catch (Exception ex)
      {
          Log.i("Exception", ex.getMessage());
          throw  ex;
    
      }
    
    }
    

    I'll appreciate if I can get any help to convert this to dart so I can use it in the flutter code.

    UPDATE

    I tried @Richard Heap pointycastle encryption which seems to work fine but the server was unable to decrypt the string. Exception thrown

    Interop+AppleCrypto+AppleCFErrorCryptographicException: The operation couldn’t be completed. (OSStatus error -2147415994 - CSSMERR_CSP_INVALID_DATA)
       at Interop.AppleCrypto.ExecuteTransform(SecKeyTransform transform)
       at Interop.AppleCrypto.RsaDecrypt(SafeSecKeyRefHandle privateKey, Byte[] data, RSAEncryptionPadding padding)
       at System.Security.Cryptography.RSAImplementation.RSASecurityTransforms.Decrypt(Byte[] data, RSAEncryptionPadding padding)
       at System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb, Boolean fOAEP)
    
    
    Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: The parameter is incorrect
       at Internal.NativeCrypto.CapiHelper.DecryptKey(SafeKeyHandle safeKeyHandle, Byte[] encryptedData, Int32 encryptedDataLength, Boolean fOAEP, Byte[]& decryptedData)
       at System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb, Boolean fOAEP
    

    The decryption method on the server is written with C#

    UPDATE 2

    Finally got this to work after hours of googling I landed on this github issue on PointyCastle and the solution by duncanhoggan. Turned out I just needed to use PKCS1Encoding.

      var pubKey = RSAPublicKey(modulus, exponent);
      var cipher = PKCS1Encoding(RSAEngine());
      cipher.init(true, PublicKeyParameter<RSAPublicKey>(pubKey));
      Uint8List output = cipher.process(utf8.encode(text));
      var base64EncodedText = base64Encode(output);
      return base64EncodedText;
    

    @Richard Heap, thanks for helping.

    • Richard Heap
      Richard Heap almost 5 years
      Have you tried pointy castle? Where did you get stuck?
  • ibnhamza
    ibnhamza almost 5 years
    Thanks Richard. Heard of PointyCastle but haven't really tried using it. Was thinking dart was gonna have some built in encryption suit. Would try out your solution.
  • ibnhamza
    ibnhamza almost 5 years
    I didn't have any issue encryption but the server was unable to decrypt my encrypted string. I debugged and it was throwing an exception at the point of decrypting. I've updated my question with the exception.
  • Richard Heap
    Richard Heap almost 5 years
    Dart, by design, has very little built in. This kind of add-on library is added in packages, like pointy castle. Updated the question with PKCSv1.5 padding implementation.
  • Pravin Divraniya
    Pravin Divraniya over 2 years
    What is hex value?
  • Richard Heap
    Richard Heap over 2 years
    @PravinDivraniya hex is a const value from the convert package (note the extra package import) for a hexadecimal codec.
  • Hemavathi
    Hemavathi about 2 years
    do we have EncodedKeySpec in flutter
  • Hemavathi
    Hemavathi about 2 years
    @RichardHeap i m trying to convert java code to flutter please refer stackoverflow.com/questions/70576691/… any help is appreciated