PointyCastle / pointycastle

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

AES CFB-128 encryption and decryption #152

Closed proteye closed 6 years ago

proteye commented 6 years ago

How to implement AES with CFB-128 mode?

My code:

    var cipher = AesHelper.cfbEncrypt('password', 'Hello world! Hello world!');
    print('AES: $cipher');
    var text = AesHelper.cfbDecrypt('password', cipher);
    print('AES: $text');

gives the result

flutter: AES: b0f850b07a57605a8f6fba9d99363b0052033ca577f27d76984d853d090b17622a6d8e513665fcf430b9696ee5f4293c
flutter: AES: Hello world! Hel\^Bh+@¯ƒ\^\   Õ?ŽËŽlD <…>
  // AES-256 (CFB) encryption
  static String cfbEncrypt(String password, String plaintext) {
    print('LEN: ${plaintext.length}');
    Uint8List derivedKey = deriveKey(password);
    KeyParameter keyParam = new KeyParameter(derivedKey);
    BlockCipher aes = new AESFastEngine();

    var rnd = FortunaRandom();
    rnd.seed(keyParam);
    Uint8List iv = rnd.nextBytes(16);

    ParametersWithIV cfbParams = new ParametersWithIV(keyParam, iv);
    CFBBlockCipher cfb = new CFBBlockCipher(aes, aes.blockSize);
    cfb.init(true, cfbParams);

    Uint8List textBytes = createUint8ListFromString(plaintext);
    Uint8List paddedText = pad(textBytes, aes.blockSize);
    Uint8List cipherBytes = _processBlocks(cfb, paddedText);
    Uint8List cipherIvBytes = new Uint8List(cipherBytes.length + iv.length)
      ..setAll(0, iv)
      ..setAll(iv.length, cipherBytes);

    return formatBytesAsHexString(cipherIvBytes);
  }

  // AES-256 (CFB) decryption
  static String cfbDecrypt(String password, String ciphertext) {
    Uint8List derivedKey = deriveKey(password);
    KeyParameter keyParam = new KeyParameter(derivedKey);
    BlockCipher aes = new AESFastEngine();

    Uint8List cipherIvBytes = createUint8ListFromHexString(ciphertext);
    Uint8List iv = new Uint8List(aes.blockSize)
      ..setRange(0, aes.blockSize, cipherIvBytes);

    ParametersWithIV cfbParams = new ParametersWithIV(keyParam, iv);
    CFBBlockCipher cfb = new CFBBlockCipher(aes, aes.blockSize);
    cfb.init(true, cfbParams);

    int cipherLen = cipherIvBytes.length - aes.blockSize;
    Uint8List cipherBytes = new Uint8List(cipherLen)
      ..setRange(0, cipherLen, cipherIvBytes, aes.blockSize);
    Uint8List textBytes = _processBlocks(cfb, cipherBytes);

    return new String.fromCharCodes(textBytes);
  }

  static Uint8List _processBlocks(BlockCipher cipher, Uint8List inp) {
    var out = new Uint8List(inp.lengthInBytes);

    for (var offset = 0; offset < inp.lengthInBytes;) {
      var len = cipher.processBlock(inp, offset, out, offset);
      offset += len;
    }

    return out;
  }
proteye commented 6 years ago

This code is work:

  // AES-256 (CFB) encryption
  static String cfbEncrypt(String password, String plaintext) {
    Uint8List derivedKey = deriveKey(password);
    KeyParameter keyParam = new KeyParameter(derivedKey);
    BlockCipher aes = new AESFastEngine();

    var rnd = FortunaRandom();
    rnd.seed(keyParam);
    Uint8List iv = rnd.nextBytes(16);

    ParametersWithIV cfbParams = new ParametersWithIV(keyParam, iv);
    CFBBlockCipher cfb = new CFBBlockCipher(aes, aes.blockSize);
    cfb.init(true, cfbParams);

    Uint8List textBytes = createUint8ListFromString(plaintext);
    Uint8List paddedText = pad(textBytes, aes.blockSize);
    Uint8List cipherBytes = _processBlocks(cfb, paddedText);
    Uint8List cipherIvBytes = new Uint8List(cipherBytes.length + iv.length)
      ..setAll(0, iv)
      ..setAll(iv.length, cipherBytes);

    return formatBytesAsHexString(cipherIvBytes);
  }

  // AES-256 (CFB) decryption
  static String cfbDecrypt(String password, String ciphertext) {
    Uint8List derivedKey = deriveKey(password);
    KeyParameter keyParam = new KeyParameter(derivedKey);
    BlockCipher aes = new AESFastEngine();

    Uint8List cipherIvBytes = createUint8ListFromHexString(ciphertext);
    Uint8List iv = new Uint8List(aes.blockSize)
      ..setRange(0, aes.blockSize, cipherIvBytes);

    ParametersWithIV cfbParams = new ParametersWithIV(keyParam, iv);
    CFBBlockCipher cfb = new CFBBlockCipher(aes, aes.blockSize);
    cfb.init(false, cfbParams);

    int cipherLen = cipherIvBytes.length - aes.blockSize;
    Uint8List cipherBytes = new Uint8List(cipherLen)
      ..setRange(0, cipherLen, cipherIvBytes, aes.blockSize);
    Uint8List paddedText = _processBlocks(cfb, cipherBytes);
    Uint8List textBytes = unpad(paddedText);

    return new String.fromCharCodes(textBytes);
  }

  static Uint8List _processBlocks(BlockCipher cipher, Uint8List inp) {
    var out = new Uint8List(inp.lengthInBytes);

    for (var offset = 0; offset < inp.lengthInBytes;) {
      var len = cipher.processBlock(inp, offset, out, offset);
      offset += len;
    }

    return out;
  }