PointyCastle / pointycastle

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

AES result is different with aes-js or nodejs #154

Closed catouse closed 5 years ago

catouse commented 6 years ago

AES/CBC/PKCS7 in pointycastle:

import 'dart:typed_data';
import 'dart:convert';
import "package:pointycastle/export.dart";

Uint8List encrypt(String data, String token, String cipherIV) {
    var key = new SHA256Digest().process(UTF8.encode(token));
    var iv = new SHA256Digest().process(UTF8.encode(cipherIV)).sublist(0, 16);
    CipherParameters params = new PaddedBlockCipherParameters(new ParametersWithIV(new KeyParameter(key), iv), null);

    PaddedBlockCipherImpl cipherImpl = new PaddedBlockCipherImpl(new PKCS7Padding(), new CBCBlockCipher(new AESFastEngine()));
    cipherImpl.init(true, params);
    return cipherImpl.process(UTF8.encode(data));
}

// Test Code:
var message = 'Hello world!';
var token = '01234567890123456789012345678901';
var cipherIV = '0123456789012345';
var result = encrypt(message, token, cipherIV);

print('result=$result');

The result with pointycastle is:

[93, 230, 77, 13, 75, 37, 207, 197, 131, 60, 244, 178, 212, 245, 233, 46]

encrypt with aes-js

AES-JS: https://github.com/ricmoo/aes-js

import AES from 'aes-js';

const encrypt = (data, token, cipherIV) => {
    const key = AES.utils.utf8.toBytes(token);
    const iv = AES.utils.utf8.toBytes(cipherIV);
    const aesCbc = new AES.ModeOfOperation.cbc(key, iv);
    const dataBytes = AES.utils.utf8.toBytes(data);
    const paddedData = AES.padding.pkcs7.pad(dataBytes);
    const encryptedBytes = aesCbc.encrypt(paddedData);
    return encryptedBytes;
};

// Test Code:
var message = 'Hello world!';
var token = '01234567890123456789012345678901';
var cipherIV = '0123456789012345';
var result = encrypt(message, token, cipherIV);

console.log('result: ' + result);

The result with aes-js is:

[200, 168, 149, 245, 48, 112, 221, 227, 109, 217, 11, 202, 214, 71, 87, 107]

encrypt with nodejs

Crypto in Nodejs: https://nodejs.org/api/crypto.html

import crypto from 'crypto';

const encrypt = (data, token, cipherIV) => {
    const cipher = crypto.createCipheriv('aes-256-cbc', token, cipherIV);
    let crypted = cipher.update(data, 'utf8', 'binary');
    crypted += cipher.final('binary');
    crypted = new Buffer(crypted, 'binary');
    return crypted;
};

// Test Code:
var message = 'Hello world!';
var token = '01234567890123456789012345678901';
var cipherIV = '0123456789012345';
var result = encrypt(message, token, cipherIV);

console.log('result: ' + result);

The result with nodejs:

[200, 168, 149, 245, 48, 112, 221, 227, 109, 217, 11, 202, 214, 71, 87, 107]

It is same with aes-js.

stevenroose commented 5 years ago

DId you take a look at this example? https://github.com/PointyCastle/pointycastle/pull/111

raodaqi commented 5 years ago

I had the same problem

raodaqi commented 5 years ago

Do not use SHA-256 encryption

import 'dart:typed_data';
import 'dart:convert';
import "package:pointycastle/export.dart";

Uint8List encrypt(String data, String token, String cipherIV) {
    var key = utf8.encode(token);
    var iv = utf8.encode(cipherIV);
    CipherParameters params = new PaddedBlockCipherParameters(new ParametersWithIV(new KeyParameter(key), iv), null);

    PaddedBlockCipherImpl cipherImpl = new PaddedBlockCipherImpl(new PKCS7Padding(), new CBCBlockCipher(new AESFastEngine()));
    cipherImpl.init(true, params);
    return cipherImpl.process(utf8.encode(data));
}

