flutter中如何实现AES加密?

问题描述 投票:0回答:1

我在将flutter中的加密与我的BE服务中的加密匹配时遇到问题,两个系统中的密钥和iv是相同的,我不知道我在flutter中做错了什么,但它无法解密BE发送的消息服务。这是BE服务中的加密和解密函数。

func EncryptData(data string) (string, error) {
    var key = []byte(config.CipherConfig.Key)
    var iv = []byte(config.CipherConfig.Iv)

    block, err := aes.NewCipher(key)
    if err != nil {
        return "", err
    }

    ciphertext := make([]byte, aes.BlockSize+len(data))
    stream := cipher.NewCFBEncrypter(block, iv)
    stream.XORKeyStream(ciphertext[aes.BlockSize:], []byte(data))

    return hex.EncodeToString(ciphertext[aes.BlockSize:]), nil
}

// Function to decrypt data
func DecryptData(encryptedData string) (string, error) {
    var key = []byte(config.CipherConfig.Key)
    var iv = []byte(config.CipherConfig.Iv)

    block, err := aes.NewCipher(key)
    if err != nil {
        return "", err
    }

    ciphertext, err := hex.DecodeString(encryptedData)
    if err != nil {
        return "", err
    }

    stream := cipher.NewCFBDecrypter(block, iv)
    stream.XORKeyStream(ciphertext, ciphertext)

    return string(ciphertext), nil
}

这里的flutter部分,我使用了加密包,结果似乎不正确。我不是创建 BE 的人,所以我不完全理解它的作用,我需要在我的 flutter 代码中更改哪些内容才能使结果匹配? (秘钥和iv已经一样了)

static String encrypt(String data) {
    final iv = IV.fromUtf8(Env.iv);
    final encrypter = Encrypter(AES(Key.fromUtf8(Env.secretKey), mode: AESMode.cfb64));
    return encrypter.encrypt(data, iv: iv).base16;
  }

  static String decrypt(String data) {
    final iv = IV.fromUtf8(Env.iv);
    final encrypter = Encrypter(AES(Key.fromUtf8(Env.secretKey), mode: AESMode.cfb64));
    return encrypter.decrypt16(data, iv: iv);
  }
flutter go encryption
1个回答
0
投票

CFB模式需要指定段大小(段大小定义每个加密步骤加密的位数)。 Go 代码使用 128 位,Dart 代码使用 64 位,因此两种代码不兼容。

加密包不允许更改段大小,因此必须替换该库。 加密PointyCastle库的一些功能的包装。后者支持128位的段大小,因此可以直接使用PointyCastle


但是,PointyCastle 实现有一个需要解决的缺点:CFB 模式是一种流密码模式,可以加密任意长度的明文而无需填充。 Go 实现考虑到了这一点,但不幸的是,

PointyCastle 实现没有考虑到这一点,并且要求明文长度是段大小的整数倍。 要使用
PointyCastle 实现加密 any 长度的明文,必须在加密之前将明文填充到所需的长度,并且必须将生成的密文缩短填充字节数。由于明文长度已知,因此任何填充,例如零填充,可以使用。 在解密过程中,密文必须在解密前填充到所需的长度,并且所得的明文必须缩短填充字节数。


以下 Dart 代码使用

PointyCastle 使用 CFB-128 加密任意长度的明文,并且与 Go 代码兼容:

import 'dart:convert'; import 'dart:typed_data'; import 'package:convert/convert.dart'; import 'package:pointycastle/export.dart'; String encrypt(String plaintext){ var key = utf8.encode("01234567890123456789012345678901"); // for the test only var iv = utf8.encode("abcdefghijklmnop"); // for the test only var pt = utf8.encode(plaintext); var keyParam = KeyParameter(key); var params = ParametersWithIV(keyParam, iv); // Zero pad plaintext var aesBlockSize = 16; var padLength = (aesBlockSize - (pt.length % aesBlockSize)) % aesBlockSize; var ptPadded = Uint8List(pt.length + padLength)..setAll(0, pt); // Encrypt var cipher = BlockCipher("AES/CFB-128"); cipher.init(true, params); var ctPadded = Uint8List(ptPadded.length); for (int offset = 0; offset < ptPadded.length;) { int len = cipher.processBlock(ptPadded, offset, ctPadded, offset); offset += len; } // Remove padding var ct = ctPadded.sublist(0, pt.length); return hex.encode(ct); } String decrypt(String ciphertext) { var key = utf8.encode("01234567890123456789012345678901"); // for the test only var iv = utf8.encode("abcdefghijklmnop"); // for the test only var ct = hex.decode(ciphertext); var keyParam = KeyParameter(key); var params = ParametersWithIV(keyParam, iv); // Zero pad ciphertext var aesBlockSize = 16; var padLength = (aesBlockSize - (ct.length % aesBlockSize)) % aesBlockSize; var ctPadded = Uint8List(ct.length + padLength)..setAll(0, ct); // Decrypt var cipher = BlockCipher("AES/CFB-128"); cipher.init(false, params); var ptPadded = Uint8List(ctPadded.length); for (int offset = 0; offset < ctPadded.length;) { int len = cipher.processBlock(ctPadded, offset, ptPadded, offset); offset += len; } // Remove padding var pt = ptPadded.sublist(0, ct.length); return utf8.decode(pt); }


请注意,实际上应使用随机字节序列作为密钥。如果密钥材料是字符串,则应应用密钥派生函数(例如PBKDF2)。

由于密钥/IV 对的重用是一个漏洞,因此如果密钥是固定的,则应为每次加密使用随机 IV。 IV 不是秘密的,并且与密文一起传递(通常是串联的)。

© www.soinside.com 2019 - 2024. All rights reserved.