问题描述
我必须实现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 (将#修改为@)