// Test Code:
var message = 'Hello world!';
var token = '01234567890123456789012345678901';
var cipherIV = '0123456789012345';
var result = encrypt(message, token, cipherIV);

print('result=$result');

The result with pointycastle is:

[200, 168, 149, 245, 48, 112, 221, 227, 109, 217, 11, 202, 214, 71, 87, 107]

@catouse

catouse commented 5 years ago

@raodaqi Thanks.

Nguyenpk57 commented 5 years ago
import 'dart:typed_data';
import 'dart:convert';
import "package:pointycastle/export.dart";

Uint8List encrypt(String data, String token, String cipherIV) {
    var key = utf8.encode(token);
    var iv = utf8.encode(cipherIV);
    CipherParameters params = new PaddedBlockCipherParameters(new ParametersWithIV(new KeyParameter(key), iv), null);

    PaddedBlockCipherImpl cipherImpl = new PaddedBlockCipherImpl(new PKCS7Padding(), new CBCBlockCipher(new AESFastEngine()));
    cipherImpl.init(true, params);
    return cipherImpl.process(utf8.encode(data));
}

// Test Code:
var message = 'Hello world!';
var token = '01234567890123456789012345678901';
var cipherIV = '0123456789012345';
var result = encrypt(message, token, cipherIV);

print('result=$result');

i have used the above code to encrypt on js But does it seem that AES.js cannot be decrypted? because there is no unpad method I see above you have to add the pad Do you have any way? @raodaqi

Nguyenpk57 commented 5 years ago
import 'dart:convert';
import 'dart:typed_data';

import "package:pointycastle/export.dart";

Uint8List encrypt(String data, String token, String cipherIV) {
  var key = utf8.encode(token);
  var iv = utf8.encode(cipherIV);
  CipherParameters params = new PaddedBlockCipherParameters(
      new ParametersWithIV(new KeyParameter(key), iv), null);

  PaddedBlockCipherImpl cipherImpl = new PaddedBlockCipherImpl(
      new PKCS7Padding(), new CBCBlockCipher(new AESFastEngine()));
  cipherImpl.init(true, params);
  return cipherImpl.process(utf8.encode(data));
}

String decrypt(Uint8List data, String token, String cipherIV) {
  var key = utf8.encode(token);
  var iv = utf8.encode(cipherIV);
  CipherParameters params = new PaddedBlockCipherParameters(
      new ParametersWithIV(new KeyParameter(key), iv), null);

  PaddedBlockCipherImpl cipherImpl = new PaddedBlockCipherImpl(new PKCS7Padding(), new CBCBlockCipher(new AESFastEngine()));
  cipherImpl.init(false, params);

  return utf8.decode(cipherImpl.process(data));
}

// Test Code:

void main() {
  var message = 'Ngoc create a chatroom. 👻 👻  김진학테스트 tiếng việt';
  var token = '20180531100733_userUid02_15277360532520000'.substring(0, 32);
  var cipherIV = '20180531100733_userUid02_15277360532520000'.substring(0, 16);
  var result = encrypt(message, token, cipherIV);
  print(result);

  String resultBase64 = base64.encode(result);
  print(resultBase64);

  print(decrypt(base64.decode(resultBase64), token, cipherIV));
}

Here my code on the flutter dart I used to decode and encode. It's okie

Nguyenpk57 commented 5 years ago

const decryptByAES = (message, keyRSA) => { var cipherIV = keyRSA.substring(0,16); keyRSA = keyRSA.substring(0,32);

const key = aesjs.utils.utf8.toBytes(keyRSA);
const iv = aesjs.utils.utf8.toBytes(cipherIV);
const aesCbc = new aesjs.ModeOfOperation.cbc(key, iv);

var decryptedBytes = aesCbc.decrypt(aesjs.utils.hex.toBytes(message));

const unpadData = aesjs.padding.pkcs7.strip(decryptedBytes);

return aesjs.utils.utf8.fromBytes(unpadData);

};

here my code decrypt use AES