PointyCastle / pointycastle

Moved into the Bouncy Castle project: https://github.com/bcgit/pc-dart
MIT License
270 stars 76 forks source link

AESFastEngine encryption gives :Input buffer too short, for UTF non english characters #229

Closed anuragvohraec closed 4 years ago

anuragvohraec commented 4 years ago

Hi Team,

Please check this code:

 test("Case 2: Bug UTF8 Character",() async{
    var key = "1234567812345678";

    var _byteEncoder  = Utf8Encoder();
    var _key= KeyParameter(_byteEncoder.convert(key));

    String _padIfRequired(String data, int blockSize){
      //here we will do the actual encryption and send
      var origDataSize = data.length;
      var remainder  = origDataSize % blockSize;
      if(remainder!=0){
        data = data+(" "*(blockSize-remainder));
      }
      return data;
    }

    Uint8List _processAllBlocks(BlockCipher cipher, Uint8List wholedata){
      Uint8List result = Uint8List(wholedata.length);
      for(int offset =0; offset<wholedata.length; offset+=cipher.blockSize){
        cipher.processBlock(wholedata, offset, result, offset);
      }
      return result;
    }

    AESFastEngine _aesForEncryption =  AESFastEngine();
    _aesForEncryption.init(true, _key);

    String encrypt(String input){
      input = _padIfRequired(input, _aesForEncryption.blockSize);
      Uint8List wholedata = _byteEncoder.convert(input);
      return base64Encode(_processAllBlocks(_aesForEncryption, wholedata));
    }
    String msg ='''{"lang":"हिंदी"}''';
    String encryptedtext  = encrypt(msg);
    print(encryptedtext);
  });

It gives me : Invalid argument(s): Input buffer too short error for only utf characters for example "हिंदी".

dbarzdys commented 4 years ago

I'm having the same problem. Any ideas on what could cause this issue?

anuragvohraec commented 4 years ago

I'm having the same problem. Any ideas on what could cause this issue?

Ok All right I got the issue and its fix. The issue is while padding white spaces! padding should be done after a String is converted to bytes. In this bytes you add empty padded bytes.

Here is the updated test case.

test("Case 2: Bug UTF8 Character",() async{
    var key = "1234567812345678";

    var _byteEncoder  = Utf8Encoder();
    var _key= KeyParameter(_byteEncoder.convert(key));

    Uint8List _padIfRequired(Uint8List origdata, int blockSize){
      var result = origdata;
      //here we will do the actual encryption and send
      var origDataSize = origdata.length;
      var remainder  = origDataSize % blockSize;
      if(remainder!=0){
        List<int> padded_data = List.from(origdata);
        padded_data.addAll(_byteEncoder.convert((" "*(blockSize-remainder))));
        result=Uint8List.fromList(padded_data);
      }
      return result;
    }

    Uint8List _removePadIfRequired(Uint8List padded_data){
      List<int> orig_data = List.from(padded_data);
      int i = " ".codeUnitAt(0);
      while(orig_data.last == i){
        orig_data.removeLast();
      }
      return Uint8List.fromList(orig_data);
    }

    Uint8List _processAllBlocks(BlockCipher cipher, Uint8List wholedata){
      Uint8List result = Uint8List(wholedata.length);
      for(int offset =0; offset<wholedata.length; offset+=cipher.blockSize){
        cipher.processBlock(wholedata, offset, result, offset);
      }
      return result;
    }

    AESFastEngine _aesForEncryption =  AESFastEngine();
    _aesForEncryption.init(true, _key);

    String encrypt(String input){
      Uint8List origdata = _byteEncoder.convert(input);
      Uint8List padeddata = _padIfRequired(origdata, _aesForEncryption.blockSize);
      Uint8List encryptedBytes=_processAllBlocks(_aesForEncryption, padeddata);
      return base64Encode(encryptedBytes);
    }
    String msg ='''{"lang":"हिंदी"}''';
    String encryptedtext  = encrypt(msg);
    print(encryptedtext);

    AESFastEngine _aesForDecryption =  AESFastEngine();
    _aesForDecryption.init(false, _key);

    var _byteDecoder  = Utf8Decoder();
    String  decrypt(String inputBase64Data){
      Uint8List encryptedBytes = base64Decode(inputBase64Data);
      Uint8List decryptedBytes = _processAllBlocks(_aesForDecryption, encryptedBytes);
      Uint8List unpaddedData = _removePadIfRequired(decryptedBytes);
      return _byteDecoder.convert(unpaddedData);
    }

    String decryptedtext = decrypt(encryptedtext);
   print(decryptedtext);
  });