Search code examples
androidflutterkotlindartencryption

How to implement rsa encryption in Dart using encrypt


I have a package written in Koltin and I want to rewrite it in Dart. I have been trying to use encrypt and pointycastle. But I'm having problems

How will I write this implementation in Dart.

I have started off with try to encode the public key var modulusBytes = base64.decode(publicKey!);

import android.util.Base64

import java.security.KeyFactory
import java.security.NoSuchAlgorithmException
import java.security.PublicKey
import java.security.spec.InvalidKeySpecException
import java.security.spec.X509EncodedKeySpec

import javax.crypto.Cipher



object Crypto {

    private const val PUBLIC_KEY = "MFwwDQYJKoZIhvcNAQEBBQADfafwfegRHqfkBiKGn/rrgrgrgrrgg" +
            "2wkeSokw2OJrCI+d6YGJPrHHx+nmb/Qn885/R01Gw6d7M824qofmCvkCAwEAAQ=="
    private const val ALGORITHM = "RSA"
    private const val CIPHER = "RSA/ECB/PKCS1Padding"

    private fun encrypt(text: String, key: PublicKey): ByteArray? {
        var cipherText: ByteArray? = null

        try {

            // get an RSA cipher object
            val cipher = Cipher.getInstance(CIPHER)

            //init cipher and encrypt the plain text using the public key
            cipher.init(Cipher.ENCRYPT_MODE, key)
            cipherText = cipher.doFinal(text.toByteArray())

        } catch (e: Exception) {

            e.printStackTrace()
        }

        return cipherText
    }
 
    

How do I used Byte Arrays in Dart?

I have this also as part of trying to encrypt the data in Koltin.

@Throws(SecurityException::class)
    fun encrypt(text: String): String {
        return String(Base64.encode(encrypt(text, getPublicKeyFromString(PUBLIC_KEY)), Base64.NO_WRAP))
    }
    

    @Throws(SecurityException::class)
    private fun getPublicKeyFromString(pubKey: String): PublicKey {

        val key: PublicKey

        try {
            //init keyFactory
            val kf = KeyFactory.getInstance(ALGORITHM)

            //decode the key into a byte array
            val keyBytes = Base64.decode(pubKey, Base64.NO_WRAP)

            //create spec
            val spec = X509EncodedKeySpec(keyBytes)

            //generate public key
            key = kf.generatePublic(spec)
        } catch (e: InvalidKeySpecException) {
            throw SecurityException("Invalid public key: " + e.message)
        } catch (e: NoSuchAlgorithmException) {
            throw SecurityException("Invalid public key: " + e.message)
        }

        return key

    }
}

Solution

  • I used two plugins basic_utils and pointycastle.

    import 'dart:async';
    import 'dart:convert';
    import 'dart:typed_data';
    import 'package:basic_utils/basic_utils.dart';
    import 'package:flutter/services.dart';
    import 'package:pointycastle/export.dart';
    
    class Cryptom {
      /// String Public Key
      String publickey =
          "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANIsL+RHqfkBiKGn/D1y1QnNrMkKzxWP" +
              "2wkeSokw2OJrCI+d6YGJPrHHx+nmb/Qn885/R01Gw6d7M824qofmCvkCAwEAAQ==";
    
      String encrypt(String plaintext, String publicKey) {
        /// After a lot of research on how to convert the public key [String] to [RSA PUBLIC KEY]
        /// We would have to use PEM Cert Type and the convert it from a PEM to an RSA PUBLIC KEY through basic_utils
        var pem =
            '-----BEGIN RSA PUBLIC KEY-----\n$publickey\n-----END RSA PUBLIC KEY-----';
        var public = CryptoUtils.rsaPublicKeyFromPem(pem);
    
        /// Initalizing Cipher
        var cipher = PKCS1Encoding(RSAEngine());
        cipher.init(true, PublicKeyParameter<RSAPublicKey>(public));
    
        /// Converting into a [Unit8List] from List<int>
        /// Then Encoding into Base64
        Uint8List output =
            cipher.process(Uint8List.fromList(utf8.encode(plaintext)));
        var base64EncodedText = base64Encode(output);
        return base64EncodedText;
      }
    
      String text(String text) {
        return encrypt(text, publickey);
      }
    }
    

    Then to run:

     String? result = Cryptom().text("TEXT TO BE ENCRYPTED");
          print(result);