You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求AESCrypt-Android库的C#实现方案:适配空IV处理

在C#中复现AESCrypt-Android的加密行为(含空IV处理)

我特意翻了AESCrypt-Android的源码,找到了它的核心加密逻辑,帮你写了一套完全匹配的C#实现,解决你遇到的空IV问题——先说明下:AES-CBC模式要求IV必须是16字节,你说的“空IV”应该是指全0的16字节数组吧?下面是具体步骤和代码:

先搞懂AESCrypt-Android的关键细节

这个库的加密逻辑是固定的,最容易踩坑的几个点:

  • 加密模式:AES/CBC/PKCS7Padding
  • 密钥派生:用PBKDF2WithHmacSHA1,迭代1000次,生成256位密钥,盐是密码本身的UTF-8字节数组(很多其他库用随机盐,这是结果不匹配的核心原因!)
  • IV处理:默认生成随机16字节IV,然后把IV拼在密文最前面;如果自定义IV(包括全0的),必须是16字节,否则会抛异常

C# 实现代码

下面的代码完全对齐Android库的逻辑,支持自定义全0IV的场景:

核心加密解密类

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class AESCryptAndroidPort
{
    private const int IterationCount = 1000;
    private const int KeyBitSize = 256;
    private const int IvByteSize = 16; // AES块大小固定16字节,CBC模式IV必须和块大小一致

    // 派生密钥,完全匹配Android的PBKDF2WithHmacSHA1逻辑
    private static byte[] GetDerivedKey(string password)
    {
        byte[] passwordUtf8 = Encoding.UTF8.GetBytes(password);
        // 注意:盐就是密码的UTF8字节,这是AESCrypt-Android的特殊处理
        using var pbkdf2 = new Rfc2898DeriveBytes(password, passwordUtf8, IterationCount, HashAlgorithmName.SHA1);
        return pbkdf2.GetBytes(KeyBitSize / 8);
    }

    /// <summary>
    /// 加密数据,和AESCrypt-Android输出完全一致
    /// </summary>
    /// <param name="password">加密密码</param>
    /// <param name="plainData">明文字节数组</param>
    /// <param name="customIv">自定义IV(传null则生成随机IV,传全0数组就是你说的"空IV")</param>
    /// <returns>加密结果:IV + 密文(和Android库格式一致)</returns>
    public static byte[] Encrypt(string password, byte[] plainData, byte[] customIv = null)
    {
        byte[] key = GetDerivedKey(password);
        byte[] iv = customIv ?? GenerateRandomIv();

        if (iv.Length != IvByteSize)
        {
            throw new ArgumentException($"IV必须是{IvByteSize}字节长度", nameof(customIv));
        }

        using var aes = Aes.Create();
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        aes.Key = key;
        aes.IV = iv;

        using var ms = new MemoryStream();
        // 先写IV,和Android库一致,IV放在密文最前面
        ms.Write(iv, 0, iv.Length);

        using var cryptoStream = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write);
        cryptoStream.Write(plainData, 0, plainData.Length);
        cryptoStream.FlushFinalBlock();

        return ms.ToArray();
    }

    /// <summary>
    /// 解密数据,支持Android库加密的结果
    /// </summary>
    /// <param name="password">解密密码</param>
    /// <param name="encryptedData">加密后的数据(IV + 密文)</param>
    /// <returns>明文字节数组</returns>
    public static byte[] Decrypt(string password, byte[] encryptedData)
    {
        if (encryptedData.Length < IvByteSize)
        {
            throw new ArgumentException("加密数据长度不够,无法提取IV", nameof(encryptedData));
        }

        byte[] key = GetDerivedKey(password);
        // 提取前16字节作为IV
        byte[] iv = new byte[IvByteSize];
        Array.Copy(encryptedData, 0, iv, 0, IvByteSize);
        // 剩下的是密文
        byte[] ciphertext = new byte[encryptedData.Length - IvByteSize];
        Array.Copy(encryptedData, IvByteSize, ciphertext, 0, ciphertext.Length);

        using var aes = Aes.Create();
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        aes.Key = key;
        aes.IV = iv;

        using var ms = new MemoryStream();
        using var cryptoStream = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write);
        cryptoStream.Write(ciphertext, 0, ciphertext.Length);
        cryptoStream.FlushFinalBlock();

        return ms.ToArray();
    }

    // 生成随机IV,和Android库默认行为一致
    private static byte[] GenerateRandomIv()
    {
        byte[] iv = new byte[IvByteSize];
        using var rng = RandomNumberGenerator.Create();
        rng.GetBytes(iv);
        return iv;
    }
}

全0IV场景的使用示例

如果你在Android端用的是全0的IV,直接这么调用就行:

// 模拟你说的"空IV"——16个0字节的数组
byte[] emptyIv = new byte[16];
string yourPassword = "yourSecretPassword";
byte[] plainTextBytes = Encoding.UTF8.GetBytes("Hello from C#!");

// 加密
byte[] encrypted = AESCryptAndroidPort.Encrypt(yourPassword, plainTextBytes, emptyIv);

// 解密验证
byte[] decryptedBytes = AESCryptAndroidPort.Decrypt(yourPassword, encrypted);
string decryptedText = Encoding.UTF8.GetString(decryptedBytes);
// decryptedText应该等于"Hello from C#!"

避坑提醒

  1. 盐的处理:千万别忘了AESCrypt-Android用密码本身当盐,这和大多数标准加密实现不一样,是最容易导致结果不匹配的点。
  2. IV格式:Android库会把IV直接拼在密文前面,解密时必须先提取前16字节,不能直接用整个加密数据当密文。
  3. 填充模式:必须用PKCS7Padding,C#里的PaddingMode.PKCS7和Java的完全兼容。
  4. 密钥长度:默认是256位,现代.NET版本默认支持AES-256,不用额外配置。

内容的提问来源于stack exchange,提问作者Pecana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 20:17:31