Flutter AES128加密与Java和角度AES加密不匹配

问题描述

我必须实现dart算法才能对密码进行加密,然后将其发送到服务器,以通过Flutter应用程序进行身份验证(距离我使用Flutter / dart几乎不到一周)。这已经在Android应用程序和angular Web应用程序中实现(不是我提供的),即使使用不同的算法,它们都可以产生相同的加密密码。

适用于Android的Java代码

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

import java.io.UnsupportedEncodingException;
import java.security.CryptoPrimitive;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;

public class AesUtil {
    private final int keySize;
    private final int iterationCount;
    private final Cipher cipher;

    public AesUtil(int keySize,int iterationCount) {
        this.keySize = keySize;
        this.iterationCount = iterationCount;
        try {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw fail(e);
        }
    }

    public String decrypt(String salt,String iv,String passphrase,String ciphertext) {
        try {
            SecretKey key = generateKey(salt,passphrase);
            byte[] decrypted = doFinal(Cipher.DECRYPT_MODE,key,iv,base64(ciphertext));
            return new String(decrypted,"UTF-8");
        } catch (UnsupportedEncodingException e) {
            return null;
        } catch (Exception e) {
            return null;
        }
    }

    private byte[] doFinal(int encryptMode,SecretKey key,byte[] bytes) {
        try {
            cipher.init(encryptMode,new IvParameterSpec(hex(iv)));
            return cipher.doFinal(bytes);
        } catch (InvalidKeyException
                | InvalidAlgorithmParameterException
                | IllegalBlockSizeException
                | BadPaddingException e) {
            return null;
        }
    }

    private SecretKey generateKey(String salt,String passphrase) {
        try {
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            KeySpec spec = new PBEKeySpec(passphrase.tochararray(),hex(salt),iterationCount,keySize);
            SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(),"AES");
            return key;
        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            return null;
        }
    }

    public static byte[] base64(String str) {
        return Base64.decode(str);
    }

    public static String base64(byte[] bytes) {
        return new String(Base64.encode(bytes));
    }

    public static byte[] hex(String str) {
        try {
            return Hex.decode(str);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    public static String hex(byte[] bytes) {
        return Hex.encode(bytes).toString();
    }

    private IllegalStateException fail(Exception e) {
        return null;
    }


    public String random(int length) {
        byte[] salt = new byte[length];
        new SecureRandom().nextBytes(salt);
        return hex(salt);
    }

    public String encrypt(String salt,String plaintext) {
        try {
            SecretKey key = generateKey(salt,passphrase);
            byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE,plaintext.getBytes("UTF-8"));


            return base64(encrypted);
        } catch (UnsupportedEncodingException e) {
            throw fail(e);
        }
    }

    public String encriptToAES(String password) {
        //`
        //for some reasons key,iv and salt are hardcoded string
        //
        final String key = "hardcoded_key_16_characters";
         
        final String iv = "hardcoded_iv_32_characters";
        final String salt = "hardcoded_salt_32_characters";
        String ciphertext = encrypt(salt,password);

        String preEncr = new String(Base64.encode((iv + "::" + salt + "::" + ciphertext).getBytes()));
        return preEncr;
    }
}

这是生成加密密码的Java代码行: AesUtil(128,1000).encriptToAES(password)

角度的JS代码

import * as CryptoJS from 'crypto-js';

export class AesUtil{
private keySize;
private iterationCount;
  constructor(keySize,iterationCount) {
    this.keySize = keySize / 32;
    this.iterationCount = iterationCount;
  };
  
  generateKey(salt,passphrase) {
    var key = CryptoJS.PBKDF2(
        passphrase,CryptoJS.enc.Hex.parse(salt),{ keySize: this.keySize,iterations: this.iterationCount });
    return key;
  }
  
  encrypt(salt,passphrase,plainText) {
    var key = this.generateKey(salt,passphrase);
    var encrypted = CryptoJS.AES.encrypt(
        plainText,{ iv: CryptoJS.enc.Hex.parse(iv) });
    return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
  }
  
  decrypt(salt,cipherText) {
    var key = this.generateKey(salt,passphrase);
    var cipherParams = CryptoJS.lib.CipherParams.create({
      ciphertext: CryptoJS.enc.Base64.parse(cipherText)
    });
    var decrypted = CryptoJS.AES.decrypt(
        cipherParams,{ iv: CryptoJS.enc.Hex.parse(iv) });
    return decrypted.toString(CryptoJS.enc.Utf8);
  }
}

这段代码可以达到目的:

const iv = CryptoJS.lib.WordArray.random(128/8).toString(CryptoJS.enc.Hex);
const salt = CryptoJS.lib.WordArray.random(128/8).toString(CryptoJS.enc.Hex);

const aesUtil = newAesUtil(128,1000);
const cipherText = aesUtils.encrypt(salt,'hardcoded_key_16_characters',password);
const aesPassword = (iv+ '::' + salt + '::'+ cipherText);
const encryptedPassword = btoa(aesPassword);

据我所知,我需要一种AES128加密方法,该方法可在其中设置特定的迭代次数,该方法可接受iv和salt并最终使用Base64加密结果。

我已经在pub.dev和摘要上尝试了各种dart加密软件包,但均未成功。

我特别依赖this,但是即使使用了硬编码的参数,结果密码也不匹配,我也无法弄清楚原因。有谁知道我必须关注哪些元素才能在颤动中获得相同的结果?例如,我应该使用哪个aes128'plugin'?静态或随机静脉注射和加盐?各种各样的事情,我几乎迷失了。谢谢

更新:

import 'dart:typed_data';
import 'dart:convert';
import 'package:cryptography/cryptography.dart';

final password = "justatest";
final key = "0123456789abcdef";
final iv = "0123456789abcdefghijklmnopqrstuv";
final salt = "abcdefghijklmnopqrstuvwzyz012345";

encryptAESCryptoJS() {
  final pbkdf2 = Pbkdf2(
    macAlgorithm: Hmac(sha1),iterations: 1000,bits: 128,);

  final Uint8List hashBytes = pbkdf2.deriveBitsSync(
    utf8.encode(key),nonce: Nonce(utf8.encode(salt)),);

}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)