如何用C#的System.Security.Cryptography.DES复现Oracle DESEncrypt()
问题:用C#复现Oracle DBMS_OBFUSCATION_TOOLKIT.DESEncrypt的加密结果
我需要用C#复现一个遗留存储过程的加密输出(无法修改该存储过程),该过程内部使用DBMS_OBFUSCATION_TOOLKIT.DESEncrypt加密ASCII密码(确认仅含ASCII字符)。我的C#代码仅在输入字符串长度不超过8字节时,能与Oracle的输出结果一致。问题出在Oracle的DESEncrypt和我当前使用的System.Security.Cryptography.DES输出不同。
Oracle示例代码及预期输出
以下是演示Oracle加密行为的示例代码:
declare key raw(8); src raw(16); encrypted raw(16); begin key := UTL_RAW.cast_to_raw('MYCRYKEY'); src := utl_raw.cast_to_raw('123456789~~~~~~~'); encrypted := DBMS_OBFUSCATION_TOOLKIT.DESEncrypt( input => src, key => UTL_RAW.cast_to_raw('MYCRYKEY')); dbms_output.put_line('KEY = ' || key); dbms_output.put_line('SRC = ' || src); dbms_output.put_line('ENCRYPTED = ' || encrypted); end;
执行后输出的十六进制转储结果:
KEY = 4D594352594B4559 SRC = 3132333435363738397E7E7E7E7E7E7E ENCRYPTED = F2E238B83939CBC1C33331A198463076
C#测试代码及错误结果
我编写了NUnit测试用例尝试复现该结果:
static string ToHex(byte[] bytes) { return BitConverter.ToString(bytes).Replace("-", ""); } [Test] public void DESTest() { byte[] key = Encoding.ASCII.GetBytes("MYCRYKEY"); byte[] src = Encoding.ASCII.GetBytes("123456789~~~~~~~"); using DES des = DES.Create(); des.Key = key; des.Mode = CipherMode.ECB; des.Padding = PaddingMode.None; using ICryptoTransform crypt = des.CreateEncryptor(); byte[] encrypted = crypt.TransformFinalBlock(src, 0, src.Length); // 这两个断言通过 Assert.That(ToHex(key), Is.EqualTo("4D594352594B4559")); Assert.That(ToHex(src), Is.EqualTo("3132333435363738397E7E7E7E7E7E7E")); // 这个断言失败 Assert.That(ToHex(encrypted), Is.EqualTo("F2E238B83939CBC1C33331A198463076")); }
输入字节一致,但输出在第8字节后不同,断言失败提示:
String lengths are both 32. Strings differ at index 17. Expected: "F2E238B83939CBC1C33331A198463076" But was: "F2E238B83939CBC1C4388144A4F16DA6" ----------------------------^
我尝试了多种des.Mode和des.Padding组合,但结果更糟——当前设置至少能让短输入匹配,其他尝试连短输入都无法匹配。作为非加密领域专家,我想知道Oracle的DESEncrypt具体逻辑是什么?
内容的提问来源于stack exchange,提问作者Carlo Sirna
相关产品推荐
相关产品推荐

