我正在尝试将当前通过存储过程发生的表插入替换为非常简单的Entity Framework命令。问题是数据以加密字符串的形式开始,然后在传递给存储过程之前变为HEX字符串。存储过程需要varbinary(50)
,并且可能只是简单地将HEX字符串转换为varbinary
。
我不能简单地将实体框架传递给HEX字符串 - 它知道它应该是byte[]
!
我无法弄清楚如何将十六进制字符串转换为byte[]
,这与SQL Server在后端的操作完全相同。
我已经确定了SQL Server使用的编码,并且能够将byte []转换回我开始使用的加密字符串:
System.Text.Encoding.GetEncoding("iso-8859-1").GetString(bytes)
是否存在实体框架技巧或其他一些选项,只是继续让SQL Server进行转换?我无法更改SQL Server中的数据类型,我宁愿不创建一个虚拟存储过程,只需接收一个字符串并返回varbinary
。
对于那些感兴趣的人,生成的示例十六进制字符串是0x1C3307260C18
。
出于本讨论的目的,如何生成此字符串并不重要 - 因为它是与安全性相关的代码,所以我无法发布创建它的确切过程。
我需要知道的是,一旦创建了这个字符串,我如何复制SQL Server使用C#将此字符串转换为varbinary
等效字符串的过程?顺便提一下,在SQL Server中查看表时,二进制数据以这种精确的十六进制形式呈现。因此,将字符串0x1C3307260C18
传递给SQL会导致它存储为varbinary
,并且它在查询中呈现完全相同的内容:0x1C3307260C18
。
答案 0 :(得分:0)
如果您可以通过Encoding.GetEncoding("iso-8859-1").GetString(bytes)
返回原始十六进制字符串,很明显原始代码实际上并不使用十六进制字符串的二进制表示 - 它只是转换文本到varbinary
!
这可能不是作者的意图。
但是,你可以通过反向做出完全相同的事情 - Encoding.GetEncoding("iso-8859-1").GetBytes(hexstring)
。
问题可能源于引用十六进制字符串 - 0x1C3307260C18
是完全正常的varbinary
值,但'0x1C3307260C18'
是varchar
- 转换为varbinary
时它只是使用字符串 - >字节转换规则进行转换(所以基本上只应用给定的编码)。
如果你想保留“错误的”代码,那就没问题了,并且SQL服务器做了同样的事情(假设服务器的内容对应于ISO-8859-1)。如果你想修复它并实际保存二进制字符串0x1C3307260C18
,你需要更难转换(或者只修复你的解密方法以返回byte[]
而不是string
: )):
Func<char, int> getHex = c =>
{
var p = c - '0';
if (p < 10) return p;
return (char.ToUpperInvariant(c) - 'A') + 10;
};
var hexString = "0x1C3307260C18";
if (!hexString.StartsWith("0x")) { return null; } // Fail in some way
var bytes = new byte[hexString.Length / 2 - 1];
for (int i = 0; i < bytes.Length; i++)
{
bytes[i] =
(byte)
(
(getHex(hexString[(i + 1) * 2]) << 4)
| getHex(hexString[(i + 1) * 2 + 1])
);
}
bytes.Select(i => i.ToString("X2")).Dump();
通常情况下,最好使用Convert.ToByte(str, 16)
,但对于像解析十六进制字符串这样简单的事情来说,执行这么多Substring
可能是浪费:)
当然,最后一行是在那里验证它是否有效;您还希望将getHex
函数设为方法,而不是将其保持匿名。根据您的要求,您可能希望添加附加错误检查 - 例如getHex
永远不应该返回到0-15范围之外等。