API加密文档下载及解密异常问题咨询
需求与问题汇总
需求:从API获取加密文档,解密后保存为本地字符串,不使用Blob,仅通过临时缓存文件实现。计划流程:获取API返回的二进制文档数据 → 转换为字节数组 → 转为FileStream处理。
问题1:文件路径含非法字符异常
下载API数据的代码实现
private static byte[] data; public static byte[] Download(List<Document> documents) { Download download = new Download(); foreach (Document document in documents) { if (document.file_ != null) { using (var client = new RestClient(uri)) { try { RestRequest request = new RestRequest(document.file_, Method.Get); request.Timeout = -1; request.AddHeader("Content-Type_", "application/json"); var body = @"{ ""justices"": [ { ""number"": ""24303016000131"" } ] }"; request.AddParameter("application/json", body, ParameterType.RequestBody); RestResponse response = client.Execute(request); var ret = response.Content; data = ASCIIEncoding.UTF8.GetBytes(ret); download.binary = data; } catch (Exception ex) { throw ex; // 抛出异常:System.ArgumentException: 'Illegal characters in path. (Parameter 'path')' } } } } return download.binary; }
模型定义
public class Download { public byte[] binary { get; set; } }
字节数组转文件的代码及异常
调用以下方法时抛出异常:Message = Illegal characters in path. (Parameter 'path')
public static bool ByteArrayToFile(string fileName, byte[] byteArray) { try { using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) { fs.Write(byteArray, 0, byteArray.Length); return true; } } catch (Exception ex) { Console.WriteLine("Exception caught in process: {0}", ex); } return false; }
修复方案
- 修正请求Header的笔误:将
Content-Type_改为标准的Content-Type,避免API解析请求出错。 - 检查并修正文件路径:确保传入
ByteArrayToFile的fileName不含非法字符(如/ \ : * ? " < > |等),可通过Path.GetInvalidPathChars()识别并替换非法字符;推荐用Path.GetTempFileName()或Path.Combine(Path.GetTempPath(), "temp_doc.bin")生成合法临时文件路径,避免手动拼接出错。 - 正确获取二进制数据:若API返回的是二进制流,应直接使用
response.RawBytes获取字节数组,而非将response.Content(字符串)转ASCII字节数组——ASCII编码会丢失非ASCII字节数据,导致后续解密失败。
问题2:解密算法的密钥尺寸不合法异常
解密代码实现
调用该方法时抛出异常:System.Security.Cryptography.CryptographicException: 'Specified key is not a valid size for this algorithm.'
public static void Decrypt(byte[] downloadDoc) { if (downloadDoc == null) throw new ArgumentNullException(nameof(downloadDoc)); else if (downloadDoc.Length == 0) throw new ArgumentOutOfRangeException(nameof(downloadDoc)); BinaryFormatter formatter = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); formatter.Serialize(ms, downloadDoc); var rt = Convert.ToBase64String(ms.ToArray()); using (var rijndaelManaged = new RijndaelManaged()) { rijndaelManaged.KeySize = (rt.Length / 8) * 2; rijndaelManaged.Key = downloadDoc; rijndaelManaged.BlockSize = (rt.Length / 8) * 2; using (var decryptor = rijndaelManaged.CreateDecryptor()) using (var cryptoStream = new CryptoStream(ms, decryptor, CryptoStreamMode.Read)) { var decrypted = new byte[downloadDoc.Length]; var bytesRead = cryptoStream.Read(decrypted, 0, downloadDoc.Length); var ret = decrypted.Take(bytesRead).ToArray(); } } }
修复方案
- 遵循Rijndael尺寸规范:Rijndael的合法
KeySize为128/192/256位,BlockSize为128/192/256位,需确认API加密时使用的参数,设置对应合法值(如常用的256位密钥对应32字节),不能随意通过字符串长度计算。 - 区分加密文档与密钥:
downloadDoc是加密后的文档内容,不能直接作为解密密钥使用,需单独获取加密时使用的密钥(固定密钥或API返回的密钥参数),并将密钥转换为符合尺寸要求的字节数组。 - 移除冗余的序列化逻辑:
BinaryFormatter.Serialize序列化字节数组完全多余,直接使用原始downloadDoc即可,无需转Base64再计算尺寸。 - 修正MemoryStream指针位置:序列化后
ms的指针处于流末尾,需先调用ms.Seek(0, SeekOrigin.Begin)将指针移到开头,否则CryptoStream无法读取数据。
内容的提问来源于stack exchange,提问作者Caroline Sousa
相关产品推荐
相关产品推荐

