.NET Core 3.1 Ubuntu环境下SecureString加密解密异常解决方案问询
问题根因
你当前遇到的报错是因为System.Security.Cryptography.ProtectedData底层完全依赖Windows专属的DPAPI(数据保护接口),本身不支持Linux、macOS等非Windows平台,因此在Ubuntu环境下运行直接抛出平台不支持异常。
适配跨平台的实现方案
这里提供两种.NET Core 3.1下可在Ubuntu运行的SecureString加密解密实现方案:
方案1:使用官方跨平台Data Protection API(推荐)
这是微软官方提供的替代DPAPI的跨平台方案,支持全平台运行,默认会根据操作系统自动适配对应的加密逻辑,也支持自定义密钥存储、有效期等配置。
- 首先安装对应NuGet包:
Install-Package Microsoft.AspNetCore.DataProtection
非ASP.NET项目也可正常引用该包。
2. 配置DataProtection实例,对应原CurrentUser scope可以将密钥存在当前用户目录下:
using Microsoft.AspNetCore.DataProtection; using System.Security; using System.Text; // 初始化DataProtectionProvider var dataProtectionProvider = DataProtectionProvider.Create( new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".your_app_name_secrets")), options => { options.SetApplicationName("your_app_unique_name"); }); var protector = dataProtectionProvider.CreateProtector("SecureStringEncryptionPurpose");
- 改写加密解密方法:
public static string EncryptString(SecureString input, IDataProtector protector) { // 将SecureString转为明文字节数组 var plainTextBytes = Encoding.Unicode.GetBytes(ToInsecureString(input)); // 加密 var encryptedBytes = protector.Protect(plainTextBytes); return Convert.ToBase64String(encryptedBytes); } public static SecureString DecryptString(string encryptedData, IDataProtector protector) { try { var encryptedBytes = Convert.FromBase64String(encryptedData); var decryptedBytes = protector.Unprotect(encryptedBytes); var plainText = Encoding.Unicode.GetString(decryptedBytes); // 清除内存中的明文字节数组,避免敏感信息残留 Array.Clear(decryptedBytes, 0, decryptedBytes.Length); return ToSecureString(plainText); } catch { return new SecureString(); } }
方案2:自定义AES对称加密实现
如果你不想引入ASP.NET相关依赖,可以自行实现AES对称加密,自行管理密钥和偏移量:
using System.Security.Cryptography; using System.Security; using System.Text; // 自行保管32位AES密钥和16位IV,生产环境不要硬编码,可通过环境变量、配置中心等方式读取 private static readonly byte[] AesKey = Encoding.UTF8.GetBytes("your_32_byte_aes_key_here_12345678"); private static readonly byte[] AesIV = Encoding.UTF8.GetBytes("your_16_byte_iv_"); public static string EncryptString(SecureString input) { var plainTextBytes = Encoding.Unicode.GetBytes(ToInsecureString(input)); using var aes = Aes.Create(); aes.Key = AesKey; aes.IV = AesIV; using var encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using var ms = new MemoryStream(); using var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write); cs.Write(plainTextBytes, 0, plainTextBytes.Length); cs.FlushFinalBlock(); var encryptedBytes = ms.ToArray(); Array.Clear(plainTextBytes, 0, plainTextBytes.Length); return Convert.ToBase64String(encryptedBytes); } public static SecureString DecryptString(string encryptedData) { try { var encryptedBytes = Convert.FromBase64String(encryptedData); using var aes = Aes.Create(); aes.Key = AesKey; aes.IV = AesIV; using var decryptor = aes.CreateDecryptor(aes.Key, aes.IV); using var ms = new MemoryStream(encryptedBytes); using var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read); using var reader = new StreamReader(cs, Encoding.Unicode); var plainText = reader.ReadToEnd(); return ToSecureString(plainText); } catch { return new SecureString(); } }
注意事项
- SecureString在非Windows平台下不会自动加密内存中的明文内容,仅能缩短明文在内存中的存活时间,无法实现Windows下的内存加密效果,如果你有更高的安全要求,建议在处理完明文后主动清空对应内存区域。
- 自定义AES方案的密钥需要妥善保管,避免密钥泄露导致敏感数据被破解。
内容的提问来源于stack exchange,提问作者Sk Azharuddin
相关产品推荐
相关产品推荐